luoyifan hace 3 años
padre
commit
9889c44ed6
Se han modificado 10 ficheros con 258 adiciones y 68 borrados
  1. 3 3
      src/Scope.ts
  2. 13 0
      src/controls/component.js
  3. 16 7
      src/controls/grid.js
  4. 10 1
      src/init.ts
  5. 0 12
      src/lib/ajax.ts
  6. 11 39
      src/lib/config.ts
  7. 20 2
      src/lib/lib.ts
  8. 180 0
      src/lib/systemLib.ts
  9. 3 3
      src/types.ts
  10. 2 1
      src/utils.ts

+ 3 - 3
src/Scope.ts

@@ -75,7 +75,7 @@ export class Scope {
 
         const vmodel = _.defaultsDeep({
             data: {}
-        }, dataOption, that.model)
+        }, that.model, dataOption)
 
         this.viewModel = new Ext.app.ViewModel(vmodel);
         this.viewModel.yvanScope = this
@@ -131,7 +131,7 @@ export class Scope {
         this._dataOption = dataOption;
         const vmodel = _.defaultsDeep({
             data: {}
-        }, dataOption, that.model)
+        }, that.model, dataOption)
 
         this.viewModel = new Ext.app.ViewModel(vmodel);
         this.viewModel.yvanScope = this
@@ -178,7 +178,7 @@ export class Scope {
         this._dataOption = dataOption;
         const vmodel = _.defaultsDeep({
             data: {}
-        }, dataOption, that.model)
+        }, that.model, dataOption)
 
         this.viewModel = new Ext.app.ViewModel(vmodel);
         this.viewModel.yvanScope = this

+ 13 - 0
src/controls/component.js

@@ -0,0 +1,13 @@
+import _ from 'lodash'
+import {componentConfigProcess} from "../lib/config";
+
+export default function () {
+    const ct = Ext.Component.prototype.constructor
+    Ext.Component.override({
+        constructor: function (config) {
+            const newConfig = _.cloneDeep(config)
+            componentConfigProcess(this, newConfig)
+            ct.call(this, newConfig)
+        }
+    });
+}

+ 16 - 7
src/controls/grid.js

@@ -23,11 +23,11 @@ export default function () {
                 {
                     xtype: 'button',
                     tooltip: '导出Excel',
-                    iconCls: 'x-fa fa-file-excel-o'
+                    iconCls: 'x-fa fa-download'
                 },
                 {
                     xtype: 'button',
-                    iconCls: 'x-fa fa-columns',
+                    iconCls: 'x-fa fa-text-width',
                     tooltip: '自适应宽度',
                     listeners: {
                         click: this.autoSizeColumns
@@ -177,18 +177,27 @@ export default function () {
             this.on({
                 afterrender(sender) {
                     const {config} = this
+                    const {dataSource} = config
+
                     if (config.autoLoad) {
                         if (config.dataSourceCallbackFn) {
                             me.reload()
-                            return
-                        }
 
-                        const {dataSource} = config
-                        if (_.isPlainObject(dataSource) && dataSource.method === 'invoke') {
+                        } else if (_.isPlainObject(dataSource) && dataSource.method === 'invoke') {
                             me.reload()
-                            return
                         }
                     }
+
+                    if (config.contextMenu) {
+                        this.contextMenu = this.add(config.contextMenu)
+                    }
+                },
+                itemcontextmenu(view, rec, node, index, e) {
+                    if (this.contextMenu) {
+                        e.stopEvent();
+                        this.contextMenu.show().setLocalXY(e.getXY());
+                        return false;
+                    }
                 },
                 destory() {
                 },

+ 10 - 1
src/init.ts

@@ -1,4 +1,5 @@
 import _ from 'lodash'
+import initComponent from './controls/component'
 import initMainTab from './controls/MainTab'
 import initPanel from './controls/panel'
 import initGrid from './controls/grid'
@@ -13,7 +14,8 @@ import initRows from './controls/rows'
 import initCols from './controls/cols'
 import initButton from './controls/button'
 import initStores from './controls/stores'
-import {lookupFn, lookupScope} from "./lib/lib";
+import {lookupFn, lookupScope} from "./lib/lib"
+import * as SystemLib from './lib/systemLib'
 
 export function init() {
     // 引入 filters 过滤插件
@@ -86,6 +88,13 @@ export function init() {
         _doAddListener.call(this, ename, fn, scope, options, order, caller, manager)
     }
 
+    // 将 SystemLib 扩展到 window.system 下
+    if (!window['system']) {
+        window['system'] = {}
+    }
+    _.extend(window, SystemLib)
+
+    initComponent()
     initPanel()
     initGrid()
     initMainTab()

+ 0 - 12
src/lib/ajax.ts

@@ -18,18 +18,6 @@ export type ApiMethod =
 
 export type ApiDataType = 'json' | 'form-data' | 'form'
 
-/**
- * 调用服务器 Ajax
- */
-export function invokeServer(url: string, ...args: any[]) {
-    // @ts-ignore
-    return ajax.func({
-        url: url,
-        method: 'invoke',
-        args: args
-    })
-}
-
 export interface ApiObject {
     url: string
     param: PlainObject

+ 11 - 39
src/lib/config.ts

@@ -1,4 +1,4 @@
-import {VJson, VJsonProcess} from "../types";
+import {VJsonProcess} from "../types";
 import {ApiFunction} from "./ajax";
 import _ from 'lodash'
 
@@ -17,11 +17,6 @@ export interface ConfigOption {
     designMode: boolean
 
     /**
-     * 扩展自定义的 vjson 运行时 修改
-     */
-    beforeResolverVJson: (module: any, vJson: VJson) => VJson;
-
-    /**
      * 扩展自定义的 ajax 方法
      */
     ajax: ApiFunction;
@@ -37,34 +32,12 @@ export interface ConfigOption {
     sqlUrlTransform: SqlUrlTransformFunction;
 
     /**
-     * 组件渲染过滤器, 如果方法返回 false 代表该组件不需要被渲染.
-     * 可以修改 vjson 的内容,但不能删除他
-     */
-    componentRenderFilter: (vjson: any) => undefined | boolean
-
-    /**
      * 获取拼音首字母的函数
      */
     pinyinFunction: (py: string) => string
-
-    /**
-     * 需要添加的 VJsonProcess 处理过程
-     */
-    vjsonProcess: VJsonProcess
 }
 
 /**
- * 全局 vjson 运行时
- */
-export let beforeResolverVJson: (undefined | ((module: any, vJson: VJson) => VJson)) = undefined;
-
-/**
- * 组件渲染过滤器, 如果方法返回 false 代表该组件不需要被渲染.
- * 可以修改 vjson 的内容,但不能删除他
- */
-export let componentRenderFilter: (undefined | ((vjson: any) => undefined | boolean)) = undefined;
-
-/**
  * 全局 ajax 方法
  */
 export const ajax: {
@@ -114,10 +87,6 @@ export function sqlUrlTransform(url: string): string {
  * YvanUI 全局扩展配置
  */
 export function extend(option: Partial<ConfigOption>) {
-    if (option.beforeResolverVJson) {
-        beforeResolverVJson = option.beforeResolverVJson
-    }
-
     if (option.ajax) {
         ajax.func = option.ajax
     }
@@ -130,10 +99,6 @@ export function extend(option: Partial<ConfigOption>) {
         _.extend(window, {_YvanUI_sqlPrefix: option.sqlUrlTransform});
     }
 
-    if (option.componentRenderFilter) {
-        componentRenderFilter = option.componentRenderFilter
-    }
-
     if (option.pinyinFunction) {
         pinyinFunc = option.pinyinFunction
     }
@@ -141,8 +106,15 @@ export function extend(option: Partial<ConfigOption>) {
     if (typeof option.designMode !== 'undefined') {
         setDesignMode(option.designMode)
     }
+}
 
-    if (option.vjsonProcess) {
-        pushVJsonProcess(option.vjsonProcess)
-    }
+/**
+ * 任意组件 Ext.Component 构造时调用的方法, 可以用来在渲染之前加工处理 VJSON
+ * @param me
+ * @param config
+ */
+export function componentConfigProcess(me, config) {
+    _.each(vjsonProcessChain, process => {
+        process(me, config)
+    })
 }

+ 20 - 2
src/lib/lib.ts

@@ -1,6 +1,7 @@
 import _ from 'lodash'
-import {FunctionRegiste} from "../types";
-import {Scope} from "../Scope";
+import {FunctionRegiste, VJsonProcess} from "../types"
+import {Scope} from "../Scope"
+import {pushVJsonProcess} from '../lib/config'
 
 export const LibList: FunctionRegiste[] = []
 
@@ -17,6 +18,11 @@ export function Lib(registe: FunctionRegiste) {
 
         } else if (registe.type === 'format') {
             _.set(window, 'yvanLib.format.' + propertyKey, target[propertyKey])
+
+        } else if (registe.type === 'mixins') {
+            // 混入方法,在每个组件初始化的时候,都会调用 mixins 混入方法
+            // 混入方法可以对 vjson 进行修改
+            pushVJsonProcess(registe.target as VJsonProcess)
         }
 
         return target
@@ -51,4 +57,16 @@ export function lookupFn(scope: Scope, event: string): Function {
 export function lookupScope(extHandle: any): Scope {
     const vm = extHandle.lookupViewModel()
     return vm.yvanScope
+}
+
+export function getClassName(me) {
+    return me.$className
+}
+
+/**
+ * 用于任意组件 Ext.Component 构造时,获取当前组件对应的表格(如果不是 grid.columns 对象就会返回 undefined)
+ * @param config 组件构造函数传入的 config 配置文件
+ */
+export function getParentGrid(config) {
+    return config.$initParent?.grid
 }

+ 180 - 0
src/lib/systemLib.ts

@@ -1,3 +1,7 @@
+import _ from 'lodash'
+import {Lib, lookupScope} from './lib'
+import {ajax} from "./config";
+
 /**
  * 对某个表达式进行求值
  * @param viewModel 数据对象
@@ -64,4 +68,180 @@ export function calcObject(viewModel, paramObject) {
             viewModel,
             {single: true})
     })
+}
+
+/**
+ * 调用服务器 Ajax
+ */
+export function invokeServer(url: string, ...args: any[]) {
+    // @ts-ignore
+    return ajax.func({
+        url: url,
+        method: 'invoke',
+        args: args
+    })
+}
+
+export function clearViewModelValues(viewModel, propertyName) {
+    const dd = _.get(viewModel.getData(), propertyName)
+    _.forOwn(dd, (value, key) => {
+        viewModel.set(propertyName + '.' + key, '')
+    })
+}
+
+export function reloadGrid(scope, gridRefName) {
+    scope.refs[gridRefName]?.reload()
+}
+
+/**
+ * 将 Ext.data.Model 对象 (及子属性) 转换为 js.object 对象
+ */
+export function toPlainObject(obj) {
+    if (obj.isModel) {
+        obj = obj.data
+    }
+    _.forOwn(obj, (v, k) => {
+        // Ext.data.Model.constructor
+        if (!v) {
+            return
+        }
+
+        if (v.isModel) {
+            v = v.data
+        }
+
+        if (typeof v === 'object') {
+            obj[k] = toPlainObject(v)
+        } else {
+            obj[k] = v
+        }
+    })
+    return obj
+}
+
+class SystemEventFu {
+
+    @Lib({
+        title: '清空 viewModel 某个属性',
+        author: '罗一帆',
+        createAt: '2021-07-02',
+        updateAt: '2021-07-02',
+        type: 'system',
+        category: '表单',
+        args: [
+            {
+                type: 'viewModel',
+                title: 'propertyName 属性路径',
+                name: 'propertyName',
+            }
+        ]
+    })
+    clearViewModelValues(propertyName: string) {
+        return function (sender) {
+            const scope = lookupScope(sender)
+            clearViewModelValues(scope.viewModel, propertyName)
+        }
+    }
+
+    @Lib({
+        title: '清空 viewModel 某个属性,并刷新表格',
+        author: '罗一帆',
+        createAt: '2021-07-02',
+        updateAt: '2021-07-02',
+        type: 'system',
+        category: '表单',
+        args: [
+            {
+                type: 'viewModel',
+                title: 'propertyName 属性路径',
+                name: 'propertyName',
+            },
+            {
+                type: 'refs',
+                title: 'gridRef 表格引用名',
+                allowEmpty: true,
+                name: 'gridRefName',
+            }
+        ]
+    })
+    clearViewModelReloadGrid(propertyName: string, gridRefName?: string) {
+        return function (sender) {
+            const scope = lookupScope(sender)
+            clearViewModelValues(scope.viewModel, propertyName)
+            if (!gridRefName) {
+                scope.down('grid')?.reload()
+
+            } else {
+                scope.refs[gridRefName]?.reload()
+            }
+        }
+    }
+
+    @Lib({
+        title: '刷新表格',
+        author: '罗一帆',
+        createAt: '2021-07-02',
+        updateAt: '2021-07-02',
+        type: 'system',
+        category: '表单',
+        args: [
+            {
+                type: 'refs',
+                title: 'gridRef 表格引用名, 不填写的情况下刷新所有',
+                allowEmpty: true,
+                name: 'gridRefName',
+            }
+        ]
+    })
+    reloadGrid(gridRefName: string) {
+        return function (sender) {
+            const scope = lookupScope(sender)
+            if (!gridRefName) {
+                scope.down('grid')?.reload()
+
+            } else {
+                scope.refs[gridRefName]?.reload()
+            }
+        }
+    }
+
+    @Lib({
+        title: '显示对话框',
+        author: '罗一帆',
+        createAt: '2021-07-02',
+        updateAt: '2021-07-02',
+        type: 'system',
+        category: '对话框',
+        args: [
+            {
+                type: 'module',
+                title: '业务模块名',
+                name: 'url',
+            },
+            {
+                type: 'object',
+                title: '参数数据',
+                name: 'dataParam',
+                allowEmpty: true,
+            }
+        ]
+    })
+    showDialog(url: string, dataParam: any) {
+        return function (sender) {
+            const scope = lookupScope(sender)
+
+            calcObject(scope.viewModel, dataParam).then((param) => {
+
+                // 从 Ext.data.Model 对象转换为 js-object 对象
+                param = toPlainObject(param)
+
+                // @ts-ignore
+                require([url], (module) => {
+                    const ScopeClass = module.default
+                    const scope = new ScopeClass()
+                    scope.showDialog(sender, {}, {data: param})
+                })
+            })
+        }
+    }
 }

+ 3 - 3
src/types.ts

@@ -12,7 +12,7 @@ export interface VJson {
  * @param vjson 是待处理的 VJson 对象
  * @result 返回处理 VJson 的 Promise 异步结果
  */
-export type VJsonProcess = (this: any, vjson: VJson) => Promise<VJson>
+export type VJsonProcess = (me, config) => boolean
 
 /**
  * 注册函数中的参数
@@ -36,7 +36,7 @@ export interface FunctionArgument {
     /**
      * 是否允许为空
      */
-    allowEmpty: boolean
+    allowEmpty?: boolean
 
     /**
      * 过滤器
@@ -86,7 +86,7 @@ export interface FunctionRegiste {
      * ajaxMethod: AjaxMethod
      * meta: 元数据
      */
-    type: 'system' | 'format' | 'ajaxMethod' | 'meta'
+    type: 'system' | 'format' | 'mixins' | 'ajaxMethod' | 'meta'
 
     /**
      * 分类名称

+ 2 - 1
src/utils.ts

@@ -18,4 +18,5 @@ export function stopEvent(e) {
     window.event.cancelBubble = true
     e.returnValue = false;
     e.cancelBubble = true;
-}
+}
+