Jelajahi Sumber

Merge remote-tracking branch 'origin/master'

yuliang 3 tahun lalu
induk
melakukan
e12a698237
4 mengubah file dengan 222 tambahan dan 93 penghapusan
  1. 15 0
      src/Defaults.ts
  2. 24 25
      src/controls/grid.js
  3. 148 67
      src/controls/input/combogrid.js
  4. 35 1
      src/lib/systemLib.ts

+ 15 - 0
src/Defaults.ts

@@ -26,6 +26,21 @@ export const combo = {
     enableKeyEvents: true,
 }
 
+export const comboGrid = {
+    selectOnTab: true,
+    pickerHeight: 500,
+    pickerWidth: 850,
+}
+
+export const comboGridPicker = {
+    xtype: 'yvgrid',
+    layout: 'fit',
+    selModel: {
+        selType: 'rowmodel',
+        mode: 'SINGLE'
+    },
+}
+
 export const numberfield = {
     labelAlign: 'right',
     labelWidth: 70,

+ 24 - 25
src/controls/grid.js

@@ -3,7 +3,7 @@ import {grid} from '../Defaults'
 import {baseConfig} from "./base";
 import {lookupFn, lookupScope} from "../lib/lib";
 import {serverInvokeUrlTransform} from "../lib/config";
-import {calcObject} from "../lib/systemLib";
+import {calcObject, calcObjectFlat} from "../lib/systemLib";
 import {
     disabled,
     fieldLabel,
@@ -162,31 +162,30 @@ export default function () {
             if (_.isPlainObject(dataSource) && dataSource.method === 'invoke' && !window["IS_DESIGN_MODE"]) {
                 const scope = lookupScope(me)
 
-                calcObject(scope.viewModel, dataSource.params).then(params => {
-
-                    me.setStore(new Ext.data.Store({
-                        remoteSort: config.remoteSort,
-                        remoteFilter: config.remoteFilter,
-                        proxy: {
-                            type: 'jsonAjax',
-                            $owner: me,
-                            url: serverInvokeUrlTransform(dataSource.url),
-                            extraParams: _.defaultsDeep({}, reloadParams, params),
-                            reader: {
-                                type: 'json',
-                                rootProperty: 'data',
-                                totalProperty: 'pagination.total',
-                                successProperty: 'success',
-                                messageProperty: 'msg'
-                            }
-                        },
-                        listeners: {
-                            load: function (store, records, successful, operation) {
-                                me.fireEvent('dataLoadComplete', me, successful, records);
-                            }
+                const params = calcObjectFlat(scope.viewModel.data, dataSource.params)
+                me.setStore(new Ext.data.Store({
+                    remoteSort: config.remoteSort,
+                    remoteFilter: config.remoteFilter,
+                    autoLoad: true,
+                    proxy: {
+                        type: 'jsonAjax',
+                        $owner: me,
+                        url: serverInvokeUrlTransform(dataSource.url),
+                        extraParams: _.defaultsDeep({}, reloadParams, params),
+                        reader: {
+                            type: 'json',
+                            rootProperty: 'data',
+                            totalProperty: 'pagination.total',
+                            successProperty: 'success',
+                            messageProperty: 'msg'
                         }
-                    }))
-                })
+                    },
+                    listeners: {
+                        load: function (store, records, successful, operation) {
+                            me.fireEvent('dataLoadComplete', me, successful, records);
+                        }
+                    }
+                }))
             }
         },
 

+ 148 - 67
src/controls/input/combogrid.js

@@ -1,4 +1,7 @@
 import _ from 'lodash'
+import {comboGrid, comboGridPicker} from '../../Defaults'
+import {calcObjectFlat, clearViewModelByLookup, lookupScope, stopEvent, tryWriteByExpress, tryWriteObject} from "../..";
+import {msg} from "../../message";
 
 export default function () {
 
@@ -19,44 +22,58 @@ export default function () {
         },
 
         config: {
-            selectOnTab: true,
-            pickerHeight: 500,
-            pickerWidth: 750,
+            ...comboGrid
         },
 
         editable: true,
+        _superBlur: false,
 
         initComponent() {
             const that = this
-            const toggle = function (e) {
-                // @ts-ignore
-                const {readOnly, disabled} = that.config
-                if (readOnly || disabled) {
-                    return
-                }
-
-                // 点击后下拉
-                if (that.isExpanded) {
-                    // that.collapse()
-
-                } else {
-                    that.expand();
-                }
-            }
 
             this.on({
                 blur(sender, e) {
-                    this.revertOnblur()
+                    if (this._superBlur) {
+                        // 挂起时不恢复内容
+                        return
+                    }
+
+                    // 离开焦点时,恢复原来的值
+                    sender.setRawValue(sender.value)
                 },
                 afterrender(sender) {
-                    const $dom = $(sender.el.dom)
-                    $dom.on('keydown', (e) => {
-                        if (e.key === 'Enter') {
-                            toggle();
-                            e.stopPropagation();
-                            e.preventDefault();
-                            return
+                    const $dom = $(sender.inputEl.dom)
+                    if (sender.column) {
+                        // 列模式,拦截 keydown
+                        $dom.on('keydown', (e) => {
+                            if (e.key === 'Enter') {
+                                stopEvent(e)
+                                that.onTriggerClick(that, that.getPickerTrigger(), e);
+                                return
+                            }
+                        })
+
+                    } else {
+                        // 常规模式,拦截 keyup
+                        $dom.on('keyup', (e) => {
+                            if (e.key === 'Enter') {
+                                stopEvent(e)
+                                that.onTriggerClick(that, that.getPickerTrigger(), e);
+                                return
+                            }
+                            // 取消 keyup 事件,让 ext 不要吧当前输入的值记录到 value 中
+                            stopEvent(e)
+                        })
+                    }
+                    $dom.on('input', e => {
+                        // that.filterChange(that, e.target.value)
+                        stopEvent(e)
+                    })
+                    $dom.on('change', e => {
+                        if (that.isExpanded) {
+                            that.filterChange(that, e.target.value)
                         }
+                        stopEvent(e)
                     })
                 },
                 // 这里不能用 specialkey, 在表格编辑时可能出 bug
@@ -98,13 +115,9 @@ export default function () {
                 maxHeight: me.pickerHeight,
                 items: [
                     {
-                        xtype: 'yvgrid',
-                        layout: 'fit',
-                        selModel: {
-                            selType: 'rowmodel',
-                            mode: 'SINGLE'
-                        },
+                        ...comboGridPicker,
                         ...me.grid,
+                        autoLoad: false,
                         listeners: {
                             afterrender(grid) {
                                 me.grid = grid
@@ -119,7 +132,16 @@ export default function () {
                                         })
                                     },
                                     keydown(sender, e) {
-                                        me.processKey(e)
+                                        if (me.column) {
+                                            // 列模式,拦截 keydown
+                                            me.processKey(e)
+                                        }
+                                    },
+                                    keyup(sender, e) {
+                                        if (!me.column) {
+                                            // 常规模式,拦截 keyup
+                                            me.processKey(e)
+                                        }
                                     }
                                 })
                             },
@@ -141,6 +163,8 @@ export default function () {
         processKey(e) {
             if (e.key === 'Enter') {
                 this.selectItem(this.grid.selection)
+                stopEvent(e)
+
             } else if (e.key === 'Escape') {
                 this.collapse()
             }
@@ -162,63 +186,120 @@ export default function () {
             }
         },
 
+        filterChange: _.debounce((sender, value) => {
+            sender.onExpand()
+
+        }, 1000),
+
         selectItem(record) {
-            var me = this;
-            me.setValue(record.getId());
-            me.fireEvent('select', me, record);
+            const me = this;
+            const {lookup} = this
+            const scope = lookupScope(this)
+
+            me.fireEvent('select', me, record)
+
+            if (record.isModel) {
+                record = record.data
+            }
+
+            tryWriteObject(lookup, record, (path, value) => {
+                if (path === 'queryValue') {
+                    me.setValue(value)
+                } else {
+                    if (me.column) {
+                        // 列模式下,写当前编辑行
+                        const parentGrid = me.column.up('grid')
+                        const parentRecord = parentGrid.getSelectionModel().getLastSelected()
+                        // Ext.data.Record / Ext.data.Model
+                        parentRecord.set(path, value)
+
+                    } else {
+                        // 常规模式下,写 viewModel
+                        scope.viewModel.set(path, value)
+                    }
+                }
+            })
+
             me.collapse();
         },
 
         onExpand() {
-            const picker = this.picker;
-            this.setFocus()
+            // 展开时,根据 lookup 带入查询参数
+            const {param} = this
+            const scope = lookupScope(this)
+            const queryValue = this.getRawValue()
+
+            const reloadParam = calcObjectFlat({
+                ...scope.viewModel.data,
+                queryValue
+            }, param)
+
+            console.log('reload', reloadParam)
+            this.grid.reload(reloadParam)
         },
 
-        onCollapse() {
+        onTriggerClick() {
+            const {isExpanded, readOnly, disabled, grid} = this
+
+            if (!grid) {
+                msg('正在初始化,请稍后')
+                return
+            }
 
+            if (isExpanded || readOnly || disabled) {
+                // 已弹出、只读、禁用状态下,不允许弹出
+                return
+            }
+
+            this._superBlur = true
+            this.superclass.onTriggerClick.apply(this, arguments)
+            this._superBlur = false
         },
 
-        revertOnblur() {
-            this.setRawValue(this.lastValue)
+        onCollapse() {
+            // 每次收回时,删除下拉组件
+            // delete this.picker
         },
 
+        /**
+         * 本方法只会从 API 或外部调用,键盘输入的内容不会记录在内
+         */
         setValue(value) {
             const me = this;
-            console.log('setValue', value)
-            me.value = value;
-
-            if (!me.store || me.store.loading) {
-                // Called while the Store is loading. Ensure it is processed by the onLoad method.
-                return me.mixins.field.setValue.call(me, value);
-                // return me;
-            }
 
-            let record = value ? me.store.getNodeById(value) : me.store.getRoot();
-            if (value === undefined) {
-                record = me.store.getRoot();
-                console.log('setValue', record.getId())
-                me.value = record.getId();
-                return me.mixins.field.setValue.call(me, value);
-
-            } else {
-                record = me.store.getNodeById(value);
-            }
-
-            // set the raw value to the record's display field if a record was found
-            me.setRawValue(record ? record.get(me.displayField) : '');
+            // 设值用户看到的表面内容
+            this.setRawValue(value);
 
+            // 设值 setValue 调用链,正常触发 change 事件等
             return me.mixins.field.setValue.call(me, value);
         },
 
-        getSubmitValue() {
-            return this.value;
-        },
+        onChange: function (newVal, oldVal) {
+            const me = this
+            const value = newVal
 
-        getValue() {
-            return this.value;
+            if (value) {
+                me.getTrigger('clear').show();
+                me.updateLayout();
+            } else {
+                me.getTrigger('clear').hide();
+                me.updateLayout();
+            }
         },
 
+        /**
+         * 清空所有值
+         */
+        onClearClick(sender, e) {
+            const me = this
+            const {config} = me
+            const {lookup} = config
+
+            me.fireEvent('clear', sender, e)
 
+            me.setValue('')
+            clearViewModelByLookup(sender, lookup)
+        }
     });
 
 }

+ 35 - 1
src/lib/systemLib.ts

@@ -23,7 +23,7 @@ export function calcExpress(data, express) {
         // '{foo}' 简单表达式
         const path = express.substring(1, express.length - 1);
         const ret = _.get(data, path)
-        return ret.isModel ? ret.data : ret
+        return ret?.isModel ? ret.data : ret
     }
 
     while (true) {
@@ -719,6 +719,40 @@ class SystemEventFu {
     }
 
     @Lib({
+        title: '从其他资源获取表格设置',
+        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',
+            }
+        ]
+    })
+    getGrid(url) {
+        return function (sender, config) {
+            // @ts-ignore
+            require([url], (grid) => {
+                if (sender.rendered) {
+                    sender.grid = grid.default
+                } else {
+                    config.grid = grid.default
+                }
+            })
+        }
+    }
+
+    @Lib({
         title: '清空 viewModel 某个属性,并刷新表格',
         author: '罗一帆',
         createAt: '2021-07-02',