|
@@ -0,0 +1,404 @@
|
|
|
+import _ from 'lodash'
|
|
|
+import {comboGrid, comboGridPicker} from '../../Defaults'
|
|
|
+import {
|
|
|
+ calcObjectFlat,
|
|
|
+ lookupScope,
|
|
|
+ tryEnable,
|
|
|
+ stopEvent,
|
|
|
+ tryVarSimple,
|
|
|
+ tryWriteObject
|
|
|
+} from "../..";
|
|
|
+import {msg} from "../../message";
|
|
|
+import {isChartEvent} from '../../utils'
|
|
|
+
|
|
|
+export default function () {
|
|
|
+
|
|
|
+ Ext.define('Yvan.ComboGrid', {
|
|
|
+ extend: 'Ext.form.field.Picker',
|
|
|
+ // extend: 'Yvan.PickerAlignCenter',
|
|
|
+ xtype: 'combogrid',
|
|
|
+
|
|
|
+ triggerCls: Ext.baseCSSPrefix + 'form-search-trigger',
|
|
|
+
|
|
|
+ triggers: {
|
|
|
+ clear: {
|
|
|
+ weight: 0,
|
|
|
+ cls: Ext.baseCSSPrefix + 'form-clear-trigger',
|
|
|
+ hidden: true,
|
|
|
+ handler: 'onClearClick',
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ config: {
|
|
|
+ ...comboGrid
|
|
|
+ },
|
|
|
+
|
|
|
+ editable: true,
|
|
|
+ _superBlur: false,
|
|
|
+
|
|
|
+ initComponent() {
|
|
|
+ const that = this
|
|
|
+
|
|
|
+ this.on({
|
|
|
+ blur(sender, e) {
|
|
|
+ if (this._superBlur) {
|
|
|
+ // 挂起时不恢复内容
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 离开焦点时,恢复原来的值
|
|
|
+ sender.setRawValue(sender.value)
|
|
|
+ },
|
|
|
+ afterrender(sender) {
|
|
|
+ const $dom = $(sender.inputEl.dom)
|
|
|
+ that.scope = lookupScope(sender)
|
|
|
+
|
|
|
+ if (sender.column) {
|
|
|
+ // 列模式,拦截 keydown
|
|
|
+ $dom.on('keydown', (e) => {
|
|
|
+ if (isChartEvent(e) && !that.tryEnable()) {
|
|
|
+ // 没有达成 editEnable 条件,不用响应
|
|
|
+ stopEvent(e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.key === 'Enter') {
|
|
|
+ stopEvent(e)
|
|
|
+ that.onTriggerClick(that, that.getPickerTrigger(), e);
|
|
|
+ return
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 常规模式,拦截 keyup
|
|
|
+ $dom.on('keyup', (e) => {
|
|
|
+ if (e.key === 'Escape' || e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isChartEvent(e) && !that.tryEnable()) {
|
|
|
+ // 没有达成 editEnable 条件,不用响应
|
|
|
+ stopEvent(e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.key === 'Enter') {
|
|
|
+ stopEvent(e)
|
|
|
+ that.onTriggerClick(that, that.getPickerTrigger(), e);
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 取消 keyup 事件,让 ext 不要吧当前输入的值记录到 value 中
|
|
|
+ stopEvent(e)
|
|
|
+ })
|
|
|
+ $dom.on('change', e => {
|
|
|
+ if (that.isExpanded) {
|
|
|
+ that.filterChange(that, e.target.value)
|
|
|
+ }
|
|
|
+ stopEvent(e)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ $dom.on('input', e => {
|
|
|
+ stopEvent(e)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 这里不能用 specialkey, 在表格编辑时可能出 bug
|
|
|
+ // specialkey(sender, e) {
|
|
|
+ // const me = this
|
|
|
+ // if (e.getKey() === e.ENTER) {
|
|
|
+ // _.defer(() => {
|
|
|
+ // toggle();
|
|
|
+ // })
|
|
|
+ // e.stopEvent()
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ // },
|
|
|
+ })
|
|
|
+
|
|
|
+ this.superclass.initComponent.apply(this, arguments)
|
|
|
+ },
|
|
|
+
|
|
|
+ createPicker() {
|
|
|
+ const me = this
|
|
|
+ const cfg = {
|
|
|
+ layout: 'fit',
|
|
|
+ border: 5,
|
|
|
+ style: {
|
|
|
+ borderColor: 'black',
|
|
|
+ borderWidth: '5px',
|
|
|
+ borderStyle: 'solid'
|
|
|
+ },
|
|
|
+ shadow: 'side',
|
|
|
+ shadowOffset: 100,
|
|
|
+ baseCls: Ext.baseCSSPrefix + 'boundlist',
|
|
|
+ shrinkWrapDock: 2,
|
|
|
+ floating: true,
|
|
|
+ width: me.pickerWidth,
|
|
|
+ height: me.pickerHeight,
|
|
|
+ minWidth: me.pickerWidth,
|
|
|
+ minHeight: me.pickerHeight,
|
|
|
+ maxWidth: me.pickerWidth,
|
|
|
+ maxHeight: me.pickerHeight,
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ ...comboGridPicker,
|
|
|
+ ...me.grid,
|
|
|
+ autoLoad: false,
|
|
|
+ listeners: {
|
|
|
+ afterrender(grid) {
|
|
|
+ me.grid = grid
|
|
|
+ grid.focus()
|
|
|
+ grid.on({
|
|
|
+ rowdblclick(sender, row) {
|
|
|
+ me.selectItem(row)
|
|
|
+ },
|
|
|
+ dataLoadComplete(sender) {
|
|
|
+ _.defer(() => {
|
|
|
+ me.setFocus()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ keydown(sender, e) {
|
|
|
+ if (me.column) {
|
|
|
+ // 列模式,拦截 keydown
|
|
|
+ me.processKey(e)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ keyup(sender, e) {
|
|
|
+ if (!me.column) {
|
|
|
+ // 常规模式,拦截 keyup
|
|
|
+ me.processKey(e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ // @ts-ignore
|
|
|
+ const picker = new Ext.container.Container(cfg)
|
|
|
+ return picker;
|
|
|
+ },
|
|
|
+
|
|
|
+ setFocus() {
|
|
|
+ if (this.grid.store.getCount() > 0) {
|
|
|
+ this.grid.focusRow(0)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ processKey(e) {
|
|
|
+ if (e.key === 'Enter') {
|
|
|
+ this.selectItem(this.grid.selection)
|
|
|
+ stopEvent(e)
|
|
|
+
|
|
|
+ } else if (e.key === 'Escape') {
|
|
|
+ this.collapse()
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ repaintPickerView() {
|
|
|
+ const style = this.picker.getView().getEl().dom.style;
|
|
|
+ style.display = style.display;
|
|
|
+ },
|
|
|
+
|
|
|
+ onItemClick(view, record, node, rowIndex, e) {
|
|
|
+ this.selectItem(record);
|
|
|
+ },
|
|
|
+
|
|
|
+ onPickerKeyDown(treeView, record, item, index, e) {
|
|
|
+ const key = e.getKey();
|
|
|
+ if (key === e.ENTER || (key === e.TAB && this.selectOnTab)) {
|
|
|
+ this.selectItem(record);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ filterChange: _.debounce((sender, value) => {
|
|
|
+ sender.onExpand()
|
|
|
+
|
|
|
+ }, 1000),
|
|
|
+
|
|
|
+ selectItem(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) => {
|
|
|
+ me._lookupSet(path, value)
|
|
|
+ })
|
|
|
+ // lookup
|
|
|
+ // fromColumn: 'toTarget'
|
|
|
+ // fromColumn: 'toTarget'
|
|
|
+ // fromColumn: 'toTarget'
|
|
|
+ _.forOwn(lookup, (toTarget, fromColumn) => {
|
|
|
+ const value = _.get(record, fromColumn)
|
|
|
+ me._lookupSet(toTarget, value)
|
|
|
+ })
|
|
|
+
|
|
|
+ const {lookupClearOnChange} = me
|
|
|
+ if (_.isArray(lookupClearOnChange)) {
|
|
|
+ _.each(lookupClearOnChange, item => {
|
|
|
+ me._lookupSet(item, '')
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ me.collapse();
|
|
|
+ },
|
|
|
+
|
|
|
+ onExpand() {
|
|
|
+ // 展开时,根据 lookup 带入查询参数
|
|
|
+ const reloadParam = calcObjectFlat(this.getExpressData(), this.param)
|
|
|
+
|
|
|
+ this.grid.reload(reloadParam)
|
|
|
+ },
|
|
|
+
|
|
|
+ onTriggerClick(sender) {
|
|
|
+ const {isExpanded, readOnly, disabled, grid,} = this
|
|
|
+
|
|
|
+ if (!grid) {
|
|
|
+ msg('正在初始化,请稍后')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.tryEnable()) {
|
|
|
+ // 没有达成 editEnable 条件,不用弹出
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isExpanded || readOnly || disabled) {
|
|
|
+ // 已弹出、只读、禁用状态下,不允许弹出
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ this._superBlur = true
|
|
|
+ this.superclass.onTriggerClick.apply(this, arguments)
|
|
|
+ this._superBlur = false
|
|
|
+ },
|
|
|
+
|
|
|
+ onCollapse() {
|
|
|
+ // 每次收回时,删除下拉组件
|
|
|
+ // delete this.picker
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 本方法只会从 API 或外部调用,键盘输入的内容不会记录在内
|
|
|
+ */
|
|
|
+ setValue(value) {
|
|
|
+ const me = this
|
|
|
+
|
|
|
+ // 设值用户看到的表面内容
|
|
|
+ this.setRawValue(value)
|
|
|
+
|
|
|
+ // 设值 setValue 调用链,正常触发 change 事件等
|
|
|
+ return me.mixins.field.setValue.call(me, value)
|
|
|
+ },
|
|
|
+
|
|
|
+ _lookupSet(path, value) {
|
|
|
+ const me = this
|
|
|
+ path = tryVarSimple(path)
|
|
|
+
|
|
|
+ if (me.column) {
|
|
|
+
|
|
|
+ // 判断写入目标,是否与自己绑定的属性相等
|
|
|
+ if (path === 'queryValue' || me.column.dataIndex === path) {
|
|
|
+ me.setValue(value)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 列模式下,写当前编辑行
|
|
|
+ const parentRecord = me._lookupEditorRecord()
|
|
|
+ if (parentRecord) {
|
|
|
+ // Ext.data.Record / Ext.data.Model
|
|
|
+ parentRecord.set(path, value)
|
|
|
+ } else {
|
|
|
+ debugger
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 常规模式下,写 viewModel
|
|
|
+ me.scope.viewModel.set(path, value)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ _lookupGrid() {
|
|
|
+ return this.column.up('grid')
|
|
|
+ },
|
|
|
+
|
|
|
+ _lookupEditorRecord() {
|
|
|
+ // parentGrid.getSelectionModel().getLastSelected()
|
|
|
+ const grid = this._lookupGrid()
|
|
|
+ const rowIdx = grid.editingPlugin?.activeEditor?.context?.rowIdx
|
|
|
+ if (_.isNumber(rowIdx)) {
|
|
|
+ return grid.store.getAt(rowIdx)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ onChange: function (newVal, oldVal) {
|
|
|
+ const me = this
|
|
|
+ const value = newVal
|
|
|
+
|
|
|
+ if (value) {
|
|
|
+ me.getTrigger('clear').show();
|
|
|
+ me.updateLayout();
|
|
|
+ } else {
|
|
|
+ me.getTrigger('clear').hide();
|
|
|
+ me.updateLayout();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 得到能用于 express 表达式计算的上下文数据
|
|
|
+ */
|
|
|
+ getExpressData() {
|
|
|
+ const queryValue = this.getRawValue()
|
|
|
+
|
|
|
+ if (this.column) {
|
|
|
+ // 列模式, 准备好判断 editEnable 表达式用的数据
|
|
|
+ const parentRecord = this._lookupEditorRecord()
|
|
|
+ if (!parentRecord) {
|
|
|
+ debugger
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...this.scope.viewModel.data,
|
|
|
+ ...parentRecord.data,
|
|
|
+ queryValue,
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 编辑模式,准备好判断用的数据
|
|
|
+ return {
|
|
|
+ ...this.scope.viewModel.data,
|
|
|
+ queryValue,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ tryEnable() {
|
|
|
+ return tryEnable(this.getExpressData(), this.editEnable)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清空所有值
|
|
|
+ */
|
|
|
+ onClearClick(sender, e) {
|
|
|
+ const me = this
|
|
|
+ const {lookup, lookupClearOnChange} = me
|
|
|
+
|
|
|
+ me.fireEvent('clear', sender, e)
|
|
|
+
|
|
|
+ me.setValue('')
|
|
|
+ _.forOwn(lookup, (toTarget, fromColumn) => {
|
|
|
+ me._lookupSet(toTarget, '')
|
|
|
+ })
|
|
|
+
|
|
|
+ _.each(lookupClearOnChange, item => {
|
|
|
+ me._lookupSet(item, '')
|
|
|
+ })
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+}
|