Explorar o código

watch / maintab contextmenu

luoyifan %!s(int64=4) %!d(string=hai) anos
pai
achega
093ce8b466
Modificáronse 3 ficheiros con 103 adicións e 1 borrados
  1. 68 1
      src/Scope.ts
  2. 20 0
      src/controls/MainTab.js
  3. 15 0
      src/init.ts

+ 68 - 1
src/Scope.ts

@@ -9,6 +9,11 @@ export class Scope {
     id = _.uniqueId('scope_')
 
     /**
+     * 模块文件路径(可以为空)
+     */
+    path
+
+    /**
      * 一个 ExtJS 能接受的配置对象
      */
     config
@@ -23,9 +28,29 @@ export class Scope {
      */
     _handle
 
+    /**
+     * 与 Watch 装饰器配合使用.
+     * viewModel 属性更改时触发成员方法
+     */
+    _watchList
+
+    _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))
+        })
+    }
+
     constructor({model, vjson}) {
         this.viewModel = new Ext.app.ViewModel(model);
         this.viewModel.yvanScope = this
+        this._applyWatchList()
 
         const that = this
         this.config = _.defaultsDeep({
@@ -33,21 +58,35 @@ export class Scope {
             listeners: {
                 added(sender) {
                     // 记录句柄
-                    that._handle = sender
+                    if (sender && !that._handle) {
+                        that._handle = sender
+                    }
                     // 调用onLoad回调
                     that.onLoad()
+
                     // 如果vjson中配置了 afterrender ,需要恢复状态
                     invokeMethod(vjson.listeners?.added, that, arguments)
                 },
                 afterrender(sender) {
+                    // 记录句柄
+                    if (sender && !that._handle) {
+                        that._handle = sender
+                    }
+
                     // 调用 onRender 回调
                     that.onRender()
+
                     // 如果vjson中配置了 afterrender ,需要恢复状态
                     invokeMethod(vjson.listeners?.afterrender, that, arguments)
                 },
                 activate(sender) {
                     // 调用 onActivate 回调
                     that.onActivate()
+
+                    const vm = sender.lookupViewModel()
+                    if (vm) {
+                        window['currentScope'] = sender.lookupViewModel().yvanScope
+                    }
                     // 如果vjson中配置了 afterrender ,需要恢复状态
                     invokeMethod(vjson.listeners?.activate, that, arguments)
                 },
@@ -72,16 +111,33 @@ export class Scope {
                 destroy(sender) {
                     // 调用 onActivate 回调
                     that.onDestroy()
+
+                    // 销毁 viewModel
+                    that.viewModel.destroy()
+                    delete that.viewModel
+                    delete that.config
+                    delete that._watchList
+                    delete that._handle
+
                     // 如果vjson中配置了 afterrender ,需要恢复状态
                     invokeMethod(vjson.listeners?.destroy, that, arguments)
                 },
             },
             yvanScope: this,
             viewModel: this.viewModel,
+            referenceHolder: true,
+
         }, vjson)
     }
 
     /**
+     * 获取所有设置过 Reference 名称的组件
+     */
+    get refs() {
+        return this._handle.getReferences()
+    }
+
+    /**
      * 模块载入完成之后的回调
      */
     onLoad() {
@@ -130,4 +186,15 @@ export class Scope {
     uid(key) {
         return this.id + key
     }
+}
+
+/**
+ * 观察装饰器,viewModel 属性更改时触发成员方法
+ * @param tplExpress tpl表达式,例如 "{form.f1}"
+ */
+export function watch(tplExpress) {
+    return function (target, propertyKey, pd) {
+        target._addWatch(tplExpress, target[propertyKey])
+        return target[propertyKey]
+    }
 }

+ 20 - 0
src/controls/MainTab.js

@@ -7,6 +7,12 @@ export default function () {
         extend: 'Ext.tab.Panel',
         xtype: 'maintab',
 
+        plugins: Ext.create('Ext.ux.TabCloseMenu', {
+            closeTabText: '关闭',
+            closeOthersTabsText: '关闭其他',
+            closeAllTabsText: '关闭所有'
+        }),
+
         constructor(config) {
             const self = this
             const newConfig = _.defaultsDeep({}, config, {
@@ -31,7 +37,21 @@ export default function () {
          * @param scopeInstance 业务对象实例
          */
         addScope(scopeInstance) {
+            if (scopeInstance.path) {
+                for (let i = 0; i < this.items.items.length; i++) {
+                    // 找到当前 tabs 里有没有已经打开过
+                    const tab = this.items.items[i]
+                    if (_.isEqual(tab.uuid, scopeInstance.path)) {
+                        // 激活
+                        this.setActiveTab(tab);
+                        return
+                    }
+                }
+            }
+
+            // 添加业务模块
             this.add({
+                uuid: scopeInstance.path,
                 closable: true,
                 ...scopeInstance.config,
             })

+ 15 - 0
src/init.ts

@@ -49,5 +49,20 @@ export function init() {
         _doAddListener.call(this, ename, fn, scope, options, order, caller, manager)
     }
 
+    /**
+     * 改变必填项之前加星号
+     */
+    const t1 = Ext.form.field.Text.prototype.initComponent
+    Ext.form.field.Text.override({
+        initComponent: function () {
+            if (this.allowBlank === false || this.validateBlank === true) {
+                this.beforeLabelTextTpl = [
+                    '<span style="color:red;font-weight:bold" data-qtip="必填选项">*</span>'
+                ];
+            }
+            t1.call(this)
+        }
+    });
+
     initMainTab()
 }