UNPKG

mldong-flow-designer-plus

Version:

本项目包含了作者为B站课堂视频[《工作流设计器开发最佳实践》](https://www.bilibili.com/cheese/play/ss24484)的过程源码。教程中开发的组件也可用于实际生产环境中。以下是和使用文档和课程章节说明。 ## 实战项目 [演示地址](https://flow-pro.mldong.com/)

650 lines (649 loc) 21.9 kB
import { a as buildProps, m as isClient, g as definePropType, L as useNamespace, s as isNumber, P as withInstall, M as useTimeoutFn, x as isString, q as isFunction, i as hasOwn, n as isElement, f as debugWarn, l as isBoolean, Q as withInstallFunction } from "./error-DEV4o0cD.js"; import { i as iconPropType, a as TypeComponentsMap, E as ElIcon, T as TypeComponents } from "./index-D0I3i9fl.js"; import { m as mutable } from "./typescript-D6L75muK.js"; import { p as provideGlobalConfig, u as useGlobalComponentSettings } from "./use-global-config-DAkQU-Bn.js"; import { d as useSizeProp, b as addUnit } from "./style-D2s_cWsv.js"; import { a as useEmptyValuesProps } from "./index-BbcOBREW.js"; import { defineComponent, watch, renderSlot, shallowReactive, computed, openBlock, createElementBlock, normalizeClass, unref, createVNode, Transition, withCtx, normalizeStyle, createTextVNode, toDisplayString, createCommentVNode, ref, onMounted, createBlock, withDirectives, createElementVNode, resolveDynamicComponent, Fragment, withModifiers, vShow, nextTick, isVNode, render } from "vue"; import { g as getEventCode, E as EVENT_CODE } from "./event-bJhzntMi.js"; import { a as useEventListener, c as useResizeObserver } from "./index-rPPo0srK.js"; const messageTypes = [ "primary", "success", "info", "warning", "error" ]; const messagePlacement = [ "top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right" ]; const MESSAGE_DEFAULT_PLACEMENT = "top"; const messageDefaults = mutable({ customClass: "", dangerouslyUseHTMLString: false, duration: 3e3, icon: void 0, id: "", message: "", onClose: void 0, showClose: false, type: "info", plain: false, offset: 16, placement: void 0, zIndex: 0, grouping: false, repeatNum: 1, appendTo: isClient ? document.body : void 0 }); const messageProps = buildProps({ /** * @description custom class name for Message */ customClass: { type: String, default: messageDefaults.customClass }, /** * @description whether `message` is treated as HTML string */ dangerouslyUseHTMLString: { type: Boolean, default: messageDefaults.dangerouslyUseHTMLString }, /** * @description display duration, millisecond. If set to 0, it will not turn off automatically */ duration: { type: Number, default: messageDefaults.duration }, /** * @description custom icon component, overrides `type` */ icon: { type: iconPropType, default: messageDefaults.icon }, /** * @description message dom id */ id: { type: String, default: messageDefaults.id }, /** * @description message text */ message: { type: definePropType([ String, Object, Function ]), default: messageDefaults.message }, /** * @description callback function when closed with the message instance as the parameter */ onClose: { type: definePropType(Function), default: messageDefaults.onClose }, /** * @description whether to show a close button */ showClose: { type: Boolean, default: messageDefaults.showClose }, /** * @description message type */ type: { type: String, values: messageTypes, default: messageDefaults.type }, /** * @description whether message is plain */ plain: { type: Boolean, default: messageDefaults.plain }, /** * @description set the distance to the top of viewport */ offset: { type: Number, default: messageDefaults.offset }, /** * @description message placement position */ placement: { type: String, values: messagePlacement, default: messageDefaults.placement }, /** * @description message element zIndex value */ zIndex: { type: Number, default: messageDefaults.zIndex }, /** * @description merge messages with the same content, type of VNode message is not supported */ grouping: { type: Boolean, default: messageDefaults.grouping }, /** * @description The number of repetitions, similar to badge, is used as the initial number when used with `grouping` */ repeatNum: { type: Number, default: messageDefaults.repeatNum } }); const messageEmits = { destroy: () => true }; const configProviderProps = buildProps({ /** * @description Controlling if the users want a11y features */ a11y: { type: Boolean, default: true }, /** * @description Locale Object */ locale: { type: definePropType(Object) }, /** * @description global component size */ size: useSizeProp, /** * @description button related configuration, [see the following table](https://element-plus.org/en-US/component/config-provider.html#button-attribute) */ button: { type: definePropType(Object) }, /** * @description card related configuration, [see the following table](https://element-plus.org/en-US/component/config-provider.html#card-attribute) */ card: { type: definePropType(Object) }, /** * @description dialog related configuration, [see the following table](https://element-plus.org/en-US/component/config-provider.html#dialog-attribute) */ dialog: { type: definePropType(Object) }, /** * @description link related configuration, [see the following table](https://element-plus.org/en-US/component/config-provider.html#link-attribute) */ link: { type: definePropType(Object) }, /** * @description features at experimental stage to be added, all features are default to be set to false, [see the following table](https://element-plus.org/en-US/component/config-provider.html#experimental-features) | ^[object] */ experimentalFeatures: { type: definePropType(Object) }, /** * @description Controls if we should handle keyboard navigation */ keyboardNavigation: { type: Boolean, default: true }, /** * @description message related configuration, [see the following table](https://element-plus.org/en-US/component/config-provider.html#message-attribute) */ message: { type: definePropType(Object) }, /** * @description global Initial zIndex */ zIndex: Number, /** * @description global component className prefix (cooperated with [$namespace](https://github.com/element-plus/element-plus/blob/dev/packages/theme-chalk/src/mixins/config.scss#L1)) | ^[string] */ namespace: { type: String, default: "el" }, /** * @description table related configuration, [see the following table](https://element-plus.org/en-US/component/config-provider.html#table-attribute) */ table: { type: definePropType(Object) }, ...useEmptyValuesProps }); const messageConfig = { placement: "top" }; defineComponent({ name: "ElConfigProvider", props: configProviderProps, setup(props, { slots }) { const config = provideGlobalConfig(props); watch(() => props.message, (val) => { var _a; Object.assign(messageConfig, ((_a = config == null ? void 0 : config.value) == null ? void 0 : _a.message) ?? {}, val ?? {}); }, { immediate: true, deep: true }); return () => renderSlot(slots, "default", { config: config == null ? void 0 : config.value }); } }); const placementInstances = shallowReactive({}); const getOrCreatePlacementInstances = (placement) => { if (!placementInstances[placement]) placementInstances[placement] = shallowReactive([]); return placementInstances[placement]; }; const getInstance = (id, placement) => { const instances = placementInstances[placement] || []; const idx = instances.findIndex((instance) => instance.id === id); const current = instances[idx]; let prev; if (idx > 0) prev = instances[idx - 1]; return { current, prev }; }; const getLastOffset = (id, placement) => { const { prev } = getInstance(id, placement); if (!prev) return 0; return prev.vm.exposed.bottom.value; }; const getOffsetOrSpace = (id, offset, placement) => { return (placementInstances[placement] || []).findIndex((instance) => instance.id === id) > 0 ? 16 : offset; }; const badgeProps = buildProps({ /** * @description display value. */ value: { type: [String, Number], default: "" }, /** * @description maximum value, shows `{max}+` when exceeded. Only works if value is a number. */ max: { type: Number, default: 99 }, /** * @description if a little dot is displayed. */ isDot: Boolean, /** * @description hidden badge. */ hidden: Boolean, /** * @description badge type. */ type: { type: String, values: [ "primary", "success", "warning", "info", "danger" ], default: "danger" }, /** * @description whether to show badge when value is zero. */ showZero: { type: Boolean, default: true }, /** * @description customize dot background color */ color: String, /** * @description CSS style of badge */ badgeStyle: { type: definePropType([ String, Object, Array, Boolean ]), default: void 0 }, /** * @description set offset of the badge */ offset: { type: definePropType(Array), default: () => [0, 0] }, /** * @description custom class name of badge */ badgeClass: { type: String } }); var badge_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ name: "ElBadge", __name: "badge", props: badgeProps, setup(__props, { expose: __expose }) { const props = __props; const ns = useNamespace("badge"); const content = computed(() => { if (props.isDot) return ""; if (isNumber(props.value) && isNumber(props.max)) return props.max < props.value ? `${props.max}+` : `${props.value}`; return `${props.value}`; }); const style = computed(() => { return [{ backgroundColor: props.color, marginRight: addUnit(-props.offset[0]), marginTop: addUnit(props.offset[1]) }, props.badgeStyle ?? {}]; }); __expose({ /** @description badge content */ content }); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { class: normalizeClass(unref(ns).b()) }, [renderSlot(_ctx.$slots, "default"), createVNode(Transition, { name: `${unref(ns).namespace.value}-zoom-in-center` }, { default: withCtx(() => [!__props.hidden && (content.value || __props.isDot || _ctx.$slots.content) ? (openBlock(), createElementBlock("sup", { key: 0, class: normalizeClass([ unref(ns).e("content"), unref(ns).em("content", __props.type), unref(ns).is("fixed", !!_ctx.$slots.default), unref(ns).is("dot", __props.isDot), unref(ns).is("hide-zero", !__props.showZero && __props.value === 0), __props.badgeClass ]), style: normalizeStyle(style.value) }, [renderSlot(_ctx.$slots, "content", { value: content.value }, () => [createTextVNode(toDisplayString(content.value), 1)])], 6)) : createCommentVNode("v-if", true)]), _: 3 }, 8, ["name"])], 2); }; } }); var badge_default = badge_vue_vue_type_script_setup_true_lang_default; const ElBadge = withInstall(badge_default); const _hoisted_1 = ["id"]; const _hoisted_2 = ["innerHTML"]; var message_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ name: "ElMessage", __name: "message", props: messageProps, emits: messageEmits, setup(__props, { expose: __expose, emit: __emit }) { const { Close } = TypeComponents; const props = __props; const emit = __emit; const isStartTransition = ref(false); const { ns, zIndex } = useGlobalComponentSettings("message"); const { currentZIndex, nextZIndex } = zIndex; const messageRef = ref(); const visible = ref(false); const height = ref(0); let stopTimer = void 0; const badgeType = computed(() => props.type ? props.type === "error" ? "danger" : props.type : "info"); const typeClass = computed(() => { const type = props.type; return { [ns.bm("icon", type)]: type && TypeComponentsMap[type] }; }); const iconComponent = computed(() => props.icon || TypeComponentsMap[props.type] || ""); const placement = computed(() => props.placement || "top"); const lastOffset = computed(() => getLastOffset(props.id, placement.value)); const offset = computed(() => { return Math.max(getOffsetOrSpace(props.id, props.offset, placement.value) + lastOffset.value, props.offset); }); const bottom = computed(() => height.value + offset.value); const horizontalClass = computed(() => { if (placement.value.includes("left")) return ns.is("left"); if (placement.value.includes("right")) return ns.is("right"); return ns.is("center"); }); const verticalProperty = computed(() => placement.value.startsWith("top") ? "top" : "bottom"); const customStyle = computed(() => ({ [verticalProperty.value]: `${offset.value}px`, zIndex: currentZIndex.value })); function startTimer() { if (props.duration === 0) return; ({ stop: stopTimer } = useTimeoutFn(() => { close(); }, props.duration)); } function clearTimer() { stopTimer == null ? void 0 : stopTimer(); } function close() { visible.value = false; nextTick(() => { var _a; if (!isStartTransition.value) { (_a = props.onClose) == null ? void 0 : _a.call(props); emit("destroy"); } }); } function keydown(event) { if (getEventCode(event) === EVENT_CODE.esc) close(); } onMounted(() => { startTimer(); nextZIndex(); visible.value = true; }); watch(() => props.repeatNum, () => { clearTimer(); startTimer(); }); useEventListener(document, "keydown", keydown); useResizeObserver(messageRef, () => { height.value = messageRef.value.getBoundingClientRect().height; }); __expose({ visible, bottom, close }); return (_ctx, _cache) => { return openBlock(), createBlock(Transition, { name: unref(ns).b("fade"), onBeforeEnter: _cache[0] || (_cache[0] = ($event) => isStartTransition.value = true), onBeforeLeave: __props.onClose, onAfterLeave: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("destroy")), persisted: "" }, { default: withCtx(() => [withDirectives(createElementVNode("div", { id: __props.id, ref_key: "messageRef", ref: messageRef, class: normalizeClass([ unref(ns).b(), { [unref(ns).m(__props.type)]: __props.type }, unref(ns).is("closable", __props.showClose), unref(ns).is("plain", __props.plain), unref(ns).is("bottom", verticalProperty.value === "bottom"), horizontalClass.value, __props.customClass ]), style: normalizeStyle(customStyle.value), role: "alert", onMouseenter: clearTimer, onMouseleave: startTimer }, [ __props.repeatNum > 1 ? (openBlock(), createBlock(unref(ElBadge), { key: 0, value: __props.repeatNum, type: badgeType.value, class: normalizeClass(unref(ns).e("badge")) }, null, 8, [ "value", "type", "class" ])) : createCommentVNode("v-if", true), iconComponent.value ? (openBlock(), createBlock(unref(ElIcon), { key: 1, class: normalizeClass([unref(ns).e("icon"), typeClass.value]) }, { default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(iconComponent.value)))]), _: 1 }, 8, ["class"])) : createCommentVNode("v-if", true), !__props.dangerouslyUseHTMLString || _ctx.$slots.default ? (openBlock(), createElementBlock("p", { key: 2, class: normalizeClass(unref(ns).e("content")) }, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(__props.message), 1)])], 2)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [createCommentVNode(" Caution here, message could've been compromised, never use user's input as message "), createElementVNode("p", { class: normalizeClass(unref(ns).e("content")), innerHTML: __props.message }, null, 10, _hoisted_2)], 2112)), __props.showClose ? (openBlock(), createBlock(unref(ElIcon), { key: 4, class: normalizeClass(unref(ns).e("closeBtn")), onClick: withModifiers(close, ["stop"]) }, { default: withCtx(() => [createVNode(unref(Close))]), _: 1 }, 8, ["class"])) : createCommentVNode("v-if", true) ], 46, _hoisted_1), [[vShow, visible.value]])]), _: 3 }, 8, ["name", "onBeforeLeave"]); }; } }); var message_default = message_vue_vue_type_script_setup_true_lang_default; let seed = 1; const normalizeAppendTo = (normalized) => { if (!normalized.appendTo) normalized.appendTo = document.body; else if (isString(normalized.appendTo)) { let appendTo = document.querySelector(normalized.appendTo); if (!isElement(appendTo)) { debugWarn("ElMessage", "the appendTo option is not an HTMLElement. Falling back to document.body."); appendTo = document.body; } normalized.appendTo = appendTo; } }; const normalizePlacement = (normalized) => { if (!normalized.placement && isString(messageConfig.placement) && messageConfig.placement) normalized.placement = messageConfig.placement; if (!normalized.placement) normalized.placement = "top"; if (!messagePlacement.includes(normalized.placement)) { debugWarn("ElMessage", `Invalid placement: ${normalized.placement}. Falling back to 'top'.`); normalized.placement = "top"; } }; const normalizeOptions = (params) => { const options = !params || isString(params) || isVNode(params) || isFunction(params) ? { message: params } : params; const normalized = { ...messageDefaults, ...options }; normalizeAppendTo(normalized); normalizePlacement(normalized); if (isBoolean(messageConfig.grouping) && !normalized.grouping) normalized.grouping = messageConfig.grouping; if (isNumber(messageConfig.duration) && normalized.duration === 3e3) normalized.duration = messageConfig.duration; if (isNumber(messageConfig.offset) && normalized.offset === 16) normalized.offset = messageConfig.offset; if (isBoolean(messageConfig.showClose) && !normalized.showClose) normalized.showClose = messageConfig.showClose; if (isBoolean(messageConfig.plain) && !normalized.plain) normalized.plain = messageConfig.plain; return normalized; }; const closeMessage = (instance) => { const instances = placementInstances[instance.props.placement || "top"]; const idx = instances.indexOf(instance); if (idx === -1) return; instances.splice(idx, 1); const { handler } = instance; handler.close(); }; const createMessage = ({ appendTo, ...options }, context) => { const id = `message_${seed++}`; const userOnClose = options.onClose; const container = document.createElement("div"); const props = { ...options, id, onClose: () => { userOnClose == null ? void 0 : userOnClose(); closeMessage(instance); }, onDestroy: () => { render(null, container); } }; const vnode = createVNode(message_default, props, isFunction(props.message) || isVNode(props.message) ? { default: isFunction(props.message) ? props.message : () => props.message } : null); vnode.appContext = context || message._context; render(vnode, container); appendTo.appendChild(container.firstElementChild); const vm = vnode.component; const instance = { id, vnode, vm, handler: { close: () => { vm.exposed.close(); } }, props: vnode.component.props }; return instance; }; const message = (options = {}, context) => { if (!isClient) return { close: () => void 0 }; const normalized = normalizeOptions(options); const instances = getOrCreatePlacementInstances(normalized.placement || "top"); if (normalized.grouping && instances.length) { const instance2 = instances.find(({ vnode: vm }) => { var _a; return ((_a = vm.props) == null ? void 0 : _a.message) === normalized.message; }); if (instance2) { instance2.props.repeatNum += 1; instance2.props.type = normalized.type; return instance2.handler; } } if (isNumber(messageConfig.max) && instances.length >= messageConfig.max) return { close: () => void 0 }; const instance = createMessage(normalized, context); instances.push(instance); return instance.handler; }; messageTypes.forEach((type) => { message[type] = (options = {}, appContext) => { return message({ ...normalizeOptions(options), type }, appContext); }; }); function closeAll(type) { for (const placement in placementInstances) if (hasOwn(placementInstances, placement)) { const instances = [...placementInstances[placement]]; for (const instance of instances) if (!type || type === instance.props.type) instance.handler.close(); } } function closeAllByPlacement(placement) { if (!placementInstances[placement]) return; [...placementInstances[placement]].forEach((instance) => instance.handler.close()); } message.closeAll = closeAll; message.closeAllByPlacement = closeAllByPlacement; message._context = null; const ElMessage = withInstallFunction(message, "$message"); export { ElMessage, MESSAGE_DEFAULT_PLACEMENT, ElMessage as default, messageDefaults, messageEmits, messagePlacement, messageProps, messageTypes }; //# sourceMappingURL=index-SN_KWgq2.js.map