diff --git a/packages/fineui/src/base/combination/bubble.js b/packages/fineui/src/base/combination/bubble.js index af3da3cef..79d06ebc5 100644 --- a/packages/fineui/src/base/combination/bubble.js +++ b/packages/fineui/src/base/combination/bubble.js @@ -72,6 +72,7 @@ export class Bubble extends Widget { popup: {}, comboClass: "bi-combo-popup", hoverClass: "bi-combo-hover", + extraModifiers: [] }); } @@ -410,7 +411,16 @@ export class Bubble extends Widget { } _popupView(e) { - const { adjustXOffset, showArrow, adjustYOffset, adjustLength, placement, hideWhenClickOutside, hideWhenBlur } = + const { + adjustXOffset, + showArrow, + adjustYOffset, + adjustLength, + placement, + hideWhenClickOutside, + hideWhenBlur, + extraModifiers + } = this.options; this._assertPopupViewRender(); this.fireEvent(Bubble.EVENT_BEFORE_POPUPVIEW); @@ -429,6 +439,7 @@ export class Bubble extends Widget { offset: () => [adjustXOffset, (showArrow ? 12 : 0) + (adjustYOffset + adjustLength)], }, }, + ...extraModifiers ]; if (this.options.showArrow) { modifiers.push({ diff --git a/packages/fineui/src/base/foundation/message.js b/packages/fineui/src/base/foundation/message.js index 3866f2475..5eb3e9d69 100644 --- a/packages/fineui/src/base/foundation/message.js +++ b/packages/fineui/src/base/foundation/message.js @@ -17,258 +17,273 @@ import { i18nText, KeyCode, isPlainObject, - SIZE_CONSANTS + SIZE_CONSANTS, + CenterAdaptLayout, + VerticalLayout, + HTapeLayout, + RightVerticalAdaptLayout } from "../../core"; -import { Toast } from "../single"; +import { Button, IconLabel, Label, Toast } from "../single"; -export const Msg = (() => { - let $mask, $pop; +let $mask, $pop; - const messageShows = []; +const messageShows = []; - const toastStack = []; +const toastStack = []; - const defaultConfig = { - buttonHeight: 24, - }; +const AlertLevel = { + WARNING: 'warning', + INFO: 'info', + ERROR: 'error', + SUCCESS: 'success', +} - return { - alert(title, message, callback, config = defaultConfig) { - this._show(false, title, message, callback, config); - }, - confirm(title, message, callback, config = defaultConfig) { - this._show(true, title, message, callback, config); - }, - prompt(title, message, value, callback, min_width) { - // Msg.prompt(title, message, value, callback, min_width); - }, - toast(message, options, context) { - isString(options) && (options = { level: options }); - options = options || {}; - context = context || Widget._renderEngine.createElement("body"); - const level = options.level || "common"; - const autoClose = isNull(options.autoClose) ? true : options.autoClose; - const callback = isFunction(options.callback) ? options.callback : emptyFn; - const toast = createWidget({ - type: "bi.toast", - cls: "bi-message-animate bi-message-leave", - level, - autoClose, - closable: options.closable, - text: message, - listeners: [ - { - eventName: Toast.EVENT_DESTORY, - action() { - remove(toastStack, toast.element); - let _height = SIZE_CONSANTS.TOAST_TOP; - each(toastStack, (i, element) => { - element.css({ top: _height }); - _height += element.outerHeight() + 10; - }); - callback(); - }, - } - ], - }); - let height = SIZE_CONSANTS.TOAST_TOP; - each(toastStack, (i, element) => { - height += element.outerHeight() + 10; - }); - createWidget({ - type: "bi.absolute", - element: context, - items: [ - { - el: toast, - left: "50%", - top: height, - } - ], - }); - toastStack.push(toast.element); - toast.element.css({ "margin-left": (-1 * toast.element.outerWidth()) / 2 }); - toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); +function getIconCls(level) { + switch (level) { + case AlertLevel.ERROR: + return 'alert-error-font'; + case AlertLevel.SUCCESS: + return 'alert-success-font'; + case AlertLevel.INFO: + return 'alert-info-font'; + case AlertLevel.WARNING: + default: + return 'alert-warning-font'; + } +} - autoClose && - delay(() => { - toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); - toast.destroy?.(); - }, 5000); - return function() { - toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); - toast.destroy?.(); - }; - }, - _show(hasCancel, title, message, callback, config) { - isNull($mask) && - ($mask = Widget._renderEngine - .createElement("
") - .css({ - position: "absolute", - zIndex: zIndex_tip - 2, - top: 0, - left: 0, - right: 0, - bottom: 0, - opacity: 0.5, - }) - .appendTo("body")); - $pop = Widget._renderEngine - .createElement("
") - .css({ - position: "absolute", - zIndex: zIndex_tip - 1, - top: 0, - left: 0, - right: 0, - bottom: 0, - }) - .appendTo("body"); - - function close() { - messageShows[messageShows.length - 1].destroy(); - messageShows.pop(); - if (messageShows.length === 0) { - $mask.remove(); - $mask = null; +export const Msg = { + alert(title, message, callback, config) { + _show(false, title, message, callback, config); + }, + confirm(title, message, callback, config) { + _show(true, title, message, callback, config); + }, + toast(message, options, context) { + isString(options) && (options = { level: options }); + options = options || {}; + context = context || Widget._renderEngine.createElement("body"); + const level = options.level || "common"; + const autoClose = isNull(options.autoClose) ? true : options.autoClose; + const callback = isFunction(options.callback) ? options.callback : emptyFn; + const toast = createWidget({ + type: "bi.toast", + cls: "bi-message-animate bi-message-leave", + level, + autoClose, + closable: options.closable, + text: message, + listeners: [ + { + eventName: Toast.EVENT_DESTORY, + action() { + remove(toastStack, toast.element); + let _height = SIZE_CONSANTS.TOAST_TOP; + each(toastStack, (i, element) => { + element.css({ top: _height }); + _height += element.outerHeight() + 10; + }); + callback(); + }, + } + ], + }); + let height = SIZE_CONSANTS.TOAST_TOP; + each(toastStack, (i, element) => { + height += element.outerHeight() + 10; + }); + createWidget({ + type: "bi.absolute", + element: context, + items: [ + { + el: toast, + left: "50%", + top: height, } - } + ], + }); + toastStack.push(toast.element); + toast.element.css({ "margin-left": (-1 * toast.element.outerWidth()) / 2 }); + toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); + + autoClose && + delay(() => { + toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); + toast.destroy?.(); + }, 5000); + + return function() { + toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); + toast.destroy?.(); + }; + }, +}; + +function _show(hasCancel, title, message, callback, config = {}) { + config = { + buttonHeight: 28, + cancelText: i18nText("BI-Basic_Cancel"), + sureText: i18nText("BI-Basic_OK"), + level: AlertLevel.WARNING, + ...config, + } + isNull($mask) && + ($mask = Widget._renderEngine + .createElement("
") + .css({ + position: "absolute", + zIndex: zIndex_tip - 2, + top: 0, + left: 0, + right: 0, + bottom: 0, + opacity: 0.5, + }) + .appendTo("body")); + $pop = Widget._renderEngine + .createElement("
") + .css({ + position: "absolute", + zIndex: zIndex_tip - 1, + top: 0, + left: 0, + right: 0, + bottom: 0, + }) + .appendTo("body"); - const controlItems = []; - if (hasCancel === true) { - controlItems.push({ - el: { - type: "bi.button", - height: config.buttonHeight, - text: i18nText("BI-Basic_Cancel"), - light: true, - handler() { + function close() { + messageShows[messageShows.length - 1].destroy(); + messageShows.pop(); + if (messageShows.length === 0) { + $mask.remove(); + $mask = null; + } + } + + const controlItems = []; + if (hasCancel === true) { + controlItems.push({ + el: { + type: Button.xtype, + height: config.buttonHeight, + text: config.cancelText, + light: true, + handler() { + close(); + if (isFunction(callback)) { + callback.apply(null, [false]); + } + }, + }, + }); + } + controlItems.push({ + el: { + type: Button.xtype, + height: config.buttonHeight, + text: config.sureText, + handler() { + close(); + if (isFunction(callback)) { + callback.apply(null, [true]); + } + }, + }, + }); + const conf = { + element: $pop, + type: CenterAdaptLayout.xtype, + items: [ + { + type: VerticalLayout.xtype, + cls: "bi-card bi-border-radius", + width: 450, + css: { + 'max-height': '100%' + }, + hgap: 32, + attributes: { + tabIndex: 1, + }, + mounted() { + this.element.keyup(e => { + if (e.keyCode === KeyCode.ENTER) { close(); if (isFunction(callback)) { - callback.apply(null, [false]); + callback.apply(null, [true]); + } + } else if (e.keyCode === KeyCode.ESCAPE) { + close(); + if (hasCancel === true) { + if (isFunction(callback)) { + callback.apply(null, [false]); + } } - }, - }, - }); - } - controlItems.push({ - el: { - type: "bi.button", - height: config.buttonHeight, - text: i18nText("BI-Basic_OK"), - handler() { - close(); - if (isFunction(callback)) { - callback.apply(null, [true]); } - }, + }); + try { + this.element.focus(); + } catch (e) { + } }, - }); - const conf = { - element: $pop, - type: "bi.center_adapt", items: [ { - type: "bi.border", - attributes: { - tabIndex: 1, - }, - mounted() { - this.element.keyup(e => { - if (e.keyCode === KeyCode.ENTER) { - close(); - if (isFunction(callback)) { - callback.apply(null, [true]); - } - } else if (e.keyCode === KeyCode.ESCAPE) { - close(); - if (hasCancel === true) { - if (isFunction(callback)) { - callback.apply(null, [false]); - } - } - } - }); - try { - this.element.focus(); - } catch (e) { - } - }, - cls: "bi-card", - items: { - north: { - el: { - type: "bi.border", - cls: "bi-message-title bi-background", - items: { - center: { - el: { - type: "bi.label", - cls: "bi-font-bold", - text: title || i18nText("BI-Basic_Prompt"), - textAlign: "left", - hgap: 20, - height: 40, - }, - }, - east: { - el: { - type: "bi.icon_button", - cls: "bi-message-close close-font", - // height: 50, - handler() { - close(); - if (isFunction(callback)) { - callback.apply(null, [false]); - } - }, - }, - width: 56, - }, - }, + el: { + type: HTapeLayout.xtype, + height: 24, + items: [ + { + type: IconLabel.xtype, + cls: `${getIconCls(config.level)} icon-size-20`, + width: 24, + height: 24, }, - height: 40, - }, - center: { - el: isPlainObject(message) - ? message - : { - type: "bi.label", - vgap: 10, - hgap: 20, - whiteSpace: "normal", - text: message, + { + el: { + type: Label.xtype, + css: {"font-size": 16}, + cls: 'bi-font-bold', // 16px + textAlign: 'left', + text: title || i18nText('BI-Basic_Prompt'), + lgap: 16, }, - }, - south: { - el: { - type: "bi.absolute", - items: [ - { - el: { - type: "bi.right_vertical_adapt", - lgap: 10, - items: controlItems, - }, - top: 0, - left: 20, - right: 20, - bottom: 0, - } - ], + width: 'fill', }, - height: 44, + ], + }, + tgap: 32, + }, + { + el: isPlainObject(message) + ? message + : { + type: Label.xtype, + css: { "font-size": 14 }, + cls: 'alert-content', + textAlign: 'left', + text: message, + whiteSpace: 'normal', }, + height: 'fill', + tgap: 12, + lgap: 40, + }, + { + el: config.footer && isFunction(config.footer) ? config.footer(close) : { + type: RightVerticalAdaptLayout.xtype, + lgap: 12, + items: controlItems, }, - width: 450, - height: 200, - } + tgap: 32, + bgap: 24, + }, ], - }; - - messageShows[messageShows.length] = createWidget(conf); - }, + }, + ], }; -})(); + + messageShows[messageShows.length] = createWidget(conf); +} diff --git a/packages/fineui/src/base/layer/layer.popover.js b/packages/fineui/src/base/layer/layer.popover.js index ea6db3662..d7649c389 100644 --- a/packages/fineui/src/base/layer/layer.popover.js +++ b/packages/fineui/src/base/layer/layer.popover.js @@ -47,7 +47,7 @@ export class Popover extends Widget { body: null, footer: null, footerHeight: 44, - footerButtonHeight: 24, + footerButtonHeight: 28, closable: true, // BI-40839 是否显示右上角的关闭按钮 bodyHgap: SIZE_CONSANTS.H_GAP_SIZE, bodyTgap: SIZE_CONSANTS.V_GAP_SIZE, @@ -64,30 +64,7 @@ export class Popover extends Widget { // var self = this; const { header, headerHeight, closable, logic, footer, footerHeight, body, bodyTgap, bodyHgap } = this.options; const c = this._constant; - this.startX = 0; - this.startY = 0; const size = this._calculateSize(); - const bodyDom = getOuterBody(); - this.tracker = new MouseMoveTracker( - (deltaX, deltaY) => { - const W = Widget._renderEngine.createElement(bodyDom).width(); - const H = Widget._renderEngine.createElement(bodyDom).height(); - this.startX += deltaX; - this.startY += deltaY; - this.element.css({ - left: `${clamp(this.startX, 0, W - this.element.width())}px`, - top: `${clamp(this.startY, 0, H - this.element.height())}px`, - }); - // BI-12134 没有什么特别好的方法 - Resizers._resize({ - target: this.element[0], - }); - }, - () => { - this.tracker.releaseMouseMoves(); - }, - _global - ); const items = [ { el: { @@ -219,7 +196,30 @@ export class Popover extends Widget { // mounted之后绑定事件 mounted() { - this.dragger.element.mousedown(e => { + this.startX = 0; + this.startY = 0; + const bodyDom = getOuterBody(); + this.tracker = new MouseMoveTracker( + (deltaX, deltaY) => { + const W = Widget._renderEngine.createElement(bodyDom).width(); + const H = Widget._renderEngine.createElement(bodyDom).height(); + this.startX += deltaX; + this.startY += deltaY; + this.element.css({ + left: `${clamp(this.startX, 0, W - this.element.width())}px`, + top: `${clamp(this.startY, 0, H - this.element.height())}px`, + }); + // BI-12134 没有什么特别好的方法 + Resizers._resize({ + target: this.element[0], + }); + }, + () => { + this.tracker.releaseMouseMoves(); + }, + _global + ); + this.dragger?.element.mousedown(e => { if (this.options.draggable !== false) { this.startX = this.element[0].offsetLeft; this.startY = this.element[0].offsetTop; diff --git a/packages/fineui/src/base/single/input/file.js b/packages/fineui/src/base/single/input/file.js index c89a02e70..63278b6e0 100644 --- a/packages/fineui/src/base/single/input/file.js +++ b/packages/fineui/src/base/single/input/file.js @@ -242,14 +242,11 @@ const sendFile = (toString => { upload.onloadstart(); } } - const boundary = `AjaxUploadBoundary${new Date().getTime()}`; - xhr.setRequestHeader("Content-Type", `multipart/form-data; boundary=${boundary}`); if (handler.file.getAsBinary) { + const boundary = `AjaxUploadBoundary${new Date().getTime()}`; + xhr.setRequestHeader("Content-Type", `multipart/form-data; boundary=${boundary}`); xhr[xhr.sendAsBinary ? "sendAsBinary" : "send"](multipart(boundary, handler.name, handler.file)); } else { - xhr.setRequestHeader("Content-Type", "multipart/form-data"); - // xhr.setRequestHeader("X-Name", handler.name); - // xhr.setRequestHeader("X-File-Name", handler.file.fileName); const form = new FormData(); form.append("FileData", handler.file); xhr.send(form); diff --git a/packages/fineui/src/case/button/item.multiselect.js b/packages/fineui/src/case/button/item.multiselect.js index 2d4879079..e3e909d13 100644 --- a/packages/fineui/src/case/button/item.multiselect.js +++ b/packages/fineui/src/case/button/item.multiselect.js @@ -19,6 +19,7 @@ export class MultiSelectItem extends BasicButton { }, height: SIZE_CONSANTS.LIST_ITEM_HEIGHT, iconWrapperWidth: 26, + el: {}, }); } @@ -55,6 +56,7 @@ export class MultiSelectItem extends BasicButton { keyword: o.keyword, value: o.value, py: o.py, + ...o.el }, } ], diff --git a/packages/fineui/src/case/button/switch.js b/packages/fineui/src/case/button/switch.js index 68a5c556a..6cc3b7912 100644 --- a/packages/fineui/src/case/button/switch.js +++ b/packages/fineui/src/case/button/switch.js @@ -1,15 +1,13 @@ import { AbsoluteLayout, shortcut, i18nText } from "@/core"; import { TextButton, Label, BasicButton } from "@/base"; +const CIRCLE_SIZE = 12; + @shortcut() export class Switch extends BasicButton { static xtype = "bi.switch"; static EVENT_CHANGE = "EVENT_CHANGE"; - constants = { - CIRCLE_SIZE: 12, - }; - props = { extraCls: "bi-switch", attributes: { @@ -18,12 +16,12 @@ export class Switch extends BasicButton { height: 20, width: 44, showTip: false, + textGap: 8, }; render() { - const o = this.options, - c = this.constants; - const tgap = (o.height - c.CIRCLE_SIZE) / 2; + const { selected, width, height, textGap, showTip } = this.options; + const tgap = (height - CIRCLE_SIZE) / 2; return { type: AbsoluteLayout.xtype, @@ -39,15 +37,15 @@ export class Switch extends BasicButton { width: 12, height: 12, top: tgap, - left: o.selected ? 28 : 4, + left: selected ? width - height + tgap : tgap, }, { type: Label.xtype, text: i18nText("BI-Basic_Simple_Open"), cls: "content-tip", - left: 8, + left: textGap, top: tgap - 2, - invisible: !(o.showTip && o.selected), + invisible: !(showTip && selected), ref: _ref => { this.openTip = _ref; }, @@ -56,9 +54,9 @@ export class Switch extends BasicButton { type: Label.xtype, text: i18nText("BI-Basic_Simple_Close"), cls: "content-tip", - right: 8, + right: textGap, top: tgap - 2, - invisible: !(o.showTip && !o.selected), + invisible: !(showTip && !selected), ref: _ref => { this.closeTip = _ref; }, @@ -78,7 +76,9 @@ export class Switch extends BasicButton { setSelected(v) { super.setSelected(...arguments); - this.layout.attr("items")[0].left = v ? 28 : 4; + const { width, height } = this.options; + const tgap = (height - CIRCLE_SIZE) / 2; + this.layout.attr("items")[0].left = v ? width - height + tgap : tgap; this.layout.resize(); this.options.showTip && this.openTip.setVisible(v); this.options.showTip && this.closeTip.setVisible(!v); diff --git a/packages/fineui/src/case/colorchooser/colorchooser.js b/packages/fineui/src/case/colorchooser/colorchooser.js index 7b075eae0..a846a2cab 100644 --- a/packages/fineui/src/case/colorchooser/colorchooser.js +++ b/packages/fineui/src/case/colorchooser/colorchooser.js @@ -24,6 +24,7 @@ export class ColorChooser extends Widget { height: 24, el: {}, simple: false, + colorBoardHeight: 80, }); } @@ -62,6 +63,8 @@ export class ColorChooser extends Widget { el: extend( { type: HexColorChooserPopup.xtype, + colorItems: o.colorItems, + colorBoardHeight: o.colorBoardHeight, recommendColorsGetter: o.recommendColorsGetter, ref: _ref => { this.colorPicker = _ref; diff --git a/packages/fineui/src/case/colorchooser/colorchooser.popup.hex.js b/packages/fineui/src/case/colorchooser/colorchooser.popup.hex.js index afde53a6a..aaaa91cd0 100644 --- a/packages/fineui/src/case/colorchooser/colorchooser.popup.hex.js +++ b/packages/fineui/src/case/colorchooser/colorchooser.popup.hex.js @@ -47,6 +47,7 @@ export class HexColorChooserPopup extends Widget { width: 300, recommendColorsGetter: emptyFn, // 推荐色获取接口 simple: false, // 简单模式, popup中没有自动和透明 + colorBoardHeight: 80, }; render() { @@ -167,6 +168,7 @@ export class HexColorChooserPopup extends Widget { type: HexColorPicker.xtype, space: true, value: o.value, + items: o.colorItems, listeners: [ { eventName: ColorPicker.EVENT_CHANGE, @@ -187,7 +189,7 @@ export class HexColorChooserPopup extends Widget { bottom: 1, } ], - height: 80, + height: o.colorBoardHeight, } ], }, diff --git a/packages/fineui/src/component/form/form.field.js b/packages/fineui/src/component/form/form.field.js index 8cc80eae6..3260edc62 100644 --- a/packages/fineui/src/component/form/form.field.js +++ b/packages/fineui/src/component/form/form.field.js @@ -69,7 +69,7 @@ export class FormField extends Widget { return { type: VerticalAdaptLayout.xtype, - columnSize: ["auto", "fill"], + columnSize: isKey(o.label) ? ["auto", "fill"] : ["fill"], verticalAlign: VerticalAlign.Stretch, items: isKey(o.label) ? [ diff --git a/packages/fineui/src/core/1.lodash.js b/packages/fineui/src/core/1.lodash.js index ca3a3ade0..2658bdf48 100644 --- a/packages/fineui/src/core/1.lodash.js +++ b/packages/fineui/src/core/1.lodash.js @@ -6142,6 +6142,30 @@ return (array && array.length) ? baseUniq(array, baseIteratee(iteratee, 2)) : []; } + /** + * This method is like `uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @see uniq, uniqBy + * @example + * + * const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }] + * + * uniqWith(objects, isEqual) + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + comparator = typeof comparator === 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; + } + /** * This method is like `_.zip` except that it accepts an array of grouped * elements and creates an array regrouping the elements to their pre-zip @@ -10041,6 +10065,7 @@ lodash.union = union; lodash.uniq = uniq; lodash.uniqBy = uniqBy; + lodash.uniqWith = uniqWith; lodash.unzip = unzip; lodash.values = values; lodash.without = without; diff --git a/packages/fineui/src/core/2.base.js b/packages/fineui/src/core/2.base.js index 15502e37b..fe0c611f2 100644 --- a/packages/fineui/src/core/2.base.js +++ b/packages/fineui/src/core/2.base.js @@ -482,6 +482,7 @@ _.each( "take", "takeRight", "uniqBy", + "uniqWith" ], name => { lodashFns[name] = _apply(name); @@ -510,6 +511,7 @@ export const range = lodashFns.range; export const take = lodashFns.take; export const takeRight = lodashFns.takeRight; export const uniqBy = lodashFns.uniqBy; +export const uniqWith = lodashFns.uniqWith; export const findIndex = lodashFns.findIndex; export const findLastIndex = lodashFns.findLastIndex; @@ -972,7 +974,7 @@ export let nextTick = /*!PURE*/(function () { pending = true; timerFunc(); } - + if (!cb && typeof Promise !== "undefined") { return new Promise((resolve, reject) => { _resolve = resolve; @@ -983,7 +985,7 @@ export let nextTick = /*!PURE*/(function () { export const setNextTick = (fn) => { nextTick = fn; -} +} // 数字相关方法 _.each(["random"], name => { diff --git a/packages/fineui/src/core/4.widget.js b/packages/fineui/src/core/4.widget.js index c8fbe5d2f..7ddf3b320 100644 --- a/packages/fineui/src/core/4.widget.js +++ b/packages/fineui/src/core/4.widget.js @@ -241,7 +241,8 @@ export class Widget extends OB { if (beforeRenderResult instanceof Promise) { beforeRenderResult.then(render).catch((e) => { _global.console && console.error(e); - render(); + // 异步render,组件此时可能已经被销毁 + !this.isDestroyed() ? render() : _global.console && console.error('Async render error! Widget has been destroyed!'); }); } } else { @@ -258,7 +259,8 @@ export class Widget extends OB { if (beforeInitResult instanceof Promise) { beforeInitResult.then(init).catch((e) => { _global.console && console.error(e); - init(); + // 异步init,组件此时可能已经被销毁 + !this.isDestroyed() ? init() : _global.console && console.error('Async init error! Widget has been destroyed!'); }); } } else { diff --git a/packages/fineui/src/core/platform/web/detectElementResize.js b/packages/fineui/src/core/platform/web/detectElementResize.js index 3ae28a853..47e360114 100644 --- a/packages/fineui/src/core/platform/web/detectElementResize.js +++ b/packages/fineui/src/core/platform/web/detectElementResize.js @@ -46,10 +46,14 @@ export const ResizeDetector = { addResizeListener(widget.element[0], fn); return function () { + // 如果fn是debounce需要cancel掉 + fn?.cancel?.(); removeResizeListener(widget.element[0], fn); }; }, removeResizeListener(widget, fn) { + // 如果fn是debounce需要cancel掉 + fn?.cancel?.(); removeResizeListener(widget.element[0], fn); }, }; diff --git a/packages/fineui/src/core/wrapper/layout/layout.table.js b/packages/fineui/src/core/wrapper/layout/layout.table.js index ec75bc8f0..b32f9b530 100644 --- a/packages/fineui/src/core/wrapper/layout/layout.table.js +++ b/packages/fineui/src/core/wrapper/layout/layout.table.js @@ -56,10 +56,10 @@ export class TableLayout extends Layout { "grid-column-gap": this._optimiseGap(o.hgap), }); } - + return { type: "bi.default", - ref(_ref) { + ref: (_ref) => { this.layout = _ref; }, items: this._formatItems(items), @@ -110,7 +110,7 @@ export class TableLayout extends Layout { type: "bi.layout", }), cls); } - + return first(wrapLayout(item), cls); })), []); } diff --git a/packages/fineui/src/fix/fix.js b/packages/fineui/src/fix/fix.js index 48e7eb0e6..ac7a8b839 100644 --- a/packages/fineui/src/fix/fix.js +++ b/packages/fineui/src/fix/fix.js @@ -1386,7 +1386,7 @@ class Model { this.$$computed = null; this.$$state = null; this.$$context = null; - this.model = null; + this.model = {}; // 一些异步请求里访问model里的属性,这里先变成空对象,保证部分场景下不报错,其他报错会try catch this._destroyHandler && this._destroyHandler(); } } diff --git a/packages/fineui/src/less/base/tree/ztree.less b/packages/fineui/src/less/base/tree/ztree.less index e9eee2c97..e7869baae 100644 --- a/packages/fineui/src/less/base/tree/ztree.less +++ b/packages/fineui/src/less/base/tree/ztree.less @@ -272,7 +272,9 @@ } .bi-theme-dark { - .ztree.solid li span.button.center_docu, .ztree.solid li span.button.bottom_docu { + .ztree.solid li span.button.center_docu, .ztree.solid li span.button.bottom_docu,.ztree.solid li span.button.roots_docu { + background: none; + &:before { border-right: 1px solid @border-color-dark-gray-line-theme-dark; } diff --git a/packages/fineui/src/less/lib/colors.less b/packages/fineui/src/less/lib/colors.less index fd429ac08..810745b94 100644 --- a/packages/fineui/src/less/lib/colors.less +++ b/packages/fineui/src/less/lib/colors.less @@ -132,3 +132,5 @@ @color-bi-border-warning: @border-color-warning; //边框提亮 @color-bi-border-highlight: @border-color-highlight; + +@color-bi-alert-warning: @color-bi-orange; diff --git a/packages/fineui/src/less/lib/constant.less b/packages/fineui/src/less/lib/constant.less index fa69a4783..eb03e23e8 100644 --- a/packages/fineui/src/less/lib/constant.less +++ b/packages/fineui/src/less/lib/constant.less @@ -248,3 +248,5 @@ //box-shadow效果 @box-shadow-toast: 0 6px 20px -2px rgba(9, 30, 64, 0.16); + +@color-bi-orange: #f0ac3c; diff --git a/packages/fineui/src/less/lib/font.less b/packages/fineui/src/less/lib/font.less index f37ec8615..d8eccc6f7 100644 --- a/packages/fineui/src/less/lib/font.less +++ b/packages/fineui/src/less/lib/font.less @@ -58,3 +58,8 @@ @font-key: "e1d0"; @font-add: "e1c7"; + +@font-alert-warning: 'e755'; +@font-alert-success: 'e6de'; +@font-alert-info: 'e74b'; +@font-alert-error: 'e757'; diff --git a/packages/fineui/src/less/resource/font.less b/packages/fineui/src/less/resource/font.less index d65940802..93330a958 100644 --- a/packages/fineui/src/less/resource/font.less +++ b/packages/fineui/src/less/resource/font.less @@ -118,3 +118,8 @@ .font(text-align-left-font, @font-align-left); .font(text-align-center-font, @font-align-center); .font(text-align-right-font, @font-align-right); + +.font(alert-success-font, @font-alert-success, @color-sea-green-100); +.font(alert-warning-font, @font-alert-warning, @color-bi-alert-warning); +.font(alert-error-font, @font-alert-error, @color-red-100); +.font(alert-info-font, @font-alert-info, @color-bi-text-highlight); diff --git a/packages/fineui/src/widget/editor/editor.search.js b/packages/fineui/src/widget/editor/editor.search.js index e0387b342..327d9464f 100644 --- a/packages/fineui/src/widget/editor/editor.search.js +++ b/packages/fineui/src/widget/editor/editor.search.js @@ -10,7 +10,7 @@ import { Controller, Events, HTapeLayout, - isEndWithBlank + isEndWithBlank, HorizontalFillLayout } from "@/core"; import { IconButton, Editor, IconLabel } from "@/base"; @@ -87,14 +87,15 @@ export class SearchEditor extends Widget { createWidget({ element: this, height: toPix(o.height, o.simple ? 1 : 2), - type: HTapeLayout.xtype, + type: HorizontalFillLayout.xtype, + columnSize: ["", "fill", ""], items: [ { el: { type: IconLabel.xtype, cls: "search-font", + width: 24, }, - width: 24, }, { el: this.editor, diff --git a/packages/fineui/src/widget/multilayerdownlist/combo.downlist.js b/packages/fineui/src/widget/multilayerdownlist/combo.downlist.js index 0862417da..56bf41107 100644 --- a/packages/fineui/src/widget/multilayerdownlist/combo.downlist.js +++ b/packages/fineui/src/widget/multilayerdownlist/combo.downlist.js @@ -10,6 +10,7 @@ export class MultiLayerDownListCombo extends Widget { static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_SON_VALUE_CHANGE = "EVENT_SON_VALUE_CHANGE"; static EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; + static EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW"; _defaultConfig() { return extend(super._defaultConfig(...arguments), { @@ -70,6 +71,10 @@ export class MultiLayerDownListCombo extends Widget { this.downlistcombo.on(Combo.EVENT_BEFORE_POPUPVIEW, () => { this.fireEvent(MultiLayerDownListCombo.EVENT_BEFORE_POPUPVIEW); }); + + this.downlistcombo.on(Combo.EVENT_BEFORE_HIDEVIEW, () => { + this.fireEvent(MultiLayerDownListCombo.EVENT_BEFORE_HIDEVIEW); + }); } hideView() { diff --git a/packages/fineui/src/widget/multiselect/multiselect.loader.js b/packages/fineui/src/widget/multiselect/multiselect.loader.js index ab234b3f9..b7b397627 100644 --- a/packages/fineui/src/widget/multiselect/multiselect.loader.js +++ b/packages/fineui/src/widget/multiselect/multiselect.loader.js @@ -107,7 +107,10 @@ export class MultiSelectLoader extends Widget { } firstItems = self._createItems(json); } - callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || ""); + const context = { + tipText: ob.tipText, + }; + callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || "", context); if (op.times === 1 && self.storeValue) { isKey(startValue) && (self.storeValue.type === Selection.All diff --git a/packages/fineui/src/widget/multiselect/multiselect.loader.nobar.js b/packages/fineui/src/widget/multiselect/multiselect.loader.nobar.js index 825a7f6ac..802c3b3ba 100644 --- a/packages/fineui/src/widget/multiselect/multiselect.loader.nobar.js +++ b/packages/fineui/src/widget/multiselect/multiselect.loader.nobar.js @@ -115,7 +115,10 @@ export class MultiSelectNoBarLoader extends Widget { } firstItems = self._createItems(json); } - callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || ""); + const context = { + tipText: ob.tipText, + }; + callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || "", context); if (op.times === 1 && self.storeValue) { isKey(startValue) && (self.storeValue.type === Selection.All diff --git a/packages/fineui/src/widget/searchmultitextvaluecombo/multitextvalue.loader.search.js b/packages/fineui/src/widget/searchmultitextvaluecombo/multitextvalue.loader.search.js index 965208bac..abdcc7398 100644 --- a/packages/fineui/src/widget/searchmultitextvaluecombo/multitextvalue.loader.search.js +++ b/packages/fineui/src/widget/searchmultitextvaluecombo/multitextvalue.loader.search.js @@ -120,8 +120,10 @@ export class SearchMultiSelectLoader extends Widget { } firstItems = this._createItems(json); } - - callback(firstItems.concat(this._createItems(ob.items)), ob.keyword || ""); + const context = { + tipText: ob.tipText, + }; + callback(firstItems.concat(this._createItems(ob.items)), ob.keyword || "", context); if (op.times === 1 && this.storeValue) { isKey(startValue) && (this.storeValue.type === Selection.All diff --git a/packages/fineui/src/widget/year/popup.year.js b/packages/fineui/src/widget/year/popup.year.js index 520e5978e..a05407d2c 100644 --- a/packages/fineui/src/widget/year/popup.year.js +++ b/packages/fineui/src/widget/year/popup.year.js @@ -150,6 +150,7 @@ export class DynamicYearPopup extends Widget { }, tab: { type: LinearSegment.xtype, + cls: "bi-split-bottom", invisible: !o.supportDynamic, height: this.constants.tabHeight, items: createItems( diff --git a/packages/fineui/typescript/base/foundation/message.ts b/packages/fineui/typescript/base/foundation/message.ts index 2094d7fea..68a0c53c7 100644 --- a/packages/fineui/typescript/base/foundation/message.ts +++ b/packages/fineui/typescript/base/foundation/message.ts @@ -8,13 +8,23 @@ type toastOptions = { export declare namespace Msg { function alert(title: string, message?: string | { [key: string]: any - }, callback?: (result?: boolean) => void): void + }, callback?: (result?: boolean) => void, config?: { + buttonHeight?: number, + sureText?: string, + cancelText?: string, + level?: 'success' | 'warning' | 'error' | 'info', + footer?: (onClose: Function) => Obj; + }): void function confirm(title: string, message?: string | { [key: string]: any - }, callback?: (result: boolean) => void): void - - function prompt(title: string, message?: string, value?: any, callback?: (result: string) => void, minWidth?: number): void + }, callback?: (result: boolean) => void, config?: { + buttonHeight?: number, + sureText?: string, + cancelText?: string, + level?: 'success' | 'warning' | 'error' | 'info', + footer?: (onClose: Function) => Obj; + }): void function toast(message: string | Obj, options?: toastOptions | string, context?: HTMLElement): Function } diff --git a/packages/fineui/typescript/case/button/switch.ts b/packages/fineui/typescript/case/button/switch.ts index dc4489892..2b08b4b98 100644 --- a/packages/fineui/typescript/case/button/switch.ts +++ b/packages/fineui/typescript/case/button/switch.ts @@ -1,6 +1,11 @@ import { BasicButton } from "../../base/single/button/button.basic"; export declare class Switch extends BasicButton { + + props: { + textGap: number; + } & BasicButton['props'] + static xtype: string; static EVENT_CHANGE: string; } diff --git a/packages/fineui/typescript/case/colorchooser/colorchooser.ts b/packages/fineui/typescript/case/colorchooser/colorchooser.ts index b58869e37..ac429ef46 100644 --- a/packages/fineui/typescript/case/colorchooser/colorchooser.ts +++ b/packages/fineui/typescript/case/colorchooser/colorchooser.ts @@ -1,3 +1,4 @@ +import { Single } from 'typescript/base/single/single'; import { Widget } from '../../core/widget'; export declare class ColorChooser extends Widget { @@ -5,6 +6,12 @@ export declare class ColorChooser extends Widget { static EVENT_CHANGE: string; static EVENT_AFTER_POPUPVIEW: string; + props: { + stopEvent?: boolean; + colorBoardHeight?: number; + colorItems?: { value: string }[][]; + } & Single["props"]; + isViewVisible(): boolean; hideView(): void; diff --git a/packages/fineui/typescript/core/base.ts b/packages/fineui/typescript/core/base.ts index 3b4efbf36..07b481d34 100644 --- a/packages/fineui/typescript/core/base.ts +++ b/packages/fineui/typescript/core/base.ts @@ -172,6 +172,8 @@ export declare function uniq(array: T[], isSorted?: boolean, iteratee?: any, export declare function uniqBy(array: T[], iteratee?: any, context?: any): T[]; +export declare function uniqWith(array: T[], comparator?: any): T[]; + // 对象相关方法 export declare function keys(object: object): string[]; @@ -320,7 +322,17 @@ export declare function once(func: Function): Function; export declare function partial(func: Function, ...partials: any): Function; -export declare function debounce(func: T, wait?: number, options?: any): T; + +interface DebouncedFunc any> { + + (...args: Parameters): ReturnType | undefined; + + cancel(): void; + + flush(): ReturnType | undefined; +} + +export declare function debounce any>(func: T, wait?: number, options?: any): DebouncedFunc; export declare function throttle(func: T, wait?: number, options?: any): T; diff --git a/packages/fineui/typescript/widget/multilayerdownlist/multilayerdownlist.combo.ts b/packages/fineui/typescript/widget/multilayerdownlist/multilayerdownlist.combo.ts index 87359ffe3..058c9af7d 100644 --- a/packages/fineui/typescript/widget/multilayerdownlist/multilayerdownlist.combo.ts +++ b/packages/fineui/typescript/widget/multilayerdownlist/multilayerdownlist.combo.ts @@ -7,6 +7,7 @@ export declare class MultiLayerDownListCombo extends Widget { static EVENT_CHANGE: string; static EVENT_SON_VALUE_CHANGE: string; static EVENT_BEFORE_POPUPVIEW: string; + static EVENT_BEFORE_HIDEVIEW: string; props: { adjustLength: Combo['props']['adjustLength'];