!(function () { /** * 多层级单选树增加无效值时状态,使用BI.config覆盖原组件,只能调用一次 * 新增watermark参数,表示空默认值,不传默认值为请选择,注意不能替代text,只是为了跟text区分开,text现在包含空默认值和暂不可用值两种情况。 * value存在且不存在于items中,为无效值,文本框标红 * value不存在,text不为watermark时,为暂不可用值,文本框不变,去除水印 */ BI.config("bi.multilayer_single_tree_combo", function (config) { var ERROR_CLASS = "combo-error"; var WATERMARK_CLASS = "bi-water-mark"; var WATERMARK = "请选择"; /** * 判断是否是有效值 * @param {Object} config * @param {String} value setValue传入的值 * @returns {Boolean} */ function isValueValid (options, value) { if (!BI.isObject(options)) { return true; } value = value || options.value; // null/undefined/空字符串作为空值 if (BI.isNull(value) || (value === "")) { return true; } var items = options.items || []; var itemIds = []; // 获取id列表 BI.each(items, function (i, item) { item && item.value && itemIds.push(item.value); }); return BI.contains(itemIds, value); } /** * 增加/去除标红className * @param {Object} widget * @param {String} value setValue传入的值 */ function changeInvalidClassName (widget, value) { if (!BI.isObject(widget)) { return; } var combo = widget.combo; var trigger = widget.textTrigger && widget.textTrigger.trigger && widget.textTrigger.trigger.trigger && widget.textTrigger.trigger.trigger.text && widget.textTrigger.trigger.trigger.text.element; var options = widget.options; var watermark = options.watermark || WATERMARK; if (isValueValid(options, value)) { combo && combo.element.removeClass(ERROR_CLASS); } else { combo && combo.element.addClass(ERROR_CLASS); } if (options.text !== watermark) { trigger.removeClass(WATERMARK_CLASS); } } config.listeners = config.listeners || []; // 新增mount生命周期回调 config.listeners.push({ eventName: BI.Events.MOUNT, action: function () { // 覆盖原setValue方法,调用原setValue前,修改样式 var _setValue = this.setValue; this.setValue = function (value) { _setValue.call(this, value); changeInvalidClassName(this, value && value[0]); }; // 立即触发一次样式变更,不需要传value changeInvalidClassName(this); } }); return config; }); var treeItems = [ {id: -1, pId: -2, value: "根目录", text: "根目录"}, {id: 1, pId: -1, value: "第一级目录1", text: "第一级目录1"}, {id: 11, pId: 1, value: "第二级文件1", text: "第二级文件1"}, {id: 12, pId: 1, value: "第二级目录2", text: "第二级目录2"}, {id: 121, pId: 12, value: "第三级目录1", text: "第三级目录1"}, {id: 122, pId: 12, value: "第三级文件1", text: "第三级文件1"}, {id: 1211, pId: 121, value: "第四级目录1", text: "第四级目录1"}, {id: 12111, pId: 1211, value: "第五级文件1", text: "第五级文件111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"}, {id: 2, pId: -1, value: "第一级目录2", text: "第一级目录2"}, {id: 21, pId: 2, value: "第二级目录3", text: "第二级目录3"}, {id: 22, pId: 2, value: "第二级文件2", text: "第二级文件2"}, {id: 211, pId: 21, value: "第三级目录2", text: "第三级目录2"}, {id: 212, pId: 21, value: "第三级文件2", text: "第三级文件2"}, {id: 2111, pId: 211, value: "第四级文件1", text: "第四级文件1"} ]; var TestTreeModel = BI.inherit(Fix.Model, { state: function () { return { items: BI.deepClone(treeItems), value: "第三级文件1" }; }, childContext: ["items"] }); BI.model("dec.amiba.test.tree.model", TestTreeModel); var TestTree = BI.inherit(BI.Widget, { _store: function () { return BI.Models.getModel("dec.amiba.test.tree.model"); }, props: { baseCls: "fine-test-tree" }, watch: { items: function (items) { console.log("items", items); this.treeRef.populate(items); }, value: function (v) { console.log("value", v); } }, render: function () { var self = this, o = this.options; return { type: "bi.vertical", height: 150, lgap: 20, tgap: 20, mounted: function () { // 测试增加树节点 var m = self.model; var newItems = [ {id: 3, pId: -1, value: "第三级目录1", text: "第三级目录1"}, {id: 31, pId: 3, value: "第三级文件1", text: "第三级文件1"} ]; m.items = m.items.concat(newItems); // 测试修改value; setTimeout(function () { console.log("setValue"); self.treeRef.setValue("不存在的值"); }, 3000); }, items: [ { type: "bi.label", textAlign: "left", text: "叶子节点单选" }, { type: "bi.multilayer_single_tree_combo", text: "无效值", watermark: "请选择", allowEdit: false, items: self.model.items, ref: function (ref) { self.treeRef = ref; }, width: 250, value: self.model.value, listeners: [{ eventName: "EVENT_CHANGE", action: function () { self.model.value = self.treeRef.getValue()[0]; } }] } ] }; } }); BI.shortcut("dec.amiba.test.tree", TestTree); })();!(function() { /** * 顶部组件,提供输入框添加todo项目 * 布局: bi.horizontal_auto 实现水平居中. bi.left_right_vertical_adapt 实现标题是输入框的靠左靠右垂直居中 */ var ToDoListHeader = BI.inherit(BI.Widget, { props: { // 指定组件的className baseCls: "my-todolist-header" }, render: function() { var self = this, o = this.options; return { type: "bi.horizontal_auto", // 水平居中布局 items: [ { el: { type: "bi.left_right_vertical_adapt", // 左右垂直居中布局 width: 600, height: o.height, items: { left: [ { el: { type: "bi.label", cls: "my-todolist-title", text: "FineUI ToDoList", height: o.height } } ], right: [ { el: { type: "bi.editor", ref: function(_ref) { self.editor = _ref; }, allowBlank: true, cls: "my-todolist-header-editor", watermark: "添加ToDo", width: 300, height: 24, listeners: [ { // 监听bi.editor 组件的"EVENT_ENTER"事件(即敲回车),触发事件ToDoListHeader.EVENT_ADD事件并将输入框值置空 eventName: "EVENT_ENTER", action: function() { // 注意:在这里this指向的是bi.editor的实例.通过bi.editor的getValue()方法获取输入框输入值. self.fireEvent(ToDoListHeader.EVENT_ADD, this.getValue()); self.editor.setValue(""); } } ] } } ] } } } ] }; } }); ToDoListHeader.EVENT_ADD = "EVENT_ADD"; BI.shortcut("my.todolist.header", ToDoListHeader); })();!(function() { /** * todo项列表 * */ var List = BI.inherit(BI.Widget, { props: { // 指定组件的className baseCls: "my-todolist-list", text: "正在进行" }, render: function() { var self = this, o = this.options; return { type: "bi.vertical", items: [ { el: { type: "bi.vertical_adapt", height: 40, items: [ { type: "bi.label", cls: "my-todolist-list-text", textAlign: "left", text: o.text, width: 580 }, { type: "bi.center_adapt", cls: "my-todolist-list-count-container", width: 20, height: 20, items: [ { el: { type: "bi.label", ref: function(_ref) { self.count = _ref; }, text: "0" } } ] } ] } }, { // 用bi.vertical布局作为列表项的容器. type: "bi.vertical", vgap: 10, ref: function(_ref) { self.list = _ref; }, items: this._createItems(o.items) } ] }; }, _createItems: function(items) { var self = this; return BI.map(items, function(index, item) { return BI.extend(item, { type: "bi.multi_select_item", // 节点采用复选节点展示 selected: item.done, // 已完成的todo项置为选中状态 disabled: item.done, // 已完成的todo项置为灰化状态 listeners: [ { // 为每个todo项添加"EVENT_CHANGE"事件监听,触发组件自身"EVENT_CHANGE"事件 eventName: "EVENT_CHANGE", action: function(v) { self.fireEvent("EVENT_CHANGE", v); } } ] }); }); }, _setCount: function(count) { this.count.setText(count); }, populate: function(items) { this.list.populate(this._createItems(items)); this._setCount(items.length); } }); BI.shortcut("my.todolist.list", List); })();!(function() { /** * todolist 组件 */ var ToDoList = BI.inherit(BI.Widget, { props: { baseCls: "fine-to-do-list" }, // 生命周期函数,在组件创建前 beforeCreate: function() { // 初始化存储数据 this.list = localStorage.getItem("fine-todolist") ? JSON.parse(localStorage.getItem("fine-todolist")) : []; }, render: function() { var self = this, o = this.options; return { type: "bi.vtape", // vtape布局,顶部高度固定,下部分列表占满高度 items: [ { el: { type: "my.todolist.header", // 顶部组件 listeners: [ { // 监听组件的EVENT_ADD事件,新建todo项 eventName: "EVENT_ADD", action: function(v) { self.addToDo(v); } } ], height: 40 }, height: 40 }, { type: "bi.horizontal_auto", // 水平居中布局 cls: "my-todolist-background", // 添加className items: [ { el: { type: "my.todolist.list", // need todo项列表 ref: function(_ref) { self.todolist = _ref; }, items: this._getNeedTodoList(), text: "正在进行", listeners: [ { // 监听EVENT_CHANGE事件,完成某一项todo eventName: "EVENT_CHANGE", action: function(v) { self.finishTodo(v); } } ], width: 600 } }, { el: { type: "my.todolist.list", // 已经完成的todo项列表 text: "已经完成", items: this._getAlreadyDoneList(), ref: function(_ref) { self.donelist = _ref; }, width: 600 } } ] } ] }; }, _updateLocalStorage: function() { localStorage.setItem("fine-todolist", JSON.stringify(this.list)); }, _getNeedTodoList: function() { return BI.filter(this.list, function(index, item) { return !item.done; }); }, _getAlreadyDoneList: function() { return BI.filter(this.list, function(index, item) { return item.done; }); }, /** * 添加todo项 * @param text todo项的内容 */ addToDo: function(text) { this.list.push({ value: BI.UUID(), text: text, done: false }); this.todolist.populate(this._getNeedTodoList()); this._updateLocalStorage(); }, /** * 完成某一项todo * @param v todo项的value */ finishTodo: function(v) { BI.some(this.list, function(index, item) { if (item.value === v) { item.done = true; } }); this.todolist.populate(this._getNeedTodoList()); this.donelist.populate(this._getAlreadyDoneList()); this._updateLocalStorage(); } }); BI.shortcut("my.todolist", ToDoList); })(); !(function () { var originData = { label: [ // "a7ed634a-0b59-4392-b92d-93a408803287" ], labels: [ { dimension: { id: "4ac8a4f8-5798-4c18-9cdf-9b1b9e7f9372", name: "部门", status: 1, description: null, createTime: "2022-03-29 15:44:36.114" }, labels: [ { id: "85253c00-268c-4c77-a87d-6c532853ff1d", name: "研发", description: null, dimensionId: "4ac8a4f8-5798-4c18-9cdf-9b1b9e7f9372", createTime: "2022-03-29 15:45:18.348" }, { id: "f18d4479-9220-43f5-a696-b408b59c75c0", name: "行政", description: null, dimensionId: "4ac8a4f8-5798-4c18-9cdf-9b1b9e7f9372", createTime: "2022-03-29 15:45:07.412" }, { id: "a7ed634a-0b59-4392-b92d-93a408803287", name: "财务", description: null, dimensionId: "4ac8a4f8-5798-4c18-9cdf-9b1b9e7f9372", createTime: "2022-03-29 15:45:12.398" } ] } ] }; var TestTreeSingleChooserModel = BI.inherit(Fix.Model, { state: function () { // 所有标签 var rawDimension = [], defaultDimension = {}; BI.each(originData.labels, function (i, item) { var temp = { text: item.dimension.name, value: item.dimension.id, children: BI.isNotEmptyArray(item.labels) ? BI.sortBy(BI.map(item.labels, function (i, label) { return { text: label.name, value: label.id }; }), [function (item) { return BI.makeFirstPY(item["name"]); }]) : [] }; rawDimension.push(temp); }); rawDimension = BI.sortBy(rawDimension, [function (item) { return BI.makeFirstPY(item["text"]); }]); !BI.isEmpty(defaultDimension) && rawDimension.unshift(defaultDimension); console.log("state --> labels", rawDimension); console.log("state --> label", originData.label); return { labels: rawDimension, label: originData.label }; } }); BI.model("dec.amiba.test.tree.single.chooser.model", TestTreeSingleChooserModel); var TestTreeSingleChooser = BI.inherit(BI.Widget, { _store: function () { return BI.Models.getModel("dec.amiba.test.tree.single.chooser.model"); }, watch: { labels: function (v) { console.log("labels", v); }, label: function (v) { console.log("label", v); } }, mounted: function () { var _this = this; setTimeout(function () { console.log("_this.dataLabelRef", _this.dataLabelRef); _this.dataLabelRef.setValue(["a7ed634a-0b59-4392-b92d-93a408803287"]); }, 3000); }, render: function () { var _this = this, o = this.options, m = this.model; console.log("_this.label", _this); return { type: "bi.vertical", height: 150, lgap: 20, tgap: 20, mounted: function () {}, items: [ { type: "bi.label", textAlign: "left", text: "层级单选下拉框" }, { type: "dec.amiba.components.tree.single.chooser.combo", watermark: "请选择", text: "无效值", width: 300, height: 32, value: m.label, items: m.labels, ref: function (ref) { _this.dataLabelRef = ref; }, listeners: [{ eventName: "EVENT_CHANGE", action: function (value) { m.label = value; } }] } ] }; } }); BI.shortcut("dec.amiba.test.tree.single.chooser", TestTreeSingleChooser); })();!(function () { /** * 组件说明: * - 只支持两级展开 * - 第二级只允许单选 * * 可用方法: * setValue([] or '') * getValue() => [] * populate() 刷新items * * 内部事件: * EVENT_CHANGE,参数:value */ var SingleChooserPopup = BI.inherit(BI.Widget, { props: function () { return { items: [], value: [], itemHeight: 32 }; }, mounted: function () { BI.each(this.refGroupList, function (index, refGroup) { refGroup.ref.element.hide(); }); }, render: function () { var o = this.options; var _this = this; return { type: "bi.button_group", items: this._createItems(o.items), layouts: [{ type: "bi.vertical", vgap: 5 }], ref: function (ref) { _this.btnGroupRef = ref; } }; }, populate: function (items) { this.btnGroupRef.populate(this._createItems(items)); }, getValue: function () { var value = []; BI.each(this.refGroupList, function (index, ref) { BI.any(ref.selectRefs, function (index, selectRef) { return (!BI.isNull(selectRef) && selectRef.isSelected()) ? (value.push(selectRef.getValue()), true) : false; }); }); return value; }, setValue: function (value) { value = BI.isArray(value) ? value : [value]; BI.each(this.refGroupList, function (index, ref) { BI.each(ref.selectRefs, function (index, selectRef) { !BI.isNull(selectRef) && selectRef.setSelected(BI.contains(value, selectRef.getValue())); }); }); }, _createItems: function (items) { var o = this.options; var _this = this; this.refGroupList = BI.map(items, function () { return { ref: null, selectRefs: [] }; }); if (BI.isNotEmptyArray(items)) { return BI.map(items, function (index, item) { var triggerRef = null; return { type: "bi.vertical", items: [{ type: "bi.basic_button", render: function () { return { type: "bi.htape", cls: "bi-list-item", height: o.itemHeight, items: [{ width: 16, lgap: 10, el: { type: "bi.icon_label", baseCls: "fold-font", height: o.itemHeight, ref: function (ref) { triggerRef = ref; } } }, { width: "fill", lgap: 5, el: { type: "bi.label", height: o.itemHeight, text: item.text, textAlign: "left" } }] }; }, listeners: [{ eventName: "BasicButton.EVENT_CHANGE", action: function () { triggerRef.element.toggleClass("unfold-font fold-font"); _this.refGroupList[index].ref.element.toggle(); } }] }, { el: { type: "bi.button_group", chooseType: BI.Selection.Multi, ref: function (ref) { _this.refGroupList[index].ref = ref; }, items: BI.map(item.children, function (idx, child) { return { type: "bi.multi_select_item", css: { paddingLeft: "40px" }, cls: "bi-list-item-active", ref: function (ref) { _this.refGroupList[index].selectRefs[idx] = ref; }, height: o.itemHeight, value: child.value, text: child.text, textLgap: 5, listeners: [{ eventName: "EVENT_CHANGE", action: function () { if (this.isSelected()) { var self = this; var ref = _this.refGroupList[index]; BI.each(ref.selectRefs, function (index, selectRef) { if (self !== selectRef && selectRef.isSelected()) { selectRef.setSelected(false); } }); } _this.fireEvent("EVENT_CHANGE", _this.getValue()); } }], logic: { dynamic: true } }; }), layouts: [{ type: "bi.vertical" }] } }] }; }); } return [{ type: "bi.label", height: 25, disabled: true, text: BI.i18nText("Fine-Plugin_AMB_Component_No_Available_Select_Items") }]; } }); BI.shortcut("dec.amiba.components.single.chooser.popup", SingleChooserPopup); /** * value: * [value, ...] * * items: * [{ * text: '', * value: '', * children: [{ * text: '', * value: '' * }], * ... * }] */ var SingleChooserCombo = BI.inherit(BI.Widget, { props: { itemHeight: 32, text: null, // 显示值,在显示值为无效值的情况下表现为水印样式 value: null, // 真实值,真实值为空的时候显示水印值 watermark: null, // 提示水印 baseCls: "dec-amiba-components-tree-single-chooser-combo" }, mounted: function () { var o = this.options; this.setValue(o.value, true); }, render: function () { var o = this.options; var _this = this; return { type: "bi.combo", cls: "bi-border", isDefaultInit: true, adjustLength: 2, el: { type: "bi.text_trigger", ref: function (ref) { _this.triggerRef = ref; }, height: o.height, readonly: o.readonly, tipType: o.tipType, warningTitle: o.warningTitle }, popup: { maxHeight: 240, minHeight: 25, el: { type: "bi.vertical", items: [{ type: "dec.amiba.components.single.chooser.popup", ref: function (ref) { _this.popupRef = ref; }, items: o.items, value: o.value, itemHeight: o.itemHeight, listeners: [{ eventName: "EVENT_CHANGE", action: function (value) { _this._adjustText(value, false); _this.fireEvent("EVENT_CHANGE", value); } }] }] } } }; }, /** * * @param {array} value 选中值 * @param {boolean}[optional] init 是否初始状态,mounted生命周期传true,其余传false或不传 */ setValue: function (value, init) { this._adjustText(value, init); this.popupRef.setValue(value); }, getValue: function () { return this.popupRef.getValue(); }, populate: function (items) { this.popupRef.populate(items); }, _digest: function (value, init, items) { var o = this.options; var text = BI.isFunction(o.watermark) ? o.watermark() : o.watermark, textCls = "bi-water-mark"; value = BI.isArray(value) ? value : [value]; var result = []; BI.each(items, function (i, item) { BI.each(item.children, function (i, leafItem) { if (BI.contains(value, leafItem.value)) { result.push(leafItem.text); } }); }); var showError = false; var valueText = result.length > 0 ? result.join(",") : BI.emptyStr; if (init && BI.isNotEmptyString(o.text)) { text = o.text; if (BI.isEqual(text, valueText)) { textCls = BI.emptyStr; } else { showError = true; } } else if (BI.isNotEmptyString(valueText)) { text = valueText; textCls = BI.emptyStr; } this._applyComboClass(showError); return { text: text, textCls: textCls }; }, /** * 初始状态下,设置的显示值的优先级最高,根据真实值构造出来的文本值次之,水印文本最末 * 非初始状态下,显示值不再有效 * * @param {*} value 真实值 * @param {*} init 是否为初始状态 */ _adjustText: function (value, init) { var o = this.options; var digestObj = this._digest(value, init, o.items); this.triggerRef.setText(digestObj.text); this.triggerRef.setTextCls(digestObj.textCls); }, // 切换下拉树控件样式 _applyComboClass: function (showError) { if (showError) { this.element.addClass("combo-error"); } else { this.element.removeClass("combo-error"); } } }); BI.shortcut("dec.amiba.components.tree.single.chooser.combo", SingleChooserCombo); })();!(function () { // 将todolist组件挂载到#wrapper上. // BI.createWidget({ // type: "my.todolist", // element: "#wrapper" // }); // 挂载下拉树测试组件 // BI.createWidget({ // type: "dec.amiba.test.tree", // element: "#wrapper" // }); // 挂载每组单选下拉框组件 BI.createWidget({ type: "dec.amiba.test.tree.single.chooser", element: "#wrapper" }); })();