import { shortcut, extend, emptyFn, deepClone, isKey, Selection, remove, pushDistinct, createWidget, isNotEmptyString, i18nText, isEmptyArray, last, initial, endWith, AbsoluteLayout, isEmptyString, makeObject, each, Func, map, concat, isNotNull, values, filter, contains, isNull, VerticalFillLayout } from "@/core"; import { Single, Searcher } from "@/base"; import { MultiSelectBar } from "@/case"; import { SelectPatchEditor } from "../multiselect/trigger/editor/editor.patch"; import { MultiSelectLoader } from "../multiselect/multiselect.loader"; import { MultiSelectSearchInsertPane } from "../multiselect/search/multiselect.search.insert.pane"; import { SearchEditor } from "@/widget/editor/editor.search"; @shortcut() export class MultiSelectInsertList extends Single { static xtype = "bi.multi_select_insert_list"; static REQ_GET_DATA_LENGTH = "1"; static REQ_GET_ALL_DATA = "-1"; static EVENT_CHANGE = "EVENT_CHANGE"; _defaultConfig() { return extend(super._defaultConfig(...arguments), { baseCls: "bi-multi-select-insert-list", itemsCreator: emptyFn, valueFormatter: emptyFn, searcherHeight: BI.SIZE_CONSANTS.TRIGGER_HEIGHT, itemHeight: BI.SIZE_CONSANTS.LIST_ITEM_HEIGHT, }); } _init() { super._init(...arguments); const self = this, o = this.options; this.storeValue = this._assertValue(deepClone(o.value) || {}); function assertShowValue() { isKey(self._startValue) && (self.storeValue.type === Selection.All ? remove(self.storeValue.value, self._startValue) : pushDistinct(self.storeValue.value, self._startValue)); // self.trigger.setValue(self.storeValue); } this.adapter = createWidget({ type: MultiSelectLoader.xtype, cls: "popup-multi-select-list bi-border-left bi-border-right bi-border-bottom", itemsCreator: o.itemsCreator, itemHeight: o.itemHeight, valueFormatter: o.valueFormatter, itemFormatter: o.itemFormatter, logic: { dynamic: false, }, // onLoaded: o.onLoaded, el: {}, isDefaultInit: true, value: o.value, }); this.adapter.on(MultiSelectLoader.EVENT_CHANGE, function () { self.storeValue = this.getValue(); assertShowValue(); self.fireEvent(MultiSelectInsertList.EVENT_CHANGE); }); this.searcherPane = createWidget({ type: MultiSelectSearchInsertPane.xtype, cls: "bi-border-left bi-border-right bi-border-bottom", valueFormatter: o.valueFormatter, itemFormatter: o.itemFormatter, keywordGetter() { return self.trigger.getKeyword(); }, itemsCreator(op, callback) { const keyword = self.trigger.getKeyword(); if (isNotEmptyString(keyword)) { op.keywords = [keyword]; this.setKeyword(op.keywords[0]); o.itemsCreator(op, callback); } }, itemHeight: o.itemHeight, }); this.searcherPane.setVisible(false); this.trigger = createWidget({ type: Searcher.xtype, el: { type: SelectPatchEditor.xtype, el: { type: SearchEditor.xtype, watermark: i18nText("BI-Basic_Search_And_Patch_Paste"), }, ref(ref) { self.editor = ref; }, }, isAutoSearch: false, isAutoSync: false, onSearch(op, callback) { callback(); }, adapter: this.adapter, popup: this.searcherPane, masker: false, listeners: [ { eventName: Searcher.EVENT_START, action() { self._showSearcherPane(); self._setStartValue(""); this.setValue(deepClone(self.storeValue)); }, }, { eventName: Searcher.EVENT_STOP, action() { self._showAdapter(); self._setStartValue(""); self.adapter.setValue(self.storeValue); // 需要刷新回到初始界面,否则搜索的结果不能放在最前面 self.adapter.populate(); }, }, { eventName: Searcher.EVENT_PAUSE, action() { let keywords = self._getKeywords(); if ( keywords[keywords.length - 1] === BI.BlankSplitChar ) { keywords = keywords.slice(0, keywords.length - 1); } const keyword = isEmptyArray(keywords) ? "" : keywords[keywords.length - 1]; self._join( { type: Selection.Multi, value: [keyword], }, () => { if (self.storeValue.type === Selection.Multi) { pushDistinct( self.storeValue.value, keyword ); } self._showAdapter(); self.adapter.setValue(self.storeValue); self._setStartValue(keyword); assertShowValue(); self.adapter.populate(); self._setStartValue(""); self.fireEvent( MultiSelectInsertList.EVENT_CHANGE ); } ); self._showAdapter(); }, }, { eventName: Searcher.EVENT_SEARCHING, action() { let keywords = self._getKeywords(); const lastKeyword = last(keywords); keywords = initial(keywords || []); if (keywords.length > 0) { self._joinKeywords(keywords, () => { if (endWith(lastKeyword, BI.BlankSplitChar)) { self.adapter.setValue(self.storeValue); assertShowValue(); self.adapter.populate(); self._setStartValue(""); } else { self.adapter.setValue(self.storeValue); assertShowValue(); } self.fireEvent( MultiSelectInsertList.EVENT_CHANGE ); }); self._getKeywordsLength() > 2000 && BI.Msg.alert( i18nText("BI-Basic_Prompt"), i18nText( "BI-Basic_Too_Much_Value_Get_Two_Thousand" ) ); } }, }, { eventName: Searcher.EVENT_CHANGE, action(value, obj) { if (obj instanceof MultiSelectBar) { self._joinAll(this.getValue(), () => { assertShowValue(); self.fireEvent( MultiSelectInsertList.EVENT_CHANGE ); }); } else { self._join(this.getValue(), () => { assertShowValue(); self.fireEvent( MultiSelectInsertList.EVENT_CHANGE ); }); } }, } ], value: o.value, }); createWidget({ type: VerticalFillLayout.xtype, rowSize: ["", "fill"], element: this, items: [ { el: this.trigger, }, { el: this.adapter, } ], }); createWidget({ type: AbsoluteLayout.xtype, element: this, items: [ { el: this.searcherPane, top: o.searcherHeight || BI.SIZE_CONSANTS.TRIGGER_HEIGHT, bottom: 0, left: 0, right: 0, } ], }); } _getKeywords() { const val = this.editor.getValue(); let keywords = val.split(/\u200b\s\u200b/); if (isEmptyString(keywords[keywords.length - 1])) { keywords = keywords.slice(0, keywords.length - 1); } if (/\u200b\s\u200b$/.test(val)) { keywords = keywords.concat([BI.BlankSplitChar]); } return keywords.length > 2000 ? keywords.slice(0, 2000).concat([BI.BlankSplitChar]) : keywords.slice(0, 2000); } _getKeywordsLength() { const val = this.editor.getValue(); const keywords = val.split(/\u200b\s\u200b/); return keywords.length - 1; } _showAdapter() { this.adapter.setVisible(true); this.searcherPane.setVisible(false); } _showSearcherPane() { this.searcherPane.setVisible(true); this.adapter.setVisible(false); } _defaultState() { this.trigger.stopEditing(); } _assertValue(val) { val || (val = {}); val.type || (val.type = Selection.Multi); val.value || (val.value = []); return val; } _makeMap(values) { return makeObject(values || []); } _joinKeywords(keywords, callback) { const self = this; this._assertValue(this.storeValue); // 和复选下拉框同步,allData做缓存是会爆炸的 digest(); function digest() { each(keywords, (i, val) => { self.storeValue.type === Selection.Multi ? pushDistinct(self.storeValue.value, val) : remove(self.storeValue.value, val); }); callback(); } } _joinAll(res, callback) { const self = this, o = this.options; this._assertValue(res); if (this.storeValue.type === res.type) { const result = Func.getSearchResult( map(this.storeValue.value, (_i, v) => { return { text: o.valueFormatter(v) || v, value: v, }; }), this.trigger.getKeyword() ); let change = false; const tempMap = this._makeMap(this.storeValue.value); each(concat(result.match, result.find), (i, obj) => { const v = obj.value; if (isNotNull(tempMap[v])) { change = true; delete tempMap[v]; } }); change && (this.storeValue.value = values(tempMap)); callback(); return; } o.itemsCreator( { type: MultiSelectInsertList.REQ_GET_ALL_DATA, keywords: [this.trigger.getKeyword()], selectedValues: filter(this.storeValue.value, (_i, v) => !contains(res.value, v)), }, ob => { const items = map(ob.items, "value"); const selectedMap = self._makeMap(self.storeValue.value); const notSelectedMap = self._makeMap(res.value); const newItems = []; each(items, (i, item) => { if (isNotNull(selectedMap[items[i]])) { delete selectedMap[items[i]]; } if (isNull(notSelectedMap[items[i]])) { newItems.push(item); } }); self.storeValue.value = newItems.concat(values(selectedMap)); callback(); } ); } _join(res, callback) { const self = this; this._assertValue(res); this._assertValue(this.storeValue); if (this.storeValue.type === res.type) { const map = this._makeMap(this.storeValue.value); each(res.value, (i, v) => { if (!map[v]) { pushDistinct(self.storeValue.value, v); map[v] = v; } }); let change = false; each(res.assist, (i, v) => { if (isNotNull(map[v])) { change = true; delete map[v]; } }); change && (this.storeValue.value = values(map)); callback(); return; } this._joinAll(res, callback); } _setStartValue(value) { this._startValue = value; this.adapter.setStartValue(value); } isAllSelected() { return this.adapter.isAllSelected(); } resize() { // this.trigger.getCounter().adjustView(); // this.trigger.adjustView(); } setValue(v) { this.storeValue = v || {}; this._assertValue(this.storeValue); this.adapter.setValue(this.storeValue); this.trigger.setValue(this.storeValue); } getValue() { return deepClone(this.storeValue); } populate() { this.adapter.populate(...arguments); this.trigger.populate(...arguments); } }