Browse Source

拼音筛选问题 / 对话框多伦打开问题

luoyifan 3 năm trước cách đây
mục cha
commit
f0cb1ddd50
7 tập tin đã thay đổi với 99 bổ sung9 xóa
  1. 4 0
      src/Defaults.ts
  2. 16 4
      src/Scope.ts
  3. 2 0
      src/controls/MainTab.js
  4. 19 0
      src/controls/input/combo.js
  5. 35 1
      src/lib/config.ts
  6. 6 1
      src/lib/fix.js
  7. 17 3
      src/lib/systemLib.ts

+ 4 - 0
src/Defaults.ts

@@ -19,6 +19,10 @@ export const combo = {
     valueField: 'id',
     displayField: 'text',
     autoLoad: true,
+    mode: 'local',
+    forceSelection: true,
+    triggerAction: 'all',
+    enableKeyEvents: true,
 }
 
 export const numberfield = {

+ 16 - 4
src/Scope.ts

@@ -44,6 +44,11 @@ export class Scope {
     _vjsonOption
     _dataOption
 
+    /**
+     * 最顶部的 scope 对象
+     */
+    topScope
+
     _addWatch(tplExpress, fn) {
         if (!this._watchList) {
             this._watchList = []
@@ -124,12 +129,19 @@ export class Scope {
         if (config.width === 'unset') {
             delete config.width
         }
-        const holder = sender?.lookupReferenceHolder()
+        // const holder = sender?.lookupReferenceHolder()
         // delete config.constrain
-        config.constrain = true
+        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 (holder) {
+        //     holder.add(win)
+        // }
+        if (topScope) {
+            topScope._handle.add(win)
         }
 
         win.addListener('beforerender', function (sender) {

+ 2 - 0
src/controls/MainTab.js

@@ -74,6 +74,8 @@ export default function () {
          * @param panelInitCallback panel初始化之后会调用函数进行构造前的加工
          */
         addScope(scopeInstance, config, panelInitCallback) {
+            scopeInstance.topScope = scopeInstance
+
             const me = this
             if (config.path) {
                 for (let i = 0; i < this.items.items.length; i++) {

+ 19 - 0
src/controls/input/combo.js

@@ -2,6 +2,7 @@ import _ from 'lodash'
 import {combo} from '../../Defaults'
 import {baseConfig} from "../base";
 import {dataSourceReload} from "../../DataSourceHelper";
+import {keywordFilter} from '../../lib/config'
 import {
     disabled,
     fieldLabel,
@@ -110,6 +111,24 @@ export default function () {
                 destory() {
                     $(this.el.dom).off('click', toggle.bind(this))
                 },
+                beforequery(e) {
+                    console.log('beforequery', e)
+                    const {query, combo} = e
+
+                    if (!e.forceAll && query) {
+                        combo.store.filterBy(function (record, id) {
+                            const text = record.get(combo.displayField)
+                            // 用拼音筛选的方式
+                            return keywordFilter(query, text, id)
+                        });
+                        combo.expand();
+                        return false;
+                    }
+
+                    combo.store.clearFilter()
+                    combo.expand();
+                    return false;
+                }
                 // focus: {
                 //     // 获得焦点后自动下拉
                 //     fn(sender) {

+ 35 - 1
src/lib/config.ts

@@ -47,7 +47,7 @@ export const ajax: {
 /**
  * 计算拼音的函数
  */
-let pinyinFunc: Function
+let pinyinFunc: Function = (str) => (str)
 
 export const baseConfigProcessList: ConfigProcess[] = []
 
@@ -108,3 +108,37 @@ export function extend(option: Partial<ConfigOption>) {
         setDesignMode(option.designMode)
     }
 }
+
+export function getPinyin(v: string) {
+    return pinyinFunc(v)
+}
+
+/**
+ * 适用于 Select / Tree 等,作筛选的通用方法.
+ * 1.首字母模糊匹配(不区分大小写)
+ * 2.标识的模糊匹配(不区分大小写)
+ * 3.名称的模糊匹配,且支持以逗号(全角或半角)隔开的字词匹配,并自动去空格,如“南京, 物流 ”可以匹配出“南京九州通物流技术开发有限公司”
+ */
+export function keywordFilter(keyword: string, label: string, value?: string) {
+    if (!keyword) {
+        return true
+    }
+    const ws = _.trim(keyword).split(/\s+|\.|,|\)|\(|,|。|-|—/g)
+    const labelPy = _.toLower(getPinyin(label))
+    value = _.toLower(_.trim(value))
+
+    let found = 0
+    _.some(ws, (word) => {
+        if (labelPy.indexOf(word.toLowerCase()) >= 0 || label.indexOf(word) >= 0) {
+            found++
+            return
+        }
+
+        if (value && value.indexOf(word.toLowerCase()) >= 0) {
+            found++
+            return
+        }
+    })
+
+    return found >= ws.length
+}

+ 6 - 1
src/lib/fix.js

@@ -11,7 +11,12 @@ class FixClass {
             return
         }
 
-        const scope = lookupScope(me)
+        delete config.fix
+
+        // 这里有个 bug
+        // 但凡是调用了 this.lookupViewModel() 就会出现绑定不了的情况
+        // const scope = config.$initParent.lookupReferenceHolder().yvanScope //lookupScope(me)
+        const scope = config.$initParent.lookupReferenceHolder().yvanScope //lookupScope(me)
         if (_.isArray(fix)) {
             _.each(fix, (f) => {
                 const fn = lookupFn(scope, f)

+ 17 - 3
src/lib/systemLib.ts

@@ -279,9 +279,16 @@ export function setComboStore(sender, config, getDictFn, bizKey) {
 
     if (sender.$className === 'Ext.form.field.ComboBox') {
         getDictFn(bizKey, (r) => {
-            if (sender.el?.dom) {
+            if (sender.rendered) {
                 // 异步回传
                 sender.setStore(new Ext.data.Store(r))
+                // 这里有个bug, 异步回传完毕之后, 需要强制刷新一下
+                // 否则在 forceSelection 的模式下。displayField 不会强制做变更
+                const realValue = sender.bind?.value?.getValue()
+                if (typeof realValue !== 'undefined') {
+                    sender.setValue(realValue)
+                }
+
             } else {
                 // 同步回传
                 config.store = new Ext.data.Store(r)
@@ -397,18 +404,20 @@ export function toPlainObject(obj) {
 
 export function confirm(msg, sender?): Promise<void> {
     return new Promise<void>(resolve => {
-        const scope = lookupScope(sender)
+        const scope = lookupScope(sender)?.topScope
+
         const config: any = {
             title: '请确认',
             icon: Ext.Msg.QUESTION,
             modal: true,
             animateTarget: sender,
+            // resizable: false,
             // constrainHeader: true,
             // constrain: true,
             // constrainTo: scope._handle?.el?.dom || Ext.getBody(),
             items: [
                 {
-                    html: _.escape(msg)
+                    html: `<div style="min-width: 300px;min-height: 110px">${_.escape(msg)}</div>`
                 }
             ],
             buttons: [
@@ -960,4 +969,9 @@ export function stopEvent(e) {
     window.event.cancelBubble = true
     e.returnValue = false;
     e.cancelBubble = true;
+}
+
+
+export {
+    msg
 }