mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-04 07:27:41 +08:00
feat: 添加 message
消息提示函数,兼容 Element Plus
和 Ant Design
两种 Message
风格
This commit is contained in:
parent
667ef918fc
commit
33bd64d9ff
@ -37,6 +37,7 @@ menus:
|
||||
hsfourZeroOne: "403"
|
||||
hsFive: "500"
|
||||
hscomponents: Components
|
||||
hsmessage: Message Tips Components
|
||||
hsvideo: Video Components
|
||||
hsmap: Map Components
|
||||
hsdraggable: Draggable Components
|
||||
|
@ -37,6 +37,7 @@ menus:
|
||||
hsfourZeroOne: "403"
|
||||
hsFive: "500"
|
||||
hscomponents: 组件
|
||||
hsmessage: 消息提示组件
|
||||
hsvideo: 视频组件
|
||||
hsmap: 地图组件
|
||||
hsdraggable: 拖拽组件
|
||||
|
@ -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")
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
196
src/views/components/message/index.vue
Normal file
196
src/views/components/message/index.vue
Normal file
@ -0,0 +1,196 @@
|
||||
<script setup lang="ts">
|
||||
import { h } from "vue";
|
||||
import hot from "@/assets/svg/hot.svg?component";
|
||||
import { message, closeAllMessage } from "@/utils/message";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "Message"
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="font-medium"> Message提示 </span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<h4 class="mb-4">element-plus 的消息提示,点击弹出提示信息</h4>
|
||||
|
||||
<el-space>
|
||||
<el-button
|
||||
type="info"
|
||||
@click="message('Info类型消息', { customClass: 'el' })"
|
||||
>
|
||||
Info
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="
|
||||
message('Success类型消息', { customClass: 'el', type: 'success' })
|
||||
"
|
||||
>
|
||||
Success
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
@click="
|
||||
message('Warning类型消息', { customClass: 'el', type: 'warning' })
|
||||
"
|
||||
>
|
||||
Warning
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="message('Error类型消息', { customClass: 'el', type: 'error' })"
|
||||
>
|
||||
Error
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="message('可关闭消息', { customClass: 'el', showClose: true })"
|
||||
>
|
||||
可关闭
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('分组消息合并', {
|
||||
customClass: 'el',
|
||||
type: 'success',
|
||||
grouping: true
|
||||
})
|
||||
"
|
||||
>
|
||||
分组消息合并
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('自定义消息图标', {
|
||||
customClass: 'el',
|
||||
icon: useRenderIcon('check')
|
||||
})
|
||||
"
|
||||
>
|
||||
自定义图标
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('3秒后关闭', {
|
||||
customClass: 'el',
|
||||
duration: 3000,
|
||||
onClose: () =>
|
||||
message('消息已关闭', { customClass: 'el', type: 'success' })
|
||||
})
|
||||
"
|
||||
>
|
||||
自定义延时关闭时间并设置关闭后其他操作
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message(
|
||||
h('p', null, [
|
||||
h('span', null, 'Message can be '),
|
||||
h('i', { style: 'color: teal' }, 'VNode')
|
||||
]),
|
||||
{ customClass: 'el' }
|
||||
)
|
||||
"
|
||||
>
|
||||
自定义内容
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('<strong>This is <i>HTML</i> string</strong>', {
|
||||
customClass: 'el',
|
||||
dangerouslyUseHTMLString: true
|
||||
})
|
||||
"
|
||||
>
|
||||
HTML 片段作为正文内容
|
||||
</el-button>
|
||||
</el-space>
|
||||
|
||||
<el-divider />
|
||||
|
||||
<h4 class="mb-4">
|
||||
类似 Ant Design 风格的消息提示,点击弹出提示信息(基于 ElMessage
|
||||
样式改版,不会影响 ElMessage
|
||||
原本样式,使用和打包大小成本极低并适配暗黑模式)
|
||||
</h4>
|
||||
|
||||
<el-space>
|
||||
<el-button type="info" @click="message('Info类型消息')">Info</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="message('Success类型消息', { type: 'success' })"
|
||||
>
|
||||
Success
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
@click="message('Warning类型消息', { type: 'warning' })"
|
||||
>
|
||||
Warning
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="message('Error类型消息', { type: 'error' })"
|
||||
>
|
||||
Error
|
||||
</el-button>
|
||||
<el-button @click="message('可关闭消息', { showClose: true })">
|
||||
可关闭
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="message('分组消息合并', { type: 'success', grouping: true })"
|
||||
>
|
||||
分组消息合并
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('自定义消息图标', {
|
||||
icon: hot
|
||||
})
|
||||
"
|
||||
>
|
||||
自定义图标
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('3秒后关闭', {
|
||||
duration: 3000,
|
||||
onClose: () => message('消息已关闭', { type: 'success' })
|
||||
})
|
||||
"
|
||||
>
|
||||
自定义延时关闭时间并设置关闭后其他操作
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message(
|
||||
h('p', null, [
|
||||
h('span', null, 'Message can be '),
|
||||
h('i', { style: 'color: teal' }, 'VNode')
|
||||
])
|
||||
)
|
||||
"
|
||||
>
|
||||
自定义内容
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
message('<strong>This is <i>HTML</i> string</strong>', {
|
||||
dangerouslyUseHTMLString: true
|
||||
})
|
||||
"
|
||||
>
|
||||
HTML 片段作为正文内容
|
||||
</el-button>
|
||||
</el-space>
|
||||
|
||||
<el-divider />
|
||||
|
||||
<el-button @click="closeAllMessage"> 关闭所有消息提示 </el-button>
|
||||
</el-card>
|
||||
</template>
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -73,7 +73,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
||||
// 获取后端路由
|
||||
initRouter().then(() => {
|
||||
router.push("/");
|
||||
message("登录成功", "success");
|
||||
message("登录成功", { type: "success" });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -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 {
|
||||
|
@ -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 = [
|
||||
|
@ -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;
|
||||
}
|
||||
</style>
|
||||
|
@ -37,7 +37,9 @@ export function useColumns() {
|
||||
`您编辑了第 ${
|
||||
dataList.value.findIndex(v => v.id === row.id) + 1
|
||||
} 行,数据为:${JSON.stringify(row)}`,
|
||||
"success"
|
||||
{
|
||||
type: "success"
|
||||
}
|
||||
)
|
||||
}
|
||||
]
|
||||
|
@ -78,7 +78,9 @@ export function useColumns() {
|
||||
callback: ({ data: { name, value } }) => {
|
||||
message(
|
||||
`您点击了第 ${i + 1} 行,图表标题为${name},图表数据为:${value}`,
|
||||
"success"
|
||||
{
|
||||
type: "success"
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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], {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
</style>
|
||||
|
@ -113,7 +113,9 @@ export function useColumns() {
|
||||
loading: false
|
||||
}
|
||||
);
|
||||
message("已成功修改角色状态", "success");
|
||||
message("已成功修改角色状态", {
|
||||
type: "success"
|
||||
});
|
||||
}, 300);
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -118,7 +118,9 @@ export function useColumns() {
|
||||
loading: false
|
||||
}
|
||||
);
|
||||
message("已成功修改用户状态", "success");
|
||||
message("已成功修改用户状态", {
|
||||
type: "success"
|
||||
});
|
||||
}, 300);
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -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"]
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user