123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- import _ from 'lodash'
- import {invokeMethod} from "./utils"
- import {windows} from './Defaults'
- import {lookupScope} from "./lib/lib";
- import {scopeOnLoad} from './lib/config'
- export class Scope {
- /**
- * 业务模块的唯一编号
- */
- id = _.uniqueId('scope_')
- originalVjson
- /**
- * 一个 ExtJS 能接受的配置对象
- */
- vjson
- /**
- * 原始 vjsonModel 对象
- */
- model
- /**
- * 双向绑定的模型对象
- */
- viewModel
- /**
- * 构建完成之后的 Ext控件句柄
- */
- _handle
- /**
- * 与 watch 装饰器配合使用.
- * viewModel 属性更改时触发成员方法
- */
- _watchList
- /**
- * 页面显示的时候带的参数 在设计刷新的时候使用
- */
- _vjsonOption
- _dataOption
- /**
- * 最顶部的 scope 对象
- */
- topScope
- _addWatch(tplExpress, fn) {
- if (!this._watchList) {
- this._watchList = []
- }
- this._watchList.push({watch: tplExpress, fn})
- }
- _applyWatchList() {
- _.forEach(this._watchList, item => {
- this.viewModel.bind(item.watch, item.fn.bind(this))
- })
- }
- get isScope() {
- return true;
- }
- /**
- * 产生一个当前模块有效的唯一id
- * @param key 唯一编号
- */
- uid(key) {
- return this.id + key
- }
- /**
- * 对话框"保存"成功.
- * 关闭对话框,并响应 success 方法
- * @param data 要傳回的數據(可以為空)
- */
- dialogSuccess(data?) {
- this._handle.fireEvent('success', this, data)
- const sender = this._handle.config.animateTarget
- const scope = lookupScope(sender)
- if (typeof this['success'] === 'function') {
- this['success'].call(scope, sender, data)
- }
- this.close()
- }
- /**
- * 设置等待状态
- * @param value
- * @param msg
- */
- setLoading(value: boolean) {
- const scope = this
- scope._handle?.setLoading(value)
- }
- /**
- * 以对话框模式打开当前模块
- * @param sender 发送者(按钮或Scope对象)
- * @param vjsonOption 界面覆盖选项(可以为空)
- * @param dataOption 数据覆盖选项(可以为空)
- */
- showDialog(sender, vjsonOption, dataOption) {
- const that = this
- const vmodel = _.defaultsDeep({
- //
- }, dataOption, that.model)
- this.viewModel = new Ext.app.ViewModel(vmodel);
- this.viewModel.yvanScope = this
- this._applyWatchList()
- this["scopeKey"] = "dialog-" + getVjsonHash(JSON.stringify(this.vjson) + JSON.stringify(vjsonOption))
- const config = _.defaultsDeep({
- animateTarget: sender,
- viewModel: this.viewModel,
- yvanScope: this,
- referenceHolder: true,
- }, vjsonOption, that.vjson, windows)
- if (config.height === 'unset') {
- delete config.height
- }
- if (config.width === 'unset') {
- delete config.width
- }
- // const holder = sender?.lookupReferenceHolder()
- // delete config.constrain
- const topScope = lookupScope(sender)?.topScope
- if (topScope) {
- config.constrain = true
- this.topScope = topScope
- }
- const win = new Ext.Window(config);
- // if (holder) {
- // holder.add(win)
- // }
- if (topScope) {
- topScope._handle.add(win)
- }
- win.addListener('beforerender', function (sender) {
- // 记录句柄
- if (sender && !that._handle) {
- that._handle = sender
- }
- })
- win.addListener('afterrender', function (sender) {
- // 调用onLoad回调
- try {
- that.onLoad()
- } catch (e) {
- console.error('errorAt onLoad', e)
- }
- })
- win.addListener('destroy', this._destroy.bind(this))
- win.show();
- }
- /**
- * 以标签模式打开当前模块
- * @param vjsonOption 界面覆盖选项(可以为空)
- * @param dataOption 数据覆盖选项(可以为空)
- */
- showPage(vjsonOption, dataOption) {
- const that = this
- this._vjsonOption = vjsonOption;
- this._dataOption = dataOption;
- const vmodel = _.defaultsDeep({
- data: {}
- }, that.model, dataOption)
- this.viewModel = new Ext.app.ViewModel(vmodel);
- this.viewModel.yvanScope = this
- this._applyWatchList()
- this["scopeKey"] = "page-" + getVjsonHash(JSON.stringify(this.vjson) + JSON.stringify(vjsonOption))
- // 根级不能设置id
- delete that.vjson.id
- const config = _.defaultsDeep({
- viewModel: this.viewModel,
- yvanScope: this,
- referenceHolder: true,
- }, vjsonOption, that.vjson)
- const tt = Ext.getCmp('TT')
- const handle = tt.addScope(this, config, (handle) => {
- handle.addListener('added', function (sender) {
- // 记录句柄
- if (sender && !that._handle) {
- that._handle = sender
- }
- })
- handle.addListener('afterrender', function (sender) {
- // 调用onLoad回调
- try {
- that.onLoad()
- } catch (e) {
- console.error('errorAt onLoad', e)
- }
- })
- handle.addListener('destroy', this._destroy.bind(this))
- })
- return handle
- }
- /**
- * 直接渲染到元素
- * @param element 渲染目标
- * @param vjsonOption 界面覆盖选项(可以为空)
- * @param dataOption 数据覆盖选项(可以为空)
- */
- renderTo(element, vjsonOption, dataOption) {
- const that = this
- this._vjsonOption = vjsonOption;
- this._dataOption = dataOption;
- const vmodel = _.defaultsDeep({
- data: {}
- }, that.model, dataOption)
- this["scopeKey"] = "render-" + getVjsonHash(JSON.stringify(this.vjson) + JSON.stringify(vjsonOption))
- this.viewModel = new Ext.app.ViewModel(vmodel);
- this.viewModel.yvanScope = this
- this._applyWatchList()
- const config = _.defaultsDeep({
- viewModel: this.viewModel,
- yvanScope: this,
- referenceHolder: true,
- renderTo: element,
- listeners: {
- afterrender(sender) {
- // 记录句柄
- if (sender && !that._handle) {
- that._handle = sender
- }
- // 调用onLoad回调
- try {
- that.onLoad()
- } catch (e) {
- console.error('errorAt onLoad', e)
- }
- // 如果vjson中配置了 afterrender ,需要恢复状态
- invokeMethod(that.vjson.listeners?.afterrender, that, arguments)
- },
- },
- }, vjsonOption, that.vjson)
- new Ext.container.Viewport(config);
- }
- /**
- * 关闭对话框(或标签页)
- */
- close() {
- this._handle.close()
- }
- /**
- * 获取 viewModel 里包含的数据(只读)
- */
- get data() {
- return this.viewModel.getData()
- }
- /**
- * 设置 viewModel 中的数据
- * 可以是 key, value 模式
- * 也可以是 {key:value} 模式
- */
- set(path, value) {
- return this.viewModel.set(path, value)
- }
- /**
- * 寻找模块内所有的 xtype 对应的对象
- * @param xtypeKey
- */
- down(xtypeKey) {
- return this._handle.down(xtypeKey)
- }
- /**
- * 获取所有设置过 Reference 名称的组件
- */
- get refs() {
- return this._handle.getReferences()
- }
- _destroy() {
- const that = this
- that.onDestroy()
- delete that._watchList
- delete that._handle
- }
- constructor({model, vjson}) {
- const that = this
- this.model = model
- this.originalVjson = _.cloneDeep(vjson)
- this.vjson = this.originalVjson // this.buildVjson()
- }
- /**
- * 模块载入完成之后的回调
- */
- onLoad() {
- if (scopeOnLoad && typeof scopeOnLoad === 'function') {
- scopeOnLoad(this)
- }
- }
- /**
- * 组件卸载之后的回调
- */
- onDestroy() {
- }
- }
- /**
- * 观察装饰器,viewModel 属性更改时触发成员方法
- * @param tplExpress tpl表达式,例如 "{form.f1}"
- */
- export function watch(tplExpress, deep = false) {
- return function (target, propertyKey, pd) {
- target._addWatch({bindTo: tplExpress, deep}, target[propertyKey])
- return target[propertyKey]
- }
- }
- // 获取vjson的hash值
- function getVjsonHash(str: string): string {
- let hash = 3465217896,i,ch;
- for (i = str.length - 1; i >= 0; i--) {
- ch = str.charCodeAt(i);
- hash ^= ((hash << 5) + ch + (hash >> 2));
- }
- return (hash & 0x7FFFFFFF) + "";
- }
|