From d4be577138f33c95545585ac3fca1f651d9b2101 Mon Sep 17 00:00:00 2001 From: GAtomis <850680822@qq.com> Date: Mon, 27 Mar 2023 11:53:03 +0800 Subject: [PATCH] update : message --- packages/aux-admin/aux-ui/main.ts | 7 +- packages/aux-admin/aux-ui/styles/global.scss | 8 + packages/aux-admin/aux-ui/styles/icon.scss | 2 +- .../aux-admin/aux-ui/wise-message/index.ts | 8 +- .../src/components/close-icon.tsx | 13 ++ .../wise-message/src/components/index.tsx | 25 +++ .../aux-ui/wise-message/src/instance.tsx | 51 ++++++ .../wise-message/src/wise-message-service.tsx | 98 +++++++++++ .../wise-message/src/wise-message-types.ts | 56 ++++++- .../aux-ui/wise-message/src/wise-message.scss | 130 +++++++++++++++ .../aux-ui/wise-message/src/wise-message.tsx | 152 +++++++++++++++++- .../docs/.vitepress/layout/sidebar.ts | 24 ++- .../wise/message/demo-codes/demo-slot.vue | 35 ++++ .../wise/message/demo-codes/demo.vue | 28 ++++ .../docs/components/wise/message/index.md | 32 ++++ 15 files changed, 646 insertions(+), 23 deletions(-) create mode 100644 packages/aux-admin/aux-ui/wise-message/src/components/close-icon.tsx create mode 100644 packages/aux-admin/aux-ui/wise-message/src/components/index.tsx create mode 100644 packages/aux-admin/aux-ui/wise-message/src/instance.tsx create mode 100644 packages/aux-admin/aux-ui/wise-message/src/wise-message-service.tsx create mode 100644 packages/aux-admin/docs/components/wise/message/demo-codes/demo-slot.vue create mode 100644 packages/aux-admin/docs/components/wise/message/demo-codes/demo.vue create mode 100644 packages/aux-admin/docs/components/wise/message/index.md diff --git a/packages/aux-admin/aux-ui/main.ts b/packages/aux-admin/aux-ui/main.ts index c2df951..31a3e15 100644 --- a/packages/aux-admin/aux-ui/main.ts +++ b/packages/aux-admin/aux-ui/main.ts @@ -10,6 +10,7 @@ import nobleCardInstall,{NobleCard} from "./noble-card" import nobleSwiperInstall,{Swiper,SwiperItem} from "./swiper" import nobleCollapseInstall ,{NobleCollapse,NobleCollapseItem} from './noble-collapse' import collapseTransitionInstall ,{CollapseTransition} from './collapse-transition' +import wiseMessageInstall, { Message as WiseMessage } from './wise-message'; import "./styles/global.scss" const installs = [ GfgButtonInstall, @@ -22,7 +23,8 @@ const installs = [ nobleCardInstall, nobleSwiperInstall, nobleCollapseInstall, - collapseTransitionInstall + collapseTransitionInstall, + wiseMessageInstall ] export { @@ -38,7 +40,8 @@ export { SwiperItem, NobleCollapse, NobleCollapseItem, - CollapseTransition + CollapseTransition, + WiseMessage } export default { verison: '0.0.1', diff --git a/packages/aux-admin/aux-ui/styles/global.scss b/packages/aux-admin/aux-ui/styles/global.scss index 69c759b..6ceedc4 100644 --- a/packages/aux-admin/aux-ui/styles/global.scss +++ b/packages/aux-admin/aux-ui/styles/global.scss @@ -59,6 +59,7 @@ $globa-prefix: aux; --aux-fill-color-blank:#fff; --aux-transition-duration:.3s; +// wise // Colors @@ -69,6 +70,13 @@ $globa-prefix: aux; --white: #ffffff; --blue: #0071e3; --blueRgba: "0, 113, 227"; + --black: #000000; + --primary:#409eff; + --success:#67c23a; + --warning:#e6a23c; + --danger:#f56c6c; + --error: #f56c6c; + --info:#909399; //fonts --fontL: "Source Sans Pro light"; diff --git a/packages/aux-admin/aux-ui/styles/icon.scss b/packages/aux-admin/aux-ui/styles/icon.scss index 89dda13..e6b1c0a 100644 --- a/packages/aux-admin/aux-ui/styles/icon.scss +++ b/packages/aux-admin/aux-ui/styles/icon.scss @@ -1 +1 @@ -@import "//at.alicdn.com/t/c/font_3882013_ze9zyogk6e.css"; \ No newline at end of file +@import "//at.alicdn.com/t/c/font_3882013_3q6kp24fxh9.css"; \ No newline at end of file diff --git a/packages/aux-admin/aux-ui/wise-message/index.ts b/packages/aux-admin/aux-ui/wise-message/index.ts index a7027c0..486e31f 100644 --- a/packages/aux-admin/aux-ui/wise-message/index.ts +++ b/packages/aux-admin/aux-ui/wise-message/index.ts @@ -1,15 +1,15 @@ import type { App } from 'vue'; -import WiseMessage from './src/wise-message'; +import Message from './src/wise-message-service'; export * from './src/wise-message-types'; -export { WiseMessage }; +export { Message }; export default { title: 'WiseMessage 万设消息弹出框', category: '通用', - status: '1%', // TODO 组件完成状态,开发完组件新特性请及时更新该状态值;若组件开发完成则填入'100%',并删除该注释 + status: '100%', // TODO 组件完成状态,开发完组件新特性请及时更新该状态值;若组件开发完成则填入'100%',并删除该注释 install(app: App): void { - app.component(WiseMessage.name, WiseMessage); + app.config.globalProperties.$message = Message; } }; diff --git a/packages/aux-admin/aux-ui/wise-message/src/components/close-icon.tsx b/packages/aux-admin/aux-ui/wise-message/src/components/close-icon.tsx new file mode 100644 index 0000000..845bdad --- /dev/null +++ b/packages/aux-admin/aux-ui/wise-message/src/components/close-icon.tsx @@ -0,0 +1,13 @@ +import { defineComponent } from 'vue'; +import { useNamespace } from '../../../shared/hooks/use-namespace'; +export default defineComponent({ + emits: ['click'], + setup(props, { emit }) { + const ns = useNamespace('wise-message') + return () => ( +
emit('click', e)}> + +
+ ); + }, +}); \ No newline at end of file diff --git a/packages/aux-admin/aux-ui/wise-message/src/components/index.tsx b/packages/aux-admin/aux-ui/wise-message/src/components/index.tsx new file mode 100644 index 0000000..4720e6c --- /dev/null +++ b/packages/aux-admin/aux-ui/wise-message/src/components/index.tsx @@ -0,0 +1,25 @@ + + +export function SuccessIcon() { + return ( + + ) +} +export function InfoIcon() { + return ( + + ) +} +export function WarningIcon() { + return ( + + ) +} +export function ErrorIcon() { + return ( + + ) +} + + + \ No newline at end of file diff --git a/packages/aux-admin/aux-ui/wise-message/src/instance.tsx b/packages/aux-admin/aux-ui/wise-message/src/instance.tsx new file mode 100644 index 0000000..22c5212 --- /dev/null +++ b/packages/aux-admin/aux-ui/wise-message/src/instance.tsx @@ -0,0 +1,51 @@ +import { shallowReactive,createApp,onUnmounted } from 'vue'; +import type { App } from 'vue'; +import type { EmitEventFn, WiseMessageOption } from './wise-message-types'; +import Message from './wise-message'; + +export type MessageContext = { + id: string; + handler?: EmitEventFn; + props: WiseMessageOption; +}; + +export const instances: MessageContext[] = shallowReactive([]); + +export const getLastOffset = (id: string): number => { + const idx = instances.findIndex((instance) => instance.id === id); + return idx * 65 + 80; +}; + +export const deleteInstance = (id: string | undefined): number => { + const idx = instances.findIndex((instance) => instance.id === id); + if (idx !== -1) { + instances.splice(idx, 1); + } + return idx; +}; + +export const initInstance = (id: string, props: WiseMessageOption, message?: string): MessageContext => { + const container = document.createElement('div'); + container.id = id; + const app: App = createApp({ + setup() { + onUnmounted(() => { + document.body.removeChild(container); + }); + + return () => ( + + {message} + + ); + }, + }); + + document.body.appendChild(container); + app.mount(container); + + return { + id, + props, + }; +}; diff --git a/packages/aux-admin/aux-ui/wise-message/src/wise-message-service.tsx b/packages/aux-admin/aux-ui/wise-message/src/wise-message-service.tsx new file mode 100644 index 0000000..2c6c5cd --- /dev/null +++ b/packages/aux-admin/aux-ui/wise-message/src/wise-message-service.tsx @@ -0,0 +1,98 @@ +import { reactive } from 'vue'; +import {isString} from 'lodash-es' +import { WiseMessageOption, VoidFn } from './wise-message-types'; +import { instances, initInstance, deleteInstance } from './instance'; + +const defaultOptions: WiseMessageOption = { + duration: 3000, + type: 'normal', +}; + +const normalizeOptions = (params?: WiseMessageOption | string) => { + const options: WiseMessageOption = + !params || isString(params) + ? { message: params } + : params; + + const normalized = { + ...defaultOptions, + ...options, + }; + + return normalized; +}; + + +let seed = 0; +function open(options: WiseMessageOption): void { + const originOnClose: VoidFn | null = options.onClose || null; + const messageContent = options.message; + // let timer; + delete options.message; + + const props = reactive({ + ...defaultOptions, + ...options, + onClose: () => { + props.visible = false; + deleteInstance(props.id); + originOnClose?.(); + }, + }); + + seed ++; + const id = `message_${seed}`; + props.id = id; + const messageContext = initInstance(id,props, messageContent); + instances.push(messageContext); + props.visible = true; + +} + +function message(params: WiseMessageOption | string): void { + const options: WiseMessageOption = normalizeOptions(params); + open({ + ...options, + }); +} + +function success(params: WiseMessageOption | string): void { + const options: WiseMessageOption = normalizeOptions(params); + open({ + ...options, + type:'success' + }); +} + +function error(params: WiseMessageOption | string): void { + const options: WiseMessageOption = normalizeOptions(params); + open({ + ...options, + type:'error' + }); +} + +function warning(params: WiseMessageOption | string): void { + const options: WiseMessageOption = normalizeOptions(params); + open({ + ...options, + type:'warning' + }); +} + +function info(params: WiseMessageOption | string): void { + const options: WiseMessageOption = normalizeOptions(params); + open({ + ...options, + type:'info' + }); +} + +const Message = Object.assign(message , { + success, + error, + warning, + info, +}); + +export default Message; diff --git a/packages/aux-admin/aux-ui/wise-message/src/wise-message-types.ts b/packages/aux-admin/aux-ui/wise-message/src/wise-message-types.ts index c389dd5..bd846d1 100644 --- a/packages/aux-admin/aux-ui/wise-message/src/wise-message-types.ts +++ b/packages/aux-admin/aux-ui/wise-message/src/wise-message-types.ts @@ -1,10 +1,56 @@ import type { PropType, ExtractPropTypes } from 'vue'; - +export type MessageType = 'normal' | 'success' | 'error' | 'warning' | 'info'; export const wiseMessageProps = { - // data: { - // type: type, - // default: defaultValue - // }, + id: { + type: String, + default: '', + }, + // 是否显示 + visible: { + type: Boolean, + default: false, + }, + // 消息内容 + message: { + type: String, + default: '', + }, + // 提示类型 + type: { + type: String as PropType, + default: 'normal', + }, + // 是否展示边框 + bordered: { + type: Boolean, + default: true, + }, + // 是否展示阴影 + shadow: { + type: Boolean, + default: true, + }, + // 延迟时间 + duration: { + type: Number, + default: 3000, + }, + // 展示可关闭按钮 + showClose: { + type: Boolean, + default: false, + }, + // 关闭回调 + onClose: { + type: Function as PropType<() => void>, + }, } as const; export type WiseMessageProps = ExtractPropTypes; + +export type EmitEventFn = (event: 'close' | 'destroy', result?: unknown) => void; + + +export type WiseMessageOption = Partial & { message?: string }; + +export type VoidFn = () => void; \ No newline at end of file diff --git a/packages/aux-admin/aux-ui/wise-message/src/wise-message.scss b/packages/aux-admin/aux-ui/wise-message/src/wise-message.scss index c6dad16..a1101e9 100644 --- a/packages/aux-admin/aux-ui/wise-message/src/wise-message.scss +++ b/packages/aux-admin/aux-ui/wise-message/src/wise-message.scss @@ -1,4 +1,134 @@ // 引入主题变量 @import '../../styles/global.scss'; + .#{$globa-prefix}-wise-message { + + + --aux-message-info-bg-color: #f4f4f5; + --aux-message-success-bg-color: #f0f9eb; + --aux-message-danger-bg-color: #fef0f0; + --aux-message-warning-bg-color: #fdf6ec; + position: fixed; + z-index: 2001; + padding: 10px 15px; + border-radius: 15px; + left: 50%; + transform: translateX(-50%); + top: 80px; + display: flex; + align-items: center; + border-width: 1px; + border-style: solid; + // border-color: $devui-line; + box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d; + // background-color: $devui-base-bg; + transition: top 0.5s ease; + + &--success { + background-color: var(--aux-message-success-bg-color); + border-color: var(--success); + } + + &--info { + background-color: var(--aux-message-info-bg-color); + border-color: var(--info); + } + + &--warning { + background-color: var(--aux-message-warning-bg-color); + border-color:var(--warning); + } + + &--error { + background-color: var(--aux-message-danger-bg-color); + border-color: var(--danger); + } + } + +.#{$globa-prefix}-wise-message__close { + margin-left: auto; + padding-left: 10px; + line-height: 0; + cursor: pointer; +} + +// 图标样式 +.#{$globa-prefix}-wise-message__image { + --aux-message-icon-info-color: var(--info); + --aux-message-icon-success-color: var(--success); + --aux-message-icon-danger-color: var(--danger); + --aux-message-icon-warning-color: var(--warning); + margin-top: 1px; + display: inline-block; + // width: $devui-font-size-icon; + // min-width: $devui-font-size-icon; + // min-height: $devui-font-size-icon; + // height: $devui-font-size-icon; + padding: 0; + line-height: 1; + margin-right: 10px; + + &--success { + color: var(--aux-message-icon-success-color); + } + + &--info { + color: var(--aux-message-icon-info-color); + } + + &--warning { + color: var(--aux-message-icon-warning-color); + } + + &--error { + color: var( --aux-message-icon-danger-color); + } +} + +// 消息文本内容 +.#{$globa-prefix}-wise-message__content { + --aux-message-icon-info-color: var(--info); + --aux-message-icon-success-color: var(--success); + --aux-message-icon-danger-color: var(--danger); + --aux-message-icon-warning-color: var(--warning); + // font-size: $devui-font-size-message; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + + &--success { + color: var(--aux-message-icon-success-color); + } + + &--info { + color: var(--aux-message-icon-info-color); + } + + &--warning { + color: var(--aux-message-icon-warning-color); + } + + &--error { + color: var( --aux-message-icon-danger-color); + } +} + + + +.message-fade { + + &-enter-active, + &-leave-active { + transform: translate(-50%, 0); + transition: all 0.5s ease; + } + + &-enter-from, + &-leave-to { + opacity: 0; + transform: translate(-50%, -200%); + } +} \ No newline at end of file diff --git a/packages/aux-admin/aux-ui/wise-message/src/wise-message.tsx b/packages/aux-admin/aux-ui/wise-message/src/wise-message.tsx index decb6aa..3ca48d4 100644 --- a/packages/aux-admin/aux-ui/wise-message/src/wise-message.tsx +++ b/packages/aux-admin/aux-ui/wise-message/src/wise-message.tsx @@ -1,20 +1,160 @@ -import { defineComponent, toRefs } from 'vue'; -import type { SetupContext } from 'vue'; +import { defineComponent, toRefs, Transition, ref, watch, computed } from 'vue'; +import type { StyleValue } from 'vue'; import { wiseMessageProps, WiseMessageProps } from './wise-message-types'; +import { useNamespace } from '../../shared/hooks/use-namespace' +import { SuccessIcon, ErrorIcon, WarningIcon, InfoIcon } from './components' +import Close from './components/close-icon' +import { getLastOffset } from './instance'; import './wise-message.scss'; export default defineComponent({ name: 'AuxWiseMessage', props: wiseMessageProps, - emits: [], - setup(props: WiseMessageProps, ctx: SetupContext) { + emits: ['destroy'], + setup(props: WiseMessageProps, ctx) { + + const { emit, slots } = ctx // 直接解构 props 会导致响应式失效,需要使用 toRefs 进行包裹 - // const { data } = toRefs(props); + const { visible, message, type, bordered, shadow, showClose } = toRefs(props); // console.log(data.value); + const ns = useNamespace('wise-message') + + + let timer: NodeJS.Timeout | null = null; + let timestamp: number; + + + // 卸载 + const handleDestroy = () => { + emit('destroy'); + }; + + + // 关闭message + const close = () => { + timer && clearTimeout(timer); + timer = null; + props.onClose?.(); + }; + + // 鼠标移入后结束定时器 + const interrupt = () => { + if (timer && props.duration) { + clearTimeout(timer); + timer = null; + } + }; + + // 鼠标移出后重新计算时间 如果超时则直接移除message + const removeReset = () => { + if (props.visible && props.duration) { + const remainTime = props.duration - (Date.now() - timestamp); + timer = setTimeout(close, remainTime); + } + }; + + // 监听 visible 变化 + watch( + () => props.visible, + (val) => { + if (val) { + // 记录当前执行值 + timestamp = Date.now(); + if (props.duration) { + timer = setTimeout(close, props.duration); + } + } + } + ); + + const classes = computed(() => ({ + [ns.b()]: true, + [ns.m(type.value)]: true, + })); + + // 偏移量 + const lastOffset = computed(() => getLastOffset(props.id)); + const styles = computed(() => { + const messageStyles: StyleValue = {}; + if (!bordered.value) { + messageStyles['border'] = 'none'; + } + if (!shadow.value) { + messageStyles['box-shadow'] = 'none'; + } + return { ...messageStyles, top: `${lastOffset.value}px`, }; + }); + + + + const renderIcon = computed(() => { + const iconClasses = computed(() => ({ + [ns.e('image')]: true, + [ns.em('image', type.value)]: true, + })); + return ( + !(!type.value || type.value === 'normal') + && + + { + type.value && + ( + (type.value === 'success' && ) || + (type.value === 'info' && ) || + (type.value === 'warning' && ) || + (type.value === 'error' && ) + ) + } + + ); + }); + const renderText = computed(() => { + const textClasses = computed(() => ({ + [ns.e('content')]: true, + [ns.em('content', type.value)]: true, + })); + return ( + + { + message.value ? message.value : slots.default?.() + } + + ); + }); + const renderClose = computed(() => { + return ( + showClose.value && + + + ); + }); + + return () => { return ( -
+ + + + + + { + visible.value && ( +
+ {renderIcon.value} + {renderText.value} + {renderClose.value} +
+ ) + } + + +
); }; } diff --git a/packages/aux-admin/docs/.vitepress/layout/sidebar.ts b/packages/aux-admin/docs/.vitepress/layout/sidebar.ts index c002d1d..98dcb4b 100644 --- a/packages/aux-admin/docs/.vitepress/layout/sidebar.ts +++ b/packages/aux-admin/docs/.vitepress/layout/sidebar.ts @@ -31,17 +31,18 @@ const sidebar = { }, { text: 'Card', link: '/components/noble/card/' - }, + }, { text: 'Swiper', link: '/components/noble/swiper/' - }, + }, { text: 'Collapse', link: '/components/noble/collapse/' }, - + ] }, + { text: 'navnav+', items: [ @@ -63,11 +64,24 @@ const sidebar = { ] }, - + ] }, + { + text: "WISE Style", + collapsible: true, + collapsed: !true, + items: [ + { + text: 'Message', link: '/components/wise/message/' + }, + + ] + + + } + - ], "/api/": [{ diff --git a/packages/aux-admin/docs/components/wise/message/demo-codes/demo-slot.vue b/packages/aux-admin/docs/components/wise/message/demo-codes/demo-slot.vue new file mode 100644 index 0000000..690ebc0 --- /dev/null +++ b/packages/aux-admin/docs/components/wise/message/demo-codes/demo-slot.vue @@ -0,0 +1,35 @@ + + + + \ No newline at end of file diff --git a/packages/aux-admin/docs/components/wise/message/demo-codes/demo.vue b/packages/aux-admin/docs/components/wise/message/demo-codes/demo.vue new file mode 100644 index 0000000..fc89048 --- /dev/null +++ b/packages/aux-admin/docs/components/wise/message/demo-codes/demo.vue @@ -0,0 +1,28 @@ + + + + \ No newline at end of file diff --git a/packages/aux-admin/docs/components/wise/message/index.md b/packages/aux-admin/docs/components/wise/message/index.md new file mode 100644 index 0000000..f841dc0 --- /dev/null +++ b/packages/aux-admin/docs/components/wise/message/index.md @@ -0,0 +1,32 @@ + +# Message 消息提示 +wise风格消息提醒 +:::tip +项目中的皆为本地使用路径,自己项目使用请根据[快速开始](/guide/quick-start/)中操作使用 +::: +## 基本用法 +nav上很炫酷的按钮 目前只有这三种颜色根据类型type去选择需要的颜色 + + + +## 带Icon按钮 +通过插槽来加入icon实现带icon的按钮 + + +## GfgButton 参数 +| 参数名 | 类型 | 默认值 | 说明 | 跳转 Demo | +| :---- | :---- | :---- | :---- | :--------- | +| type | `primary success danger` | primary | 三种标签代表三种颜色状态 | [基本用法](#基本用法) | + + +## GfgButton 插槽 + +| 插槽名 | 说明 | 跳转 Demo | +| :---- | :---- | :--------- | +| default | 任意内容 | [基本用法](#基本用法) | +| icon | 组件内图标插槽 | [基本用法](#基本用法) | + + + + +