;
+
+// 从组件实例中提取 Props 类型
+type DialogProps = ElDialogInstance["$props"] & {
+ onBeforeOpen?: () => boolean | void; // 支持显示之前钩子
+};
+
+interface ElDialogSlots {
+ header?: (...args: any[]) => Content;
+ footer?: (...args: any[]) => Content;
+}
+
+interface Options {
+ dialogProps?: DialogProps;
+ dialogSlots?: ElDialogSlots;
+ contentProps?: P;
+ callBack?: Function;
+ closeEventName?: string;
+}
+
+// 定义工具函数,获取计算属性的option
+function getOptions
(options?: Ref> | Options) {
+ if (!options) return {};
+ return isRef(options) ? options.value : options;
+}
+
+export function useDialog
(content: Content, options?: Ref> | Options) {
+ let dialogInstance: ComponentInternalInstance | null = null;
+ let fragment: Element | null = null;
+
+ // 关闭并卸载组件
+ const closeAfter = () => {
+ if (fragment) {
+ render(null, fragment as unknown as Element); // 卸载组件
+ fragment.textContent = ""; // 清空文档片段
+ fragment = null;
+ }
+ dialogInstance = null;
+ };
+
+ // 关闭对话框
+ async function closeDialog() {
+ if (dialogInstance) dialogInstance.props.modelValue = false;
+ }
+
+ // 获取当前组件实例,用于设置当前dialog的上下文,继承prototype
+ const instance = getCurrentInstance();
+
+ // 创建并挂载组件
+ function openDialog(modifyOptions?: Partial>) {
+ if (dialogInstance) {
+ closeDialog();
+ closeAfter();
+ }
+ const _options = getOptions(options);
+ // 如果有修改,则合并options。替换之前的options变量为 _options
+ if (modifyOptions) merge(_options, modifyOptions);
+ const { dialogProps, contentProps } = _options;
+
+ // 调用before钩子,如果为false则不打开
+ if (dialogProps?.onBeforeOpen?.() === false) {
+ return;
+ }
+ fragment = document.createDocumentFragment() as unknown as Element;
+
+ // 转换closeEventName事件
+ const closeEventName = `on${upperFirst(_options?.closeEventName || "closeDialog")}`;
+
+ // 定义当前块关闭前钩子变量
+ let onBeforeClose: (() => Promise | boolean | void) | null;
+
+ const vNode = h(
+ ElDialog,
+ {
+ ...dialogProps,
+ modelValue: true,
+ beforeClose: async done => {
+ // 配置`el-dialog`的关闭回调钩子函数
+ const result = await onBeforeClose?.();
+ if (result === false) {
+ return;
+ }
+ done();
+ },
+ onClosed: () => {
+ dialogProps?.onClosed?.();
+ closeAfter();
+ // 关闭后回收当前变量
+ onBeforeClose = null;
+ }
+ },
+ {
+ default: () => [
+ typeof content === "string"
+ ? content
+ : h(content as any, {
+ ...contentProps,
+ [closeEventName]: closeDialog, // 监听自定义关闭事件,并执行关闭
+ // 监听自定义回调事件,并执行关闭
+ callBack: (data: any) => {
+ if (_options.callBack) _options.callBack(data);
+ closeDialog();
+ },
+ beforeCloseDialog: (fn: () => boolean | void) => {
+ // 把`beforeCloseDialog`传递给`content`,当组件内部使用`props.beforeCloseDialog(fn)`时,会把fn传递给`onBeforeClose`
+ onBeforeClose = fn;
+ }
+ })
+ ],
+ ..._options.dialogSlots
+ }
+ );
+
+ // 设置当前的上下文为使用者的上下文
+ vNode.appContext = instance?.appContext || null;
+ render(vNode, fragment);
+ dialogInstance = vNode.component;
+ document.body.appendChild(fragment);
+ }
+
+ onUnmounted(() => {
+ closeDialog();
+ });
+
+ return { openDialog, closeDialog };
+}
diff --git a/src/hooks/useECharts.ts b/src/hooks/useECharts.ts
new file mode 100644
index 00000000..28461fa7
--- /dev/null
+++ b/src/hooks/useECharts.ts
@@ -0,0 +1,93 @@
+import * as echarts from "echarts";
+import { onActivated, onDeactivated, onMounted, onUnmounted, reactive, Ref, shallowRef, watch } from "vue";
+
+// 定义一个策略接口 , 方便具体策略实现使用
+export interface ChartStrategy {
+ getOptions: () => echarts.EChartsOption;
+}
+
+// 自定义的 Vue 钩子函数,用于管理 ECharts 实例
+export function useECharts(
+ chartRef: Ref, // chartRef 是一个引用,指向包含图表的 DOM 元素
+ initOptions: echarts.EChartsOption, // strategy 是一个接口,提供获取图表配置的方法
+ theme?: string | object | null, // 可选的 theme 参数,用于设置 ECharts 主题
+ opts?: echarts.EChartsInitOpts // 可选的 opts 参数,用于初始化 ECharts 的配置
+) {
+ // 使用 shallowRef 创建一个响应式引用,用于保存 ECharts 实例
+ const instance = shallowRef(null);
+
+ // 使用 ref 创建一个响应式引用,用于保存图表的配置选项
+ const options = reactive(initOptions);
+
+ // 初始化图表实例的函数
+ const initEchart = () => {
+ // 确保 chartRef 绑定了 DOM 元素且 instance 尚未初始化
+ if (chartRef.value && !instance.value) {
+ // 初始化 ECharts 实例并赋值给 instance
+ instance.value = echarts.init(chartRef.value, theme, opts);
+ // 设置图表的初始选项
+ instance.value.setOption(options);
+ }
+ };
+
+ // 更新图表配置选项的函数
+ const updateEchartOptions = (newOptions: echarts.EChartsOption) => {
+ if (instance.value) {
+ // 使用新的选项更新图表,不合并现有选项并延迟更新以优化性能
+ instance.value.setOption(newOptions, { notMerge: true, lazyUpdate: true });
+ }
+ };
+
+ // 处理窗口大小调整的函数,确保图表能够自动调整大小
+ const handleResize = () => {
+ instance.value?.resize(); // 如果 instance 存在,则调用 resize 方法
+ };
+
+ // 销毁图表实例的函数,释放内存并清空引用
+ const disposeEchart = () => {
+ instance.value?.dispose(); // 调用 ECharts 的 dispose 方法销毁实例
+ instance.value = null; // 清空 instance 引用,避免内存泄漏
+ };
+
+ // 监听 options 的变化,并在其发生改变时更新图表
+ watch(
+ () => options,
+ () => updateEchartOptions,
+ { deep: true }
+ );
+
+ // 组件挂载时初始化图表并添加窗口大小调整的事件监听器
+ onMounted(() => {
+ initEchart(); // 初始化图表
+ window.addEventListener("resize", handleResize); // 监听窗口大小变化
+ });
+
+ // 组件卸载时移除事件监听器并销毁图表实例
+ onUnmounted(() => {
+ window.removeEventListener("resize", handleResize); // 移除窗口大小调整的监听器
+ disposeEchart(); // 销毁图表实例
+ });
+
+ // 组件激活时重新初始化图表并添加事件监听器
+ onActivated(() => {
+ if (!instance.value) {
+ initEchart(); // 如果图表实例不存在,重新初始化
+ }
+ window.addEventListener("resize", handleResize); // 监听窗口大小变化
+ });
+
+ // 组件停用时移除事件监听器并销毁图表实例
+ onDeactivated(() => {
+ window.removeEventListener("resize", handleResize); // 移除窗口大小调整的监听器
+ disposeEchart(); // 销毁图表实例
+ });
+
+ // 返回 instance 和相关的控制方法,供外部组件使用
+ return {
+ instance, // 返回图表实例的引用
+ options, // 返回图表配置选项的引用
+ initEchart, // 返回初始化图表的方法
+ handleResize, // 返回手动触发图表调整大小的方法
+ disposeEchart // 返回手动销毁图表实例的方法
+ };
+}
diff --git a/src/views/assembly/dialog/useDialog/index.vue b/src/views/assembly/dialog/useDialog/index.vue
new file mode 100644
index 00000000..e99aa42a
--- /dev/null
+++ b/src/views/assembly/dialog/useDialog/index.vue
@@ -0,0 +1,58 @@
+
+
+
useDialog hooks 操作弹框🍓🍇🍈🍉
+
+
打开弹框
+
+
+
useDialog hooks介绍 📚
+
+ 在 Vue 中,Hook 允许在函数式组件或者 API 中「钩入」Vue 特性。它们通常在组合式 API(Composition API)中使用,这是 Vue
+ 提供的一套响应式和可复用逻辑功能的集合。 本文提到的 useDialog Hook 就是一个封装了 el-dialog 组件基本功能的自定义
+ Hook,它还可以提供附加特性以便在项目中管理和展示弹窗。
+
+
主要实现功能📚
+
+ - 满足基础用法,传入 el-dialog 的基础属性以及默认slot显示的内容,导出 openDialog 和 closeDialog 函数;
+ - 支持 el-dialog 的事件配置;
+ - 支持默认 slot 组件的属性配置;
+ - 支持 el-dialog 其他 slot 配置,例如 header 和 footer 等;
+ - 在内容组件中抛出特定事件支持关闭 dialog;
+ - 支持显示内容为 jsx、普通文本、Vue Component;
+ - 支持在显示内容中控制是否可以关闭的回调函数,例如 beforeClose;
+ - 支持显示之前钩子,例如 onBeforeOpen;
+ - 支持定义和弹出时修改配置属性;
+ - 支持继承 root vue 的 prototype,可以使用如 vue-i18n 的 $t 函数;
+ - 支持 ts 参数提示;
+
+
+
+
+
+
+
+
diff --git a/src/views/assembly/dialog/useDialog/test.vue b/src/views/assembly/dialog/useDialog/test.vue
new file mode 100644
index 00000000..c7f9bb26
--- /dev/null
+++ b/src/views/assembly/dialog/useDialog/test.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+ Online activities
+ Promotion activities
+ Offline activities
+ Simple brand exposure
+
+
+
+
+ Sponsor
+ Venue
+
+
+
+
+
+
+ Create
+ Cancel
+
+
+
+
+
diff --git a/src/views/echarts/lineChart/index.vue b/src/views/echarts/lineChart/index.vue
index 4c9c3bf2..02971d8e 100644
--- a/src/views/echarts/lineChart/index.vue
+++ b/src/views/echarts/lineChart/index.vue
@@ -1,12 +1,130 @@
-
-