mldong-flow-designer-plus
Version:
本项目包含了作者为B站课堂视频[《工作流设计器开发最佳实践》](https://www.bilibili.com/cheese/play/ss24484)的过程源码。教程中开发的组件也可用于实际生产环境中。以下是和使用文档和课程章节说明。 ## 实战项目 [演示地址](https://flow-pro.mldong.com/)
518 lines (517 loc) • 16.1 kB
JavaScript
import { defineComponent, computed, openBlock, createElementBlock, normalizeClass, unref, renderSlot, createVNode, Transition, withCtx, withDirectives, createElementVNode, normalizeStyle, createTextVNode, toDisplayString, vShow, shallowReactive, ref, onMounted, watch, createBlock, createCommentVNode, resolveDynamicComponent, Fragment, withModifiers, isVNode, render } from "vue";
import { a as useEventListener, u as useResizeObserver } from "./index-B5MEhWj_.js";
import { b as buildProps, d as definePropType, u as useNamespace, j as isNumber, _ as _export_sfc, w as withInstall, h as isClient, q as useTimeoutFn, c as isString, g as isFunction, o as isElement, f as debugWarn, e as isBoolean, s as withInstallFunction } from "./install-La2G4dPY.js";
import { a as addUnit, u as useSizeProp } from "./index-CLW2rQKZ.js";
import { i as iconPropType, T as TypeComponentsMap, E as ElIcon, d as TypeComponents } from "./icon-DV3tCSN7.js";
import { m as mutable } from "./typescript-D6L75muK.js";
import { a as useGlobalComponentSettings, p as provideGlobalConfig } from "./use-global-config-D79ZGLfx.js";
import { E as EVENT_CODE } from "./aria-DJRDfGoO.js";
import { b as useEmptyValuesProps } from "./index-Ii41w6Nd.js";
const badgeProps = buildProps({
value: {
type: [String, Number],
default: ""
},
max: {
type: Number,
default: 99
},
isDot: Boolean,
hidden: Boolean,
type: {
type: String,
values: ["primary", "success", "warning", "info", "danger"],
default: "danger"
},
showZero: {
type: Boolean,
default: true
},
color: String,
badgeStyle: {
type: definePropType([String, Object, Array])
},
offset: {
type: definePropType(Array),
default: [0, 0]
},
badgeClass: {
type: String
}
});
const __default__$1 = defineComponent({
name: "ElBadge"
});
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
...__default__$1,
props: badgeProps,
setup(__props, { 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(() => {
var _a, _b, _c, _d, _e;
return [
{
backgroundColor: props.color,
marginRight: addUnit(-((_b = (_a = props.offset) == null ? void 0 : _a[0]) != null ? _b : 0)),
marginTop: addUnit((_d = (_c = props.offset) == null ? void 0 : _c[1]) != null ? _d : 0)
},
(_e = props.badgeStyle) != null ? _e : {}
];
});
expose({
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`,
persisted: ""
}, {
default: withCtx(() => [
withDirectives(createElementVNode("sup", {
class: normalizeClass([
unref(ns).e("content"),
unref(ns).em("content", _ctx.type),
unref(ns).is("fixed", !!_ctx.$slots.default),
unref(ns).is("dot", _ctx.isDot),
unref(ns).is("hide-zero", !_ctx.showZero && props.value === 0),
_ctx.badgeClass
]),
style: normalizeStyle(unref(style))
}, [
renderSlot(_ctx.$slots, "content", { value: unref(content) }, () => [
createTextVNode(toDisplayString(unref(content)), 1)
])
], 6), [
[vShow, !_ctx.hidden && (unref(content) || _ctx.isDot || _ctx.$slots.content)]
])
]),
_: 3
}, 8, ["name"])
], 2);
};
}
});
var Badge = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__file", "badge.vue"]]);
const ElBadge = withInstall(Badge);
const messageTypes = ["success", "info", "warning", "error"];
const messageDefaults = mutable({
customClass: "",
center: false,
dangerouslyUseHTMLString: false,
duration: 3e3,
icon: void 0,
id: "",
message: "",
onClose: void 0,
showClose: false,
type: "info",
plain: false,
offset: 16,
zIndex: 0,
grouping: false,
repeatNum: 1,
appendTo: isClient ? document.body : void 0
});
const messageProps = buildProps({
customClass: {
type: String,
default: messageDefaults.customClass
},
center: {
type: Boolean,
default: messageDefaults.center
},
dangerouslyUseHTMLString: {
type: Boolean,
default: messageDefaults.dangerouslyUseHTMLString
},
duration: {
type: Number,
default: messageDefaults.duration
},
icon: {
type: iconPropType,
default: messageDefaults.icon
},
id: {
type: String,
default: messageDefaults.id
},
message: {
type: definePropType([
String,
Object,
Function
]),
default: messageDefaults.message
},
onClose: {
type: definePropType(Function),
default: messageDefaults.onClose
},
showClose: {
type: Boolean,
default: messageDefaults.showClose
},
type: {
type: String,
values: messageTypes,
default: messageDefaults.type
},
plain: {
type: Boolean,
default: messageDefaults.plain
},
offset: {
type: Number,
default: messageDefaults.offset
},
zIndex: {
type: Number,
default: messageDefaults.zIndex
},
grouping: {
type: Boolean,
default: messageDefaults.grouping
},
repeatNum: {
type: Number,
default: messageDefaults.repeatNum
}
});
const messageEmits = {
destroy: () => true
};
const instances = shallowReactive([]);
const getInstance = (id) => {
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) => {
const { prev } = getInstance(id);
if (!prev)
return 0;
return prev.vm.exposed.bottom.value;
};
const getOffsetOrSpace = (id, offset) => {
const idx = instances.findIndex((instance) => instance.id === id);
return idx > 0 ? 16 : offset;
};
const __default__ = defineComponent({
name: "ElMessage"
});
const _sfc_main = /* @__PURE__ */ defineComponent({
...__default__,
props: messageProps,
emits: messageEmits,
setup(__props, { expose }) {
const props = __props;
const { Close } = TypeComponents;
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 lastOffset = computed(() => getLastOffset(props.id));
const offset = computed(() => getOffsetOrSpace(props.id, props.offset) + lastOffset.value);
const bottom = computed(() => height.value + offset.value);
const customStyle = computed(() => ({
top: `${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;
}
function keydown({ code }) {
if (code === 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"),
onBeforeLeave: _ctx.onClose,
onAfterLeave: ($event) => _ctx.$emit("destroy"),
persisted: ""
}, {
default: withCtx(() => [
withDirectives(createElementVNode("div", {
id: _ctx.id,
ref_key: "messageRef",
ref: messageRef,
class: normalizeClass([
unref(ns).b(),
{ [unref(ns).m(_ctx.type)]: _ctx.type },
unref(ns).is("center", _ctx.center),
unref(ns).is("closable", _ctx.showClose),
unref(ns).is("plain", _ctx.plain),
_ctx.customClass
]),
style: normalizeStyle(unref(customStyle)),
role: "alert",
onMouseenter: clearTimer,
onMouseleave: startTimer
}, [
_ctx.repeatNum > 1 ? (openBlock(), createBlock(unref(ElBadge), {
key: 0,
value: _ctx.repeatNum,
type: unref(badgeType),
class: normalizeClass(unref(ns).e("badge"))
}, null, 8, ["value", "type", "class"])) : createCommentVNode("v-if", true),
unref(iconComponent) ? (openBlock(), createBlock(unref(ElIcon), {
key: 1,
class: normalizeClass([unref(ns).e("icon"), unref(typeClass)])
}, {
default: withCtx(() => [
(openBlock(), createBlock(resolveDynamicComponent(unref(iconComponent))))
]),
_: 1
}, 8, ["class"])) : createCommentVNode("v-if", true),
renderSlot(_ctx.$slots, "default", {}, () => [
!_ctx.dangerouslyUseHTMLString ? (openBlock(), createElementBlock("p", {
key: 0,
class: normalizeClass(unref(ns).e("content"))
}, toDisplayString(_ctx.message), 3)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
createCommentVNode(" Caution here, message could've been compromised, never use user's input as message "),
createElementVNode("p", {
class: normalizeClass(unref(ns).e("content")),
innerHTML: _ctx.message
}, null, 10, ["innerHTML"])
], 2112))
]),
_ctx.showClose ? (openBlock(), createBlock(unref(ElIcon), {
key: 2,
class: normalizeClass(unref(ns).e("closeBtn")),
onClick: withModifiers(close, ["stop"])
}, {
default: withCtx(() => [
createVNode(unref(Close))
]),
_: 1
}, 8, ["class", "onClick"])) : createCommentVNode("v-if", true)
], 46, ["id"]), [
[vShow, visible.value]
])
]),
_: 3
}, 8, ["name", "onBeforeLeave", "onAfterLeave"]);
};
}
});
var MessageConstructor = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "message.vue"]]);
const configProviderProps = buildProps({
a11y: {
type: Boolean,
default: true
},
locale: {
type: definePropType(Object)
},
size: useSizeProp,
button: {
type: definePropType(Object)
},
experimentalFeatures: {
type: definePropType(Object)
},
keyboardNavigation: {
type: Boolean,
default: true
},
message: {
type: definePropType(Object)
},
zIndex: Number,
namespace: {
type: String,
default: "el"
},
...useEmptyValuesProps
});
const messageConfig = {};
defineComponent({
name: "ElConfigProvider",
props: configProviderProps,
setup(props, { slots }) {
watch(() => props.message, (val) => {
Object.assign(messageConfig, val != null ? val : {});
}, { immediate: true, deep: true });
const config = provideGlobalConfig(props);
return () => renderSlot(slots, "default", { config: config == null ? void 0 : config.value });
}
});
let seed = 1;
const normalizeOptions = (params) => {
const options = !params || isString(params) || isVNode(params) || isFunction(params) ? { message: params } : params;
const normalized = {
...messageDefaults,
...options
};
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;
}
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;
}
return normalized;
};
const closeMessage = (instance) => {
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(MessageConstructor, 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 handler = {
close: () => {
vm.exposed.visible.value = false;
}
};
const instance = {
id,
vnode,
vm,
handler,
props: vnode.component.props
};
return instance;
};
const message = (options = {}, context) => {
if (!isClient)
return { close: () => void 0 };
const normalized = normalizeOptions(options);
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) => {
const normalized = normalizeOptions(options);
return message({ ...normalized, type }, appContext);
};
});
function closeAll(type) {
for (const instance of instances) {
if (!type || type === instance.props.type) {
instance.handler.close();
}
}
}
message.closeAll = closeAll;
message._context = null;
const ElMessage = withInstallFunction(message, "$message");
export {
ElMessage,
ElMessage as default,
messageDefaults,
messageEmits,
messageProps,
messageTypes
};
//# sourceMappingURL=index-DZsFuYr2.js.map