Browse Source

Merge remote-tracking branch 'origin/master'

liuzhuang 3 years ago
parent
commit
e0e64724c4
5 changed files with 207 additions and 33 deletions
  1. 3 2
      src/Scope.ts
  2. 9 10
      src/controls/input/search.js
  3. 6 0
      src/controls/input/textfield.js
  4. 188 20
      src/lib/systemLib.ts
  5. 1 1
      src/types.ts

+ 3 - 2
src/Scope.ts

@@ -74,8 +74,9 @@ export class Scope {
         const that = this
 
         const vmodel = _.defaultsDeep({
-            data: {}
-        }, that.model, dataOption)
+            //
+
+        }, dataOption, that.model)
 
         this.viewModel = new Ext.app.ViewModel(vmodel);
         this.viewModel.yvanScope = this

+ 9 - 10
src/controls/input/search.js

@@ -2,7 +2,8 @@ import _ from 'lodash'
 import {baseConfig} from "../base";
 import {search} from "../../Defaults";
 import {invokeMethod, stopEvent} from "../../utils";
-import {lookupScope} from "../../lib/lib";
+import {lookupScope} from "../../lib/lib"
+import {calcObjectFlat,tryWriteByExpress} from "../../lib/systemLib"
 
 export default function () {
 
@@ -78,11 +79,10 @@ export default function () {
                 widgetScope = new WidgetScopeClass()
 
                 const rawValue = this.getRawValue()
-                const widgetDialogData = {
-                    queryKeyword: rawValue
-                }
+
+                // 传递进 widget.model 的数据
+                const widgetDialogData = calcObjectFlat({queryValue: rawValue, ...parentScope.viewModel.data}, lookup)
                 widgetScope.parentScope = parentScope
-                widgetScope.queryKeyword = rawValue
                 widgetScope.searchWidgetSuccess = (data) => {
                     if (typeof lookup === 'string') {
                         // lookup 是字符串的情况下,就是取某个列作为 value 值
@@ -92,17 +92,16 @@ export default function () {
 
                     /**
                      * lookup: {
-                     *   // 自己本身的值做更改
-                     *   "value": 'PRODNAME',
-
                      *   // 扩展到 viewModel 的值做更改
-                     *   "query.PRODID": "PRODID",
-                     *   "query.PRODNAME": "PRODNAME",
+                     *   WH_CODE: "{queryValue}",
+                     *   WH_NAME: "{query.WH_NAME}",
                      * }
                      */
                     if (_.isPlainObject(lookup)) {
                         const parentScope = lookupScope(sender)
 
+                        tryWriteByExpress(parentScope.viewModel, )
+
                         _.forOwn(lookup, (value, key) => {
                             if (!key || key === 'value') {
                                 me.setValue(data[value])

+ 6 - 0
src/controls/input/textfield.js

@@ -46,6 +46,12 @@ export default function () {
             const me = this
             this.on({
                 change(sender, newVal) {
+                    const {hideTrigger, disabled, readonly} = sender
+                    if (hideTrigger || disabled || readonly) {
+                        // 禁用、隐藏、只读状态下,不需要显示清空按钮
+                        return
+                    }
+
                     const value = newVal
 
                     if (value) {

+ 188 - 20
src/lib/systemLib.ts

@@ -4,29 +4,197 @@ import {ajax} from "./config";
 
 /**
  * 对某个表达式进行求值
- * @param viewModel 数据对象
- * @param express
+ * a:{query.a},b:{query.b} -> a:aValue,b:bValue
+ *
+ * @example
+ * calcExpress(cc.viewModel.data, "WH_ID:{query.WH_ID},C:{theGrid.selection.data.WH_ID}")
+ * 计算出来的值是: "WH_ID:queryWhId,C:JH000000001"
+ *
+ * @param data 数据环境对象
+ * @param express 表达式对象
+ */
+export function calcExpress(data, express) {
+    let result = express
+
+    while (true) {
+        const mlist = result.match(/{(.*?)}/)
+        if (!mlist) {
+            break
+        }
+
+        const pathC = mlist[0]  // {query.a}
+        const path = mlist[1]  // query.a
+
+        let value = _.get(data, path)
+        result = result.replaceAll(pathC, value || '')
+    }
+
+    return result
+}
+
+/**
+ * 对个对象进行表达式求值,不用回调
+ * @example
+ * calcObjectFlat({query:{a:'aValue',b1:'b1Value',b2:'b2Value',d1:1,d2:2}}, { a:'{query.a}', b:{b1:'{query.b1}', b2:'{query.b2}'},c:'aa',d:['{query.d1}','{query.d2}'] })
+ *
+ * {
+ *     a: '{query.a}',
+ *     b: {
+ *         b1: '{query.b1}',
+ *         b2: '{query.b2}',
+ *     },
+ *     c: 'aa',
+ *     d: [
+ *         '{query.d1}',
+ *         '{query.d2}'
+ *     ]
+ * }
+ *
+ * 计算结果为
+ * {
+ *     a: 'aValue',
+ *     b: {
+ *         b1: 'b1Value',
+ *         b2: 'b2Value'
+ *     },
+ *     c: 'aa'
+ *     d: [
+ *         '1',
+ *         '2'
+ *     ]
+ * }
+ *
+ * @param data
+ * @param paramObject
  */
-export function tplExpress(viewModel, express) {
-    if (viewModel.expressionRe.test(express)) {
+export function calcObjectFlat(data, paramObject) {
+    const result = _.cloneDeep(paramObject)
+
+    const trav = (param) => {
+        _.forOwn(param, (value, key) => {
+            if (_.isPlainObject(value)) {
+                // 深度递归,对子对象进行求解
+                trav(value)
+
+            } else if (_.isString(value)) {
+                // 字符串直接用 calcExpress 表达式求解
+                param[key] = calcExpress(data, param[key])
+
+            } else if (_.isArray(value)) {
+                // 数组求解
+                _.each(value, (v, idx) => {
+                    value[idx] = calcExpress(data, v)
+                })
+            }
+        })
+    }
+
+    trav(result)
+    return result
+}
+
+/**
+ * 根据表达式进入写值
+ * express="{query.a}"   写值就是 viewModel.set('query.a', value)
+ * express="test-{query.a}"   写值就会失败
+ *
+ * @example
+ * tryWriteByExpress(cc.viewModel, "{query.WH_ID}", "111")
+ * 写值成功
+ *
+ * tryWriteByExpress(cc.viewModel, "test-{query.WH_ID}", "111")
+ * 写值失败
+ *
+ * @param viewModel VM对象
+ * @param express 表达式对象
+ * @param value 目标值
+ */
+export function tryWriteByExpress(viewModel, express, value) {
+    if (/^(?:\{(?:(\d+)|([a-z_][\w\.]*))\})$/i.test(express)) {
         // If we have '{foo}' alone it is a literal 简单表达式
         express = express.substring(1, express.length - 1);
-        return viewModel.get(express)
-
-    } else {
-        // Ext.app.bind.Parser.prototype.compile("{theGrid.selection.data}")
-        throw new TypeError("没有做完")
-        // let ret = undefined
-        // viewModel.bind(express, function (v) {
-        //     ret = v
-        //     debugger
-        // })
-        // // Ext.app.bind.TemplateBinding
-        // debugger
+        viewModel.set(express, value)
     }
 }
 
 /**
+ * 尝试根据含表达式的对象回写, calcObjectFlat 的逆向方法
+ * @example
+ * tryWriteObject(null, { a:'{query.a}', b:{b1:'{query.b1}', b2:'{query.b2}'},c:'aa',d:['{query.d1}','{query.d2}'] }, { a: 'aValue', b: { b1: 'b1Value', b2: 'b2Value' }, c: 'aa', d: [ '1', '2' ] })
+ *
+ * expressObject:
+ * {
+ *     a: '{query.a}',
+ *     b: {
+ *         b1: '{query.b1}',
+ *         b2: '{query.b2}',
+ *     },
+ *     c: 'aa',
+ *     d: [
+ *         '{query.a}',
+ *         '{query.b2}'
+ *     ]
+ * }
+ *
+ * valueObject:
+ * {
+ *     a: 'aValue',
+ *     b: {
+ *         b1: 'b1Value',
+ *         b2: 'b2Value'
+ *     },
+ *     c: 'aa'
+ *     c: [
+ *         'aValue',
+ *         'b2Value'
+ *     ]
+ * }
+ *
+ * 系统会尝试回写
+ * viewModel.set('query.a', 'aValue')
+ * viewModel.set('query.b1', 'b1Value')
+ * viewModel.set('query.b2', 'b2Value')
+ *
+ * @param expressObject 含表达式的对象
+ * @param valueObject 表达式计算完成之后的结果对象
+ * @param writeFn 忽略方法 (key,value)=>boolean ,如果这个方法返回 false 代表不需要系统做处理
+ */
+export function tryWriteObject(expressObject, valueObject, writeFn) {
+
+    const trav = (pathPrefix) => {
+        let parent = expressObject
+        if (_.size(pathPrefix) > 1) {
+            parent = _.get(parent, pathPrefix.substring(1))
+        }
+        _.forOwn(parent, (value, key) => {
+            if (_.isPlainObject(value)) {
+                // 深度递归,对子对象进行求解
+                trav(pathPrefix + "." + key)
+
+            } else if (_.isString(value)) {
+                // 字符串直接用 calcExpress 表达式求解
+                if (/^(?:\{(?:(\d+)|([a-z_][\w\.]*))\})$/i.test(value)) {
+                    // If we have '{foo}' alone it is a literal 简单表达式
+                    const targetPath = value.substring(1, value.length - 1);
+                    const targetValue = _.get(valueObject, (pathPrefix + "." + key).substr(1))
+                    if (!writeFn) {
+                        console.log(`viewModel.set('${targetPath}', '${targetValue}')`)
+                    } else {
+                        writeFn(targetPath, targetValue)
+                    }
+                }
+            } else if (_.isArray(value)) {
+                _.each(value, (v, idx) => {
+
+                })
+            }
+        })
+    }
+
+    trav("")
+}
+
+/**
  * 对多个表达式进行求值. 异步回调的方式返回
  *      {
  *          a: 1,
@@ -63,6 +231,10 @@ export function calcObject(viewModel, paramObject) {
             viewModel,
             (ret) => {
                 schedule.destroy()
+
+                // 从 Ext.data.Model 对象转换为 js-object 对象
+                ret = toPlainObject(ret)
+
                 resolve(ret)
             },
             viewModel,
@@ -317,10 +489,6 @@ class SystemEventFu {
             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

+ 1 - 1
src/types.ts

@@ -22,7 +22,7 @@ export interface FunctionArgument {
      * 参数值存放的内容(类型)
      *    module 选择一个功能模块
      *    control 从当前模块的 controller 中选择一个方法
-     *    viewModel 从当前模块的 VM 中的一个属性
+     *    viewModel 从当前模块的 model 中,选择一个属性
      *    refs 从当前模块的 refs 中选一个控件
      *    event 当成事件输入框来填写
      *    string 任意字符串