|
|
|
import {
|
|
|
|
shortcut,
|
|
|
|
extend,
|
|
|
|
emptyFn,
|
|
|
|
each,
|
|
|
|
isKey,
|
|
|
|
UUID,
|
|
|
|
isNotEmptyArray,
|
|
|
|
defaults,
|
|
|
|
createWidget,
|
|
|
|
Tree,
|
|
|
|
nextTick,
|
|
|
|
Selection,
|
|
|
|
Controller,
|
|
|
|
Events,
|
|
|
|
VerticalLayout,
|
|
|
|
AdaptiveLayout,
|
|
|
|
isNull,
|
|
|
|
isArray
|
|
|
|
} from "@/core";
|
|
|
|
import { Pane, CustomTree, Loader, ButtonTree } from "@/base";
|
|
|
|
import { BasicTreeNode, BasicTreeItem, TreeExpander } from "@/case";
|
|
|
|
|
|
|
|
@shortcut()
|
|
|
|
export class MultiLayerSelectLevelTree extends Pane {
|
|
|
|
static xtype = "bi.multilayer_select_level_tree";
|
|
|
|
|
|
|
|
static EVENT_CHANGE = "EVENT_CHANGE";
|
|
|
|
|
|
|
|
_defaultConfig() {
|
|
|
|
return extend(super._defaultConfig(...arguments), {
|
|
|
|
baseCls: "bi-multilayer-select-level-tree",
|
|
|
|
isDefaultInit: false,
|
|
|
|
items: [],
|
|
|
|
itemsCreator: emptyFn,
|
|
|
|
keywordGetter: emptyFn,
|
|
|
|
value: "",
|
|
|
|
scrollable: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_init() {
|
|
|
|
const o = this.options;
|
|
|
|
super._init(...arguments);
|
|
|
|
|
|
|
|
this.storeValue = o.value;
|
|
|
|
|
|
|
|
this.initTree(this.options.items);
|
|
|
|
|
|
|
|
this.check();
|
|
|
|
}
|
|
|
|
|
|
|
|
_formatItems(nodes, layer, pNode) {
|
|
|
|
const self = this,
|
|
|
|
o = this.options;
|
|
|
|
const keyword = o.keywordGetter();
|
|
|
|
each(nodes, (i, node) => {
|
|
|
|
const extend = {
|
|
|
|
isFirstNode: i === 0,
|
|
|
|
isLastNode: i === nodes.length - 1,
|
|
|
|
height: BI.SIZE_CONSANTS.LIST_ITEM_HEIGHT,
|
|
|
|
};
|
|
|
|
node.layer = layer;
|
|
|
|
if (!isKey(node.id)) {
|
|
|
|
node.id = UUID();
|
|
|
|
}
|
|
|
|
node.keyword = node.keyword || keyword;
|
|
|
|
extend.pNode = pNode;
|
|
|
|
if (
|
|
|
|
node.isParent === true ||
|
|
|
|
node.parent === true ||
|
|
|
|
isNotEmptyArray(node.children)
|
|
|
|
) {
|
|
|
|
extend.type = BasicTreeNode.xtype;
|
|
|
|
extend.selectable = true;
|
|
|
|
defaults(node, extend);
|
|
|
|
self._formatItems(node.children, layer + 1, node);
|
|
|
|
} else {
|
|
|
|
extend.type = BasicTreeItem.xtype;
|
|
|
|
defaults(node, extend);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
_assertId(sNodes) {
|
|
|
|
each(sNodes, (i, node) => {
|
|
|
|
node.id = node.id || UUID();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
initTree(nodes) {
|
|
|
|
const self = this,
|
|
|
|
o = this.options;
|
|
|
|
let hasNext = false;
|
|
|
|
this.empty();
|
|
|
|
this._assertId(nodes);
|
|
|
|
this.tree = createWidget({
|
|
|
|
type: CustomTree.xtype,
|
|
|
|
cls: "tree-view display-table",
|
|
|
|
expander: {
|
|
|
|
type: TreeExpander.xtype,
|
|
|
|
selectable: true,
|
|
|
|
isDefaultInit: o.isDefaultInit,
|
|
|
|
el: {},
|
|
|
|
popup: {
|
|
|
|
type: CustomTree.xtype,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
items: this._formatItems(Tree.transformToTreeFormat(nodes), 0),
|
|
|
|
itemsCreator(op, callback) {
|
|
|
|
op.times === 1 &&
|
|
|
|
!op.node &&
|
|
|
|
nextTick(() => {
|
|
|
|
self.loading();
|
|
|
|
});
|
|
|
|
o.itemsCreator(op, ob => {
|
|
|
|
hasNext = ob.hasNext;
|
|
|
|
op.times === 1 && !op.node && self._populate(ob.items);
|
|
|
|
callback(
|
|
|
|
self._formatItems(
|
|
|
|
Tree.transformToTreeFormat(ob.items),
|
|
|
|
op.node ? op.node.layer + 1 : 0,
|
|
|
|
op.node
|
|
|
|
)
|
|
|
|
);
|
|
|
|
self.setValue(self.storeValue);
|
|
|
|
op.times === 1 &&
|
|
|
|
!op.node &&
|
|
|
|
nextTick(() => {
|
|
|
|
self.loaded();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
value: o.value,
|
|
|
|
|
|
|
|
el: {
|
|
|
|
type: Loader.xtype,
|
|
|
|
isDefaultInit: o.itemsCreator !== emptyFn,
|
|
|
|
el: {
|
|
|
|
type: ButtonTree.xtype,
|
|
|
|
chooseType:
|
|
|
|
o.chooseType === Selection.None
|
|
|
|
? Selection.None
|
|
|
|
: Selection.Default, // 不使用buttontree内部getValue逻辑
|
|
|
|
behaviors: o.behaviors,
|
|
|
|
layouts: [
|
|
|
|
{
|
|
|
|
type: VerticalLayout.xtype,
|
|
|
|
}
|
|
|
|
],
|
|
|
|
},
|
|
|
|
hasNext() {
|
|
|
|
return hasNext;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
this.tree.on(Controller.EVENT_CHANGE, function (type, value) {
|
|
|
|
self.fireEvent(Controller.EVENT_CHANGE, arguments);
|
|
|
|
if (type === Events.CLICK) {
|
|
|
|
self.setValue(value);
|
|
|
|
self.fireEvent(
|
|
|
|
MultiLayerSelectLevelTree.EVENT_CHANGE,
|
|
|
|
arguments
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
createWidget({
|
|
|
|
type: AdaptiveLayout.xtype,
|
|
|
|
element: this,
|
|
|
|
scrollable: o.scrollable,
|
|
|
|
items: [this.tree],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_populate() {
|
|
|
|
super.populate(...arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
populate(nodes) {
|
|
|
|
this._populate(nodes);
|
|
|
|
isNull(nodes)
|
|
|
|
? this.tree.populate()
|
|
|
|
: this.tree.populate(
|
|
|
|
this._formatItems(Tree.transformToTreeFormat(nodes), 0)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
setValue(v) {
|
|
|
|
// getValue依赖于storeValue, 那么不选的时候就不要更新storeValue了
|
|
|
|
if (this.options.chooseType === Selection.None) {
|
|
|
|
} else {
|
|
|
|
this.storeValue = v;
|
|
|
|
this.tree.setValue(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getValue() {
|
|
|
|
return isArray(this.storeValue)
|
|
|
|
? this.storeValue
|
|
|
|
: isNull(this.storeValue)
|
|
|
|
? []
|
|
|
|
: [this.storeValue];
|
|
|
|
}
|
|
|
|
|
|
|
|
getAllLeaves() {
|
|
|
|
return this.tree.getAllLeaves();
|
|
|
|
}
|
|
|
|
|
|
|
|
getNodeById(id) {
|
|
|
|
return this.tree.getNodeById(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
getNodeByValue(id) {
|
|
|
|
return this.tree.getNodeByValue(id);
|
|
|
|
}
|
|
|
|
}
|