diff --git a/locales/en.yaml b/locales/en.yaml index 89c6a7140..5c965520e 100644 --- a/locales/en.yaml +++ b/locales/en.yaml @@ -37,6 +37,7 @@ menus: hsfourZeroOne: "403" hsFive: "500" hscomponents: Components + hsmessage: Message Tips Components hsvideo: Video Components hsmap: Map Components hsdraggable: Draggable Components diff --git a/locales/zh-CN.yaml b/locales/zh-CN.yaml index f7c370468..5db781115 100644 --- a/locales/zh-CN.yaml +++ b/locales/zh-CN.yaml @@ -37,6 +37,7 @@ menus: hsfourZeroOne: "403" hsFive: "500" hscomponents: 组件 + hsmessage: 消息提示组件 hsvideo: 视频组件 hsmap: 地图组件 hsdraggable: 拖拽组件 diff --git a/src/router/modules/components.ts b/src/router/modules/components.ts index 26feab9c0..43b880c7c 100644 --- a/src/router/modules/components.ts +++ b/src/router/modules/components.ts @@ -10,6 +10,18 @@ export default { rank: components }, children: [ + { + path: "/components/message", + name: "Message", + component: () => import("@/views/components/message/index.vue"), + meta: { + title: $t("menus.hsmessage"), + extraIcon: { + svg: true, + name: "team-iconxinpinrenqiwang" + } + } + }, { path: "/components/video", name: "Video", @@ -47,11 +59,7 @@ export default { name: "SplitPane", component: () => import("@/views/components/split-pane/index.vue"), meta: { - title: $t("menus.hssplitPane"), - extraIcon: { - svg: true, - name: "team-iconxinpinrenqiwang" - } + title: $t("menus.hssplitPane") } }, { diff --git a/src/style/dark.scss b/src/style/dark.scss index 23008ada6..348575631 100644 --- a/src/style/dark.scss +++ b/src/style/dark.scss @@ -186,4 +186,18 @@ html.dark { .el-dropdown-menu__item:not(.is-disabled):hover { background: transparent; } + + /* 克隆并自定义 ElMessage 样式,不会影响 ElMessage 原本样式,在 src/utils/message.ts 中调用自定义样式 ElMessage 方法即可,非暗黑模式在 src/style/element-plus.scss 文件进行了适配 */ + .pure-message { + background-image: initial !important; + background-color: rgb(36, 37, 37) !important; + box-shadow: rgb(13 13 13 / 12%) 0px 3px 6px -4px, + rgb(13 13 13 / 8%) 0px 6px 16px 0px, rgb(13 13 13 / 5%) 0px 9px 28px 8px !important; + + & .el-message__content { + color: $color-white !important; + pointer-events: all !important; + background-image: initial !important; + } + } } diff --git a/src/style/element-plus.scss b/src/style/element-plus.scss index a24c30fb6..aa357b95c 100644 --- a/src/style/element-plus.scss +++ b/src/style/element-plus.scss @@ -62,3 +62,30 @@ border-left-color: var(--el-color-primary); } } + +/* 克隆并自定义 ElMessage 样式,不会影响 ElMessage 原本样式,在 src/utils/message.ts 中调用自定义样式 ElMessage 方法即可,暗黑模式在 src/style/dark.scss 文件进行了适配 */ +.pure-message { + border-width: 0 !important; + background: #fff !important; + padding: 10px 13px !important; + box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, + 0 9px 28px 8px #0000000d !important; + + &.el-message.is-closable .el-message__content { + padding-right: 17px !important; + } + + & .el-message__content { + color: #000000d9 !important; + pointer-events: all !important; + background-image: initial !important; + } + + & .el-message__icon { + margin-right: 8px !important; + } + + & .el-message__closeBtn { + right: 9px !important; + } +} diff --git a/src/utils/message.ts b/src/utils/message.ts index 86b631cbf..54b100f59 100644 --- a/src/utils/message.ts +++ b/src/utils/message.ts @@ -1,32 +1,84 @@ +import { type VNode } from "vue"; +import { isFunction } from "@pureadmin/utils"; import { type MessageHandler, ElMessage } from "element-plus"; -// 更多配置请看:https://element-plus.org/zh-CN/component/message.html#message-%E9%85%8D%E7%BD%AE%E9%A1%B9 +type messageStyle = "el" | "antd"; +type messageTypes = "info" | "success" | "warning" | "error"; -type messageTypes = "success" | "info" | "warning" | "error"; +interface MessageParams { + /** 消息类型,可选 `info` 、`success` 、`warning` 、`error` ,默认 `info` */ + type?: messageTypes; + /** 自定义图标,该属性会覆盖 `type` 的图标 */ + icon?: any; + /** 是否将 `message` 属性作为 `HTML` 片段处理,默认 `false` */ + dangerouslyUseHTMLString?: boolean; + /** 消息风格,可选 `el` 、`antd` ,默认 `antd` */ + customClass?: messageStyle; + /** 显示时间,单位为毫秒。设为 `0` 则不会自动关闭,`element-plus` 默认是 `3000` ,平台改成默认 `2000` */ + duration?: number; + /** 是否显示关闭按钮,默认值 `false` */ + showClose?: boolean; + /** 文字是否居中,默认值 `false` */ + center?: boolean; + /** `Message` 距离窗口顶部的偏移量,默认 `20` */ + offset?: number; + /** 设置组件的根元素,默认 `document.body` */ + appendTo?: string | HTMLElement; + /** 合并内容相同的消息,不支持 `VNode` 类型的消息,默认值 `false` */ + grouping?: boolean; + /** 关闭时的回调函数, 参数为被关闭的 `message` 实例 */ + onClose?: Function | null; +} + +/** 用法非常简单,参考 src/views/components/message/index.vue 文件 */ /** - * `element-plus` 的 `info` 消息类型 + * `Message` 消息提示函数 */ const message = ( - message: string, - type = "info" as messageTypes, - showClose = true, - duration = 2000, - center = false, - grouping = false + message: string | VNode | (() => VNode), + params?: MessageParams ): MessageHandler => { - return ElMessage({ - message, - type, - showClose, - duration, - center, - grouping - }); + if (!params) { + return ElMessage({ + message, + customClass: "pure-message" + }); + } else { + const { + icon, + type = "info", + dangerouslyUseHTMLString = false, + customClass = "antd", + duration = 2000, + showClose = false, + center = false, + offset = 20, + appendTo = document.body, + grouping = false, + onClose + } = params; + + return ElMessage({ + message, + type, + icon, + dangerouslyUseHTMLString, + duration, + showClose, + center, + offset, + appendTo, + grouping, + // 全局搜 pure-message 即可知道该类的样式位置 + customClass: customClass === "antd" ? "pure-message" : "", + onClose: () => (isFunction(onClose) ? onClose() : null) + }); + } }; /** - * 关闭 `element-plus` 的所有消息实例 + * 关闭所有 `Message` 消息提示函数 */ const closeAllMessage = (): void => ElMessage.closeAll(); diff --git a/src/views/components/message/index.vue b/src/views/components/message/index.vue new file mode 100644 index 000000000..23c330d3a --- /dev/null +++ b/src/views/components/message/index.vue @@ -0,0 +1,196 @@ + + + diff --git a/src/views/login/components/phone.vue b/src/views/login/components/phone.vue index 583fe6e9b..4d547c625 100644 --- a/src/views/login/components/phone.vue +++ b/src/views/login/components/phone.vue @@ -26,7 +26,7 @@ const onLogin = async (formEl: FormInstance | undefined) => { if (valid) { // 模拟登录请求,需根据实际开发进行修改 setTimeout(() => { - message(transformI18n($t("login.loginSuccess")), "success"); + message(transformI18n($t("login.loginSuccess")), { type: "success" }); loading.value = false; }, 2000); } else { diff --git a/src/views/login/components/regist.vue b/src/views/login/components/regist.vue index 4110f4591..523889a6a 100644 --- a/src/views/login/components/regist.vue +++ b/src/views/login/components/regist.vue @@ -45,12 +45,14 @@ const onUpdate = async (formEl: FormInstance | undefined) => { if (checked.value) { // 模拟请求,需根据实际开发进行修改 setTimeout(() => { - message(transformI18n($t("login.registerSuccess")), "success"); + message(transformI18n($t("login.registerSuccess")), { + type: "success" + }); loading.value = false; }, 2000); } else { loading.value = false; - message(transformI18n($t("login.tickPrivacy")), "warning"); + message(transformI18n($t("login.tickPrivacy")), { type: "warning" }); } } else { loading.value = false; diff --git a/src/views/login/components/update.vue b/src/views/login/components/update.vue index 984450111..3b973c091 100644 --- a/src/views/login/components/update.vue +++ b/src/views/login/components/update.vue @@ -42,7 +42,9 @@ const onUpdate = async (formEl: FormInstance | undefined) => { if (valid) { // 模拟请求,需根据实际开发进行修改 setTimeout(() => { - message(transformI18n($t("login.passwordUpdateReg")), "success"); + message(transformI18n($t("login.passwordUpdateReg")), { + type: "success" + }); loading.value = false; }, 2000); } else { diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 122ab3328..fa76f5286 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -73,7 +73,7 @@ const onLogin = async (formEl: FormInstance | undefined) => { // 获取后端路由 initRouter().then(() => { router.push("/"); - message("登录成功", "success"); + message("登录成功", { type: "success" }); }); } }); diff --git a/src/views/pure-table/base/column-template/columns.tsx b/src/views/pure-table/base/column-template/columns.tsx index 26066cb8b..0e6f53bd2 100644 --- a/src/views/pure-table/base/column-template/columns.tsx +++ b/src/views/pure-table/base/column-template/columns.tsx @@ -56,14 +56,13 @@ export function useColumns() { ]; const handleEdit = (index: number, row) => { - message( - `您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`, - "success" - ); + message(`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`, { + type: "success" + }); }; const handleDelete = (index: number, row) => { - message(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`, "info"); + message(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`); }; return { diff --git a/src/views/pure-table/base/header-renderer/columns.tsx b/src/views/pure-table/base/header-renderer/columns.tsx index 08e4bbf71..d7871d55f 100644 --- a/src/views/pure-table/base/header-renderer/columns.tsx +++ b/src/views/pure-table/base/header-renderer/columns.tsx @@ -15,14 +15,13 @@ export function useColumns() { ); const handleEdit = (index: number, row) => { - message( - `您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`, - "success" - ); + message(`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`, { + type: "success" + }); }; const handleDelete = (index: number, row) => { - message(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`, "info"); + message(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`); }; const columns: TableColumnList = [ diff --git a/src/views/pure-table/high.vue b/src/views/pure-table/high.vue index ef011f828..7f978207d 100644 --- a/src/views/pure-table/high.vue +++ b/src/views/pure-table/high.vue @@ -68,4 +68,15 @@ function tabClick({ index }) { :deep(.el-alert__title) { font-size: 16px; } + +:deep(.el-tabs__nav-next), +:deep(.el-tabs__nav-prev) { + font-size: 16px; + color: var(--el-text-color-primary); +} + +:deep(.el-tabs__nav-next.is-disabled), +:deep(.el-tabs__nav-prev.is-disabled) { + opacity: 0.5; +} diff --git a/src/views/pure-table/high/contextmenu/columns.tsx b/src/views/pure-table/high/contextmenu/columns.tsx index 3ab9e2f0c..5a791618a 100644 --- a/src/views/pure-table/high/contextmenu/columns.tsx +++ b/src/views/pure-table/high/contextmenu/columns.tsx @@ -37,7 +37,9 @@ export function useColumns() { `您编辑了第 ${ dataList.value.findIndex(v => v.id === row.id) + 1 } 行,数据为:${JSON.stringify(row)}`, - "success" + { + type: "success" + } ) } ] diff --git a/src/views/pure-table/high/echarts/columns.tsx b/src/views/pure-table/high/echarts/columns.tsx index 8d7c77546..8095e322f 100644 --- a/src/views/pure-table/high/echarts/columns.tsx +++ b/src/views/pure-table/high/echarts/columns.tsx @@ -78,7 +78,9 @@ export function useColumns() { callback: ({ data: { name, value } }) => { message( `您点击了第 ${i + 1} 行,图表标题为${name},图表数据为:${value}`, - "success" + { + type: "success" + } ); } } diff --git a/src/views/pure-table/high/edit/columns.tsx b/src/views/pure-table/high/edit/columns.tsx index e1cd80657..befd978d4 100644 --- a/src/views/pure-table/high/edit/columns.tsx +++ b/src/views/pure-table/high/edit/columns.tsx @@ -113,7 +113,9 @@ export function useColumns() { `您编辑了第 ${index + 1} 行,编辑后数据为:${JSON.stringify( dataList.value[index] )}`, - "success" + { + type: "success" + } ); // 编辑状态关闭 editStatus.value[index] = Object.assign({}, editStatus.value[index], { diff --git a/src/views/pure-table/high/execl/columns.tsx b/src/views/pure-table/high/execl/columns.tsx index d028265d7..7ddcb1ac2 100644 --- a/src/views/pure-table/high/execl/columns.tsx +++ b/src/views/pure-table/high/execl/columns.tsx @@ -39,7 +39,9 @@ export function useColumns() { const workBook = utils.book_new(); utils.book_append_sheet(workBook, workSheet, "数据报表"); writeFile(workBook, "pure-admin-table.xlsx"); - message("导出成功", "success"); + message("导出成功", { + type: "success" + }); }; return { diff --git a/src/views/pure-table/index.vue b/src/views/pure-table/index.vue index e9ec2b5c2..dcf3716c1 100644 --- a/src/views/pure-table/index.vue +++ b/src/views/pure-table/index.vue @@ -62,4 +62,15 @@ defineOptions({ :deep(.el-alert__title) { font-size: 16px; } + +:deep(.el-tabs__nav-next), +:deep(.el-tabs__nav-prev) { + font-size: 16px; + color: var(--el-text-color-primary); +} + +:deep(.el-tabs__nav-next.is-disabled), +:deep(.el-tabs__nav-prev.is-disabled) { + opacity: 0.5; +} diff --git a/src/views/system/role/columns.tsx b/src/views/system/role/columns.tsx index 9849d0323..e37e90d7c 100644 --- a/src/views/system/role/columns.tsx +++ b/src/views/system/role/columns.tsx @@ -113,7 +113,9 @@ export function useColumns() { loading: false } ); - message("已成功修改角色状态", "success"); + message("已成功修改角色状态", { + type: "success" + }); }, 300); }) .catch(() => { diff --git a/src/views/system/user/columns.tsx b/src/views/system/user/columns.tsx index dda65a04f..2ef28e2da 100644 --- a/src/views/system/user/columns.tsx +++ b/src/views/system/user/columns.tsx @@ -118,7 +118,9 @@ export function useColumns() { loading: false } ); - message("已成功修改用户状态", "success"); + message("已成功修改用户状态", { + type: "success" + }); }, 300); }) .catch(() => { diff --git a/tsconfig.json b/tsconfig.json index 0cb30b9a7..4252509a9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,7 +29,8 @@ "element-plus/global", "@pureadmin/table/volar", "@pureadmin/descriptions/volar", - "unplugin-vue-macros/macros-global" + "unplugin-vue-macros/macros-global", + "unplugin-vue-define-options/macros-global" ], "typeRoots": ["./node_modules/@types/", "./types"] },