import _ from 'lodash' import {tree} from '../Defaults' import {baseConfig} from "./base"; import {lookupFn, lookupScope} from "../lib/lib"; import {calcObject, calcObjectFlat, invokeServer} from "../lib/systemLib"; import {msg} from "../message"; export default function () { Ext.define('Yvan.Tree', { extend: 'Ext.tree.Panel', alias: 'widget.yvtree', xtype: 'yvtree', constructor(config) { const newConfig = _.defaultsDeep({ // 强制性属性 }, baseConfig(config, 'row-item'), config, tree) this.superclass.constructor.call(this, newConfig) }, /** * 在根节点上增加一个节点,会触发 addNode 事件 * @param props */ addRoot(props) { const me = this const tableNode = me.getRootNode() const fieldNode = tableNode.createNode(new Ext.data.NodeInterface({})) if (_.isFunction(props)) { props = props.call(this, parent) } _.forOwn(props, (value, key) => { fieldNode.set(key, value) }) const node = tableNode.appendChild(fieldNode) me.ensureVisible(node) me.setSelection(node) me.fireEvent('addNode', me, { parent: tableNode, node: node, }); }, addLast(props) { const me = this const sel = me.selModel.getSelection() if (!sel || sel.length <= 0) { msg('请选择一个要添加的同级节点路径') return } const parent = sel[0].parentNode ? sel[0].parentNode : me.getRootNode() const fieldNode = parent.createNode(new Ext.data.NodeInterface({})) if (_.isFunction(props)) { props = props.call(this, parent) } _.forOwn(props, (value, key) => { fieldNode.set(key, value) }) const node = parent.appendChild(fieldNode) me.ensureVisible(node) me.setSelection(node) me.fireEvent('addNode', me, { parent: parent, node: node, }); }, addChildren(props) { const me = this const sel = me.selModel.getSelection() if (!sel || sel.length <= 0) { msg('请选择一个要添加子节点的路径') return } const parent = sel[0] if (_.isFunction(props)) { props = props.call(this, parent) } const fieldNode = parent.createNode(new Ext.data.NodeInterface({})) _.forOwn(props, (value, key) => { fieldNode.set(key, value) }) const node = parent.appendChild(fieldNode) parent.expand() me.ensureVisible(node) me.setSelection(node) me.fireEvent('addNode', me, { parent: parent, node: node, }); }, initComponent() { const me = this const {config} = me const scope = lookupScope(this) if (!window["IS_DESIGN_MODE"]) { // 转换 dataSource 属性 convertDataSource(me, scope, config) } this.superclass.initComponent.call(this) this.on({ afterrender(sender) { const me = this const {config} = this const {dataSource} = config if (config.autoLoad) { if (config.dataSourceCallbackFn) { me.reload() } else if (_.isPlainObject(dataSource) && dataSource.method === 'invoke') { me.reload() } } } }) }, _setDataReal(value) { const me = this // me.setStore(new Ext.data.TreeStore({ // root: { // expanded: true, // // children: value // children: [ // { // id: '1', text: 'A', // children: [ // {id: '1', text: 'A',}, // {id: '2', text: 'B'}, // ] // }, // {id: '2', text: 'B'}, // ] // } // })) me.store.setRoot({ expanded: true, children: value }) // me.store = new Ext.data.TreeStore({ // root: { // expanded: true, // // children: value // children: [ // { // id: '1', text: 'A', // children: [ // {id: '1', text: 'A',}, // {id: '2', text: 'B'}, // ] // }, // {id: '2', text: 'B'}, // ] // } // }) }, /** * 重新载入数据(重新计算参数) */ reload(reloadParams = {}) { const me = this const {config} = me if (config.dataSourceCallbackFn) { // 函数请求刷新 const scope = lookupScope(this) // me.setLoading(true) config.dataSourceCallbackFn.call(scope, me, { successCallback(value) { me._setDataReal(value) // me.setLoading(false) me.fireEvent('dataLoadComplete', me, true, value); }, failCallback(error) { // me.setLoading(false) me.fireEvent('dataLoadComplete', me, false, error); } }) return } const {dataSource} = config if (_.isPlainObject(dataSource) && dataSource.method === 'invoke' && !window["IS_DESIGN_MODE"]) { const scope = lookupScope(me) const params = calcObjectFlat(scope.viewModel.data, _.defaultsDeep({}, reloadParams, dataSource.params),) me.setLoading(true) invokeServer(dataSource.url, params) .then(res => { me._setDataReal(res.data) me.fireEvent('dataLoadComplete', me, res) }) .finally(() => { me.setLoading(false) }) } }, filterByText(text) { this.filterBy(text, 'text'); }, filterBy(text, by) { this.clearFilter(); const view = this.getView(), me = this, nodesAndParents = []; this.getRootNode().cascadeBy(function (tree, view) { let currNode = this; if (currNode && currNode.data[by] && currNode.data[by].toString().toLowerCase().indexOf(text.toLowerCase()) > -1) { me.expandPath(currNode.getPath()); while (currNode.parentNode) { nodesAndParents.push(currNode.id); currNode = currNode.parentNode; } } }, null, [me, view]); this.getRootNode().cascadeBy(function (tree, view) { var uiNode = view.getNodeByRecord(this); if (uiNode && !Ext.Array.contains(nodesAndParents, this.id)) { Ext.get(uiNode).setDisplayed('none'); } }, null, [me, view]); }, clearFilter() { const view = this.getView(); this.getRootNode().cascadeBy(function (tree, view) { var uiNode = view.getNodeByRecord(this); if (uiNode) { Ext.get(uiNode).setDisplayed('table-row'); } }, null, [this, view]); }, root: [], rootVisible: false, tbar: [ { xtype: 'trigger', triggerCls: 'x-form-clear-trigger', onTriggerClick(sender) { sender.setValue(''); const scope = sender.up("yvtree") scope.clearFilter() }, flex: 1, emptyText: '搜索过滤', enableKeyEvents: true, listeners: { keyup: { fn(sender, e) { if (e.ESC == e.getKey()) { sender.onTriggerClick(sender); } else { const scope = sender.up("yvtree") scope.filterByText(this.getRawValue()); } }, buffer: 500 } } }, { xtype: 'button', iconCls: 'x-fa fa-refresh', tooltip: '刷新', listeners: { click(sender) { const scope = sender.up("yvtree") scope.reload() } } }, { xtype: 'button', iconCls: 'x-fa fa-plus-square-o', tooltip: '全部展开', listeners: { click(sender) { const scope = sender.up("yvtree") scope.expandAll() } } }, { xtype: 'button', iconCls: 'x-fa fa-minus-square-o', tooltip: '全部收起', listeners: { click(sender) { const scope = sender.up("yvtree") scope.collapseAll() } } } ], }) } function convertDataSource(sender, scope, newConfig) { if (typeof newConfig.store !== 'undefined') { // 有 store 属性的情况下,不做任何事 return } if (typeof newConfig.dataSource === 'undefined') { // 没有定义 dataSource 的情况下,不做任何事 return } let {dataSource} = newConfig if (typeof dataSource === 'string') { // dataSource 是字符串的情况下,找到成员函数 dataSource = lookupFn(scope, dataSource) } if (typeof dataSource === 'function') { // dataSource 是函数的情况下,在 afterrender 之后进行回调 newConfig.store = new Ext.data.TreeStore({ root: { expanded: true, children: [] } }) newConfig.dataSourceCallbackFn = dataSource return } // throw new TypeError('无法识别的调用方法') }