fineui是帆软报表和BI产品线所使用的前端框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

301 lines
9.7 KiB

import {
shortcut,
emptyFn,
i18nText,
isNotNull,
isKey,
HorizontalFillLayout,
Tree,
deepClone,
Func,
concat,
isNotEmptyArray,
each,
uniqBy,
map,
isFunction,
find
} from "@/core";
import { Trigger, Searcher } from "@/base";
import { StateEditor, DefaultTextEditor } from "@/case";
import { MultiLayerSelectTreeInsertSearchPane } from "./multilayerselecttree.insert.search.pane";
import { MultiLayerSelectTreePopup } from "./multilayerselecttree.popup";
@shortcut()
export class MultiLayerSelectTreeTrigger extends Trigger {
static xtype = "bi.multilayer_select_tree_trigger";
static EVENT_FOCUS = "EVENT_FOCUS";
static EVENT_BLUR = "EVENT_BLUR";
static EVENT_SEARCHING = "EVENT_SEARCHING";
static EVENT_STOP = "EVENT_STOP";
static EVENT_START = "EVENT_START";
static EVENT_CHANGE = "EVENT_CHANGE";
static EVENT_ADD_ITEM = "EVENT_ADD_ITEM";
props() {
return {
extraCls: "bi-multi-layer-select-tree-trigger",
height: 24,
itemsCreator: emptyFn,
watermark: i18nText("BI-Basic_Search"),
allowSearchValue: false,
title: () => this._getShowText(),
};
}
render() {
const self = this,
o = this.options;
if (o.itemsCreator === BI.emptyFn) {
this._initData();
}
return {
type: HorizontalFillLayout.xtype,
items: [
{
el: {
type: Searcher.xtype,
ref() {
self.searcher = this;
},
masker: isNotNull(o.container)
? {
offset: {},
container: o.container,
}
: {
offset: {},
},
isAutoSearch: false,
el: {
type: DefaultTextEditor.xtype,
ref() {
self.editor = this;
},
defaultText: o.defaultText,
text: isKey(o.value)
? this._digest(o.value)
: o.text,
value: o.value,
height: o.height,
tipText: "",
watermark: o.watermark,
listeners: [
{
eventName: StateEditor.EVENT_FOCUS,
action() {
self.fireEvent(
MultiLayerSelectTreeTrigger.EVENT_FOCUS
);
},
},
{
eventName: StateEditor.EVENT_BLUR,
action() {
self.fireEvent(
MultiLayerSelectTreeTrigger.EVENT_BLUR
);
},
},
{
eventName: StateEditor.EVENT_CHANGE,
action() {
self.fireEvent(
MultiLayerSelectTreeTrigger.EVENT_SEARCHING
);
},
}
],
},
popup: {
type: o.allowInsertValue
? MultiLayerSelectTreeInsertSearchPane.xtype
: MultiLayerSelectTreePopup.xtype,
itemsCreator:
o.itemsCreator === emptyFn
? emptyFn
: function (op, callback) {
op.keyword = self.editor.getValue();
o.itemsCreator(op, callback);
},
keywordGetter() {
return self.editor.getValue();
},
cls: "bi-card",
listeners: [
{
eventName:
MultiLayerSelectTreeInsertSearchPane.EVENT_ADD_ITEM,
action() {
self.options.text = self
.getSearcher()
.getKeyword();
self.fireEvent(
MultiLayerSelectTreeTrigger.EVENT_ADD_ITEM
);
},
}
],
ref(_ref) {
self.popup = _ref;
},
},
onSearch(obj, callback) {
const keyword = obj.keyword;
if (o.itemsCreator === BI.emptyFn) {
callback(self._getSearchItems(keyword));
o.allowInsertValue &&
self.popup.setKeyword(keyword);
} else {
callback();
}
},
listeners: [
{
eventName: Searcher.EVENT_CHANGE,
action() {
self.fireEvent(
MultiLayerSelectTreeTrigger.EVENT_CHANGE
);
},
}
],
},
width: "fill",
rgap: 24,
}
],
};
}
_initData() {
const o = this.options;
this.tree = new Tree();
this.nodes = Tree.treeFormat(deepClone(o.items));
this.tree.initTree(this.nodes);
}
_getSearchItems(keyword) {
const self = this,
o = this.options;
// 把数组搜索换成用BI.tree搜索节点, 搜到了就不再往下搜索
const items = [];
this.tree.traverse(node => {
const find = Func.getSearchResult(
self.tree.isRoot(node)
? []
: concat(
[node.text],
o.allowSearchValue ? [node.value] : []
),
keyword
);
if (find.find.length > 0 || find.match.length > 0) {
items.push(node);
return true;
}
});
return this._fillTreeStructure4Search(items, "id");
}
_createJson(node, open) {
return {
id: node.id,
pId: node.pId,
text: node.text,
value: node.value,
isParent: isNotEmptyArray(node.children),
open,
};
}
_getChildren(node) {
const self = this;
node.children = node.children || [];
let nodes = [];
each(node.children, (idx, child) => {
const children = self._getChildren(child);
nodes = nodes.concat(children);
});
return node.children.concat(nodes);
}
_fillTreeStructure4Search(leaves) {
const self = this;
let result = [];
const queue = [];
each(leaves, (idx, node) => {
queue.push({ pId: node.pId });
result.push(node);
result = result.concat(self._getChildren(node));
});
queue.reverse();
while (isNotEmptyArray(queue)) {
const node = queue.pop();
const pNode = this.tree.search(this.tree.getRoot(), node.pId, "id");
if (pNode != null) {
pNode.open = true;
queue.push({ pId: pNode.pId });
result.push(pNode);
}
}
return uniqBy(
map(result, (idx, node) => self._createJson(node, node.open)),
"id"
);
}
_digest(v) {
const o = this.options;
if (isFunction(o.valueFormatter)) {
return o.valueFormatter(v);
}
const result = find(o.items, (i, item) => item.value === v);
return isNotNull(result) ? result.text : o.text ?? v;
}
_getShowText() {
return this.editor.getText();
}
stopEditing() {
this.searcher.stopSearch();
}
getSearcher() {
return this.searcher;
}
populate(items) {
this.options.items = items;
this._initData(items);
}
setValue(v) {
this.editor.setState(this._digest(v[0]));
}
getValue() {
return this.searcher.getValue();
}
focus() {
this.searcher.focus();
}
blur() {
this.searcher.blur();
}
setWaterMark(v) {
this.searcher.setWaterMark(v);
}
}