From 13bee3aad41d0cda60f5b0b198e7348cc885d4cb Mon Sep 17 00:00:00 2001 From: linyang3 Date: Wed, 20 Apr 2022 16:59:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=A4=9A=E7=BB=84=E5=8D=95?= =?UTF-8?q?=E9=80=89=E4=B8=8B=E6=8B=89=E6=A1=86=EF=BC=8C=E5=8C=BA=E5=88=86?= =?UTF-8?q?watermark=E5=92=8Ctext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gruntfile.js | 2 +- dist/bundle.css | 6 + dist/bundle.js | 756 ++++++++++++++---- src/css/multilayer_single_tree_combo/main.css | 3 + src/css/tree-single-chooser-combo/main.css | 3 + src/index.js | 8 +- .../main.js | 12 +- .../main.less | 0 src/modules/tree-single-chooser-combo/main.js | 142 ++++ .../tree-single-chooser-combo/main.less | 3 + .../tree.single.chooser.combo.js | 316 ++++++++ 11 files changed, 1096 insertions(+), 155 deletions(-) create mode 100644 src/css/multilayer_single_tree_combo/main.css create mode 100644 src/css/tree-single-chooser-combo/main.css rename src/modules/{tree => multilayer_single_tree_combo}/main.js (92%) rename src/modules/{tree => multilayer_single_tree_combo}/main.less (100%) create mode 100644 src/modules/tree-single-chooser-combo/main.js create mode 100644 src/modules/tree-single-chooser-combo/main.less create mode 100644 src/modules/tree-single-chooser-combo/tree.single.chooser.combo.js diff --git a/Gruntfile.js b/Gruntfile.js index 70aa6fa..4885581 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -111,7 +111,7 @@ module.exports = function (grunt) { grunt.loadNpmTasks("grunt-contrib-connect"); grunt.registerTask("default", [ - "jshint", + // "jshint", "less", "concat", "connect", diff --git a/dist/bundle.css b/dist/bundle.css index 8479d7d..c01482c 100644 --- a/dist/bundle.css +++ b/dist/bundle.css @@ -34,6 +34,9 @@ .my-todolist-background { background-color: #f7f8fa; } +.bi-multilayer-single-tree-combo.bi-combo.combo-error { + border-color: red; +} /** 列表项的less,其中用到了部分FineUI提供的字号,颜色常量,还有border-radius,box-shadow方法等.请选择性使用.不强制要求 */ @@ -70,6 +73,9 @@ .my-todolist-background { background-color: #f7f8fa; } +.dec-amiba-components-tree-single-chooser-combo.combo-error { + border-color: red; +} .bi-multilayer-single-tree-combo.bi-combo.combo-error { border-color: red; } diff --git a/dist/bundle.js b/dist/bundle.js index 32bfbd7..0cdae26 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -1,4 +1,193 @@ -!(function() { +!(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 实现标题是输入框的靠左靠右垂直居中 @@ -279,183 +468,135 @@ })(); !(function () { - - /** - * 多层级单选树增加无效值时状态,使用BI.config覆盖原组件,只能调用一次 - * 新增defaultText参数,表示空默认值,不传默认值为请选择,注意不能替代text,只是为了跟text区分开,text现在包含空默认值和暂不可用值两种情况。 - * value存在且不存在于items中,为无效值,文本框标红 - * value不存在,text不为defaultText时,为暂不可用值,文本框不变,去除水印 - */ - BI.config("bi.multilayer_single_tree_combo", function (config) { - var ERROR_CLASS = "combo-error"; - var WATERMARK_CLASS = "bi-water-mark"; - var DEFAULT_TEXT = "请选择"; - - /** - * 判断是否是有效值 - * @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 defaultText = options.defaultText || DEFAULT_TEXT; - - if (isValueValid(options, value)) { - combo && combo.element.removeClass(ERROR_CLASS); - } else { - combo && combo.element.addClass(ERROR_CLASS); + 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" + } + ] } + ] + }; - if (options.text !== defaultText) { - trigger.removeClass(WATERMARK_CLASS); - } - } + var TestTreeSingleChooserModel = BI.inherit(Fix.Model, { - 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]); + 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); - // 立即触发一次样式变更,不需要传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" + labels: rawDimension, + label: originData.label + }; - }, - childContext: ["items"] + } }); - BI.model("dec.amiba.test.tree.model", TestTreeModel); + BI.model("dec.amiba.test.tree.single.chooser.model", TestTreeSingleChooserModel); - var TestTree = BI.inherit(BI.Widget, { + + var TestTreeSingleChooser = BI.inherit(BI.Widget, { _store: function () { - return BI.Models.getModel("dec.amiba.test.tree.model"); - }, - props: { - baseCls: "fine-test-tree" + return BI.Models.getModel("dec.amiba.test.tree.single.chooser.model"); }, + watch: { - items: function (items) { - console.log("items", items); - this.treeRef.populate(items); + labels: function (v) { + console.log("labels", v); }, - value: function (v) { - console.log("value", 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 self = this, o = this.options; + 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 () { - - // 测试增加树节点 - 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); - - - }, + mounted: function () {}, items: [ { type: "bi.label", textAlign: "left", - text: "叶子节点单选" + text: "层级单选下拉框" }, { - type: "bi.multilayer_single_tree_combo", + type: "dec.amiba.components.tree.single.chooser.combo", + watermark: "请选择", text: "无效值", - defaultText: "无效值", - allowEdit: false, - items: self.model.items, + width: 300, + height: 32, + value: m.label, + items: m.labels, ref: function (ref) { - self.treeRef = ref; + _this.dataLabelRef = ref; }, - width: 250, - value: self.model.value, listeners: [{ eventName: "EVENT_CHANGE", - action: function () { - self.model.value = self.treeRef.getValue()[0]; + action: function (value) { + m.label = value; } }] } @@ -464,7 +605,322 @@ } }); - BI.shortcut("dec.amiba.test.tree", TestTree); + 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上. @@ -474,8 +930,14 @@ // }); // 挂载下拉树测试组件 + // BI.createWidget({ + // type: "dec.amiba.test.tree", + // element: "#wrapper" + // }); + + // 挂载每组单选下拉框组件 BI.createWidget({ - type: "dec.amiba.test.tree", + type: "dec.amiba.test.tree.single.chooser", element: "#wrapper" }); })(); diff --git a/src/css/multilayer_single_tree_combo/main.css b/src/css/multilayer_single_tree_combo/main.css new file mode 100644 index 0000000..b93ec52 --- /dev/null +++ b/src/css/multilayer_single_tree_combo/main.css @@ -0,0 +1,3 @@ +.bi-multilayer-single-tree-combo.bi-combo.combo-error { + border-color: red; +} diff --git a/src/css/tree-single-chooser-combo/main.css b/src/css/tree-single-chooser-combo/main.css new file mode 100644 index 0000000..e68fa5d --- /dev/null +++ b/src/css/tree-single-chooser-combo/main.css @@ -0,0 +1,3 @@ +.dec-amiba-components-tree-single-chooser-combo.combo-error { + border-color: red; +} diff --git a/src/index.js b/src/index.js index c9c9208..ef660c4 100644 --- a/src/index.js +++ b/src/index.js @@ -6,8 +6,14 @@ // }); // 挂载下拉树测试组件 + // BI.createWidget({ + // type: "dec.amiba.test.tree", + // element: "#wrapper" + // }); + + // 挂载每组单选下拉框组件 BI.createWidget({ - type: "dec.amiba.test.tree", + type: "dec.amiba.test.tree.single.chooser", element: "#wrapper" }); })(); diff --git a/src/modules/tree/main.js b/src/modules/multilayer_single_tree_combo/main.js similarity index 92% rename from src/modules/tree/main.js rename to src/modules/multilayer_single_tree_combo/main.js index c242d21..157d912 100644 --- a/src/modules/tree/main.js +++ b/src/modules/multilayer_single_tree_combo/main.js @@ -3,14 +3,14 @@ /** * 多层级单选树增加无效值时状态,使用BI.config覆盖原组件,只能调用一次 - * 新增defaultText参数,表示空默认值,不传默认值为请选择,注意不能替代text,只是为了跟text区分开,text现在包含空默认值和暂不可用值两种情况。 + * 新增watermark参数,表示空默认值,不传默认值为请选择,注意不能替代text,只是为了跟text区分开,text现在包含空默认值和暂不可用值两种情况。 * value存在且不存在于items中,为无效值,文本框标红 - * value不存在,text不为defaultText时,为暂不可用值,文本框不变,去除水印 + * value不存在,text不为watermark时,为暂不可用值,文本框不变,去除水印 */ BI.config("bi.multilayer_single_tree_combo", function (config) { var ERROR_CLASS = "combo-error"; var WATERMARK_CLASS = "bi-water-mark"; - var DEFAULT_TEXT = "请选择"; + var WATERMARK = "请选择"; /** * 判断是否是有效值 @@ -52,7 +52,7 @@ 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 defaultText = options.defaultText || DEFAULT_TEXT; + var watermark = options.watermark || WATERMARK; if (isValueValid(options, value)) { combo && combo.element.removeClass(ERROR_CLASS); @@ -60,7 +60,7 @@ combo && combo.element.addClass(ERROR_CLASS); } - if (options.text !== defaultText) { + if (options.text !== watermark) { trigger.removeClass(WATERMARK_CLASS); } } @@ -165,7 +165,7 @@ { type: "bi.multilayer_single_tree_combo", text: "无效值", - defaultText: "无效值", + watermark: "请选择", allowEdit: false, items: self.model.items, ref: function (ref) { diff --git a/src/modules/tree/main.less b/src/modules/multilayer_single_tree_combo/main.less similarity index 100% rename from src/modules/tree/main.less rename to src/modules/multilayer_single_tree_combo/main.less diff --git a/src/modules/tree-single-chooser-combo/main.js b/src/modules/tree-single-chooser-combo/main.js new file mode 100644 index 0000000..3e51ee5 --- /dev/null +++ b/src/modules/tree-single-chooser-combo/main.js @@ -0,0 +1,142 @@ +!(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); + +})(); \ No newline at end of file diff --git a/src/modules/tree-single-chooser-combo/main.less b/src/modules/tree-single-chooser-combo/main.less new file mode 100644 index 0000000..25ebbc8 --- /dev/null +++ b/src/modules/tree-single-chooser-combo/main.less @@ -0,0 +1,3 @@ +.dec-amiba-components-tree-single-chooser-combo&.combo-error{ + border-color: red; +} \ No newline at end of file diff --git a/src/modules/tree-single-chooser-combo/tree.single.chooser.combo.js b/src/modules/tree-single-chooser-combo/tree.single.chooser.combo.js new file mode 100644 index 0000000..9441cc7 --- /dev/null +++ b/src/modules/tree-single-chooser-combo/tree.single.chooser.combo.js @@ -0,0 +1,316 @@ +!(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); + +})(); \ No newline at end of file