diff --git a/.eslintrc.js b/.eslintrc.js
index f63fef1..1c45832 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -30,6 +30,7 @@ module.exports = {
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly',
+ NodeJS: true,
},
rules: {
// @typescript-eslint
diff --git a/packages/nice2cu-ui-mobile-example/src/router/routes.ts b/packages/nice2cu-ui-mobile-example/src/router/routes.ts
index 34ba01a..4180771 100644
--- a/packages/nice2cu-ui-mobile-example/src/router/routes.ts
+++ b/packages/nice2cu-ui-mobile-example/src/router/routes.ts
@@ -188,4 +188,12 @@ export default [
title: '索引列表',
},
},
+ {
+ path: '/toast',
+ name: 'Toast',
+ component: () => import(/* webpackChunkName: "Toast" */ '@views/componentsViews/Toast.vue'),
+ meta: {
+ title: '消息提示',
+ },
+ },
];
diff --git a/packages/nice2cu-ui-mobile-example/src/views/HomeIndex.vue b/packages/nice2cu-ui-mobile-example/src/views/HomeIndex.vue
index 2120c4d..43f3a36 100644
--- a/packages/nice2cu-ui-mobile-example/src/views/HomeIndex.vue
+++ b/packages/nice2cu-ui-mobile-example/src/views/HomeIndex.vue
@@ -19,5 +19,6 @@
+
diff --git a/packages/nice2cu-ui-mobile-example/src/views/componentsViews/Toast.vue b/packages/nice2cu-ui-mobile-example/src/views/componentsViews/Toast.vue
new file mode 100644
index 0000000..d17fd39
--- /dev/null
+++ b/packages/nice2cu-ui-mobile-example/src/views/componentsViews/Toast.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+ 基本用法
+
+
+ 文字提示
+
+
+ 成功提示
+
+
+ 警告提示
+
+
+ 失败提示
+
+
+ 加载提示
+
+
+
+
+ 自定义属性
+
+
+ 自定义图标
+
+
+ 自定义内容
+
+
+
+
+
+
+
+
+
diff --git a/packages/nice2cu-ui/src/index.ts b/packages/nice2cu-ui/src/index.ts
index 0ce912a..24c1c76 100644
--- a/packages/nice2cu-ui/src/index.ts
+++ b/packages/nice2cu-ui/src/index.ts
@@ -22,3 +22,4 @@ export * from './nDivider';
export * from './nTag';
export * from './nCard';
export * from './nIndexList';
+export * from './nToast';
diff --git a/packages/nice2cu-ui/src/nLoading/LoadingProps.ts b/packages/nice2cu-ui/src/nLoading/LoadingProps.ts
index fc82134..7935c82 100644
--- a/packages/nice2cu-ui/src/nLoading/LoadingProps.ts
+++ b/packages/nice2cu-ui/src/nLoading/LoadingProps.ts
@@ -1,11 +1,3 @@
-/*
- * @Author: linMeow linjinnan1998@sina.com
- * @Date: 2022-11-26 13:35:08
- * @LastEditors: linMeow linjinnan1998@sina.com
- * @LastEditTime: 2023-07-03 17:19:45
- * @FilePath: /nice2cu/packages/nice2cu-ui/src/nLoading/LoadingProps.ts
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
- */
import { ExtractPropTypes, PropType } from 'vue';
export function typeValidator(type: string): boolean {
diff --git a/packages/nice2cu-ui/src/nToast/Toast.vue b/packages/nice2cu-ui/src/nToast/Toast.vue
new file mode 100644
index 0000000..0333c64
--- /dev/null
+++ b/packages/nice2cu-ui/src/nToast/Toast.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
+
diff --git a/packages/nice2cu-ui/src/nToast/ToastProps.ts b/packages/nice2cu-ui/src/nToast/ToastProps.ts
new file mode 100644
index 0000000..8fcdc4f
--- /dev/null
+++ b/packages/nice2cu-ui/src/nToast/ToastProps.ts
@@ -0,0 +1,62 @@
+import { ExtractPropTypes, PropType, VNode } from 'vue';
+
+const typeValidator = (position: string) => {
+ return ['default', 'success', 'warning', 'error'].includes(position);
+};
+
+export function loadingTypeValidator(type: string): boolean {
+ return ['circle', 'time', 'wave', 'point', 'rever', 'bounce', 'battery'].includes(type);
+}
+
+export const ToastProps = {
+ id: {
+ type: [String, Number],
+ default: '',
+ },
+ type: {
+ type: String as PropType<'default' | 'success' | 'warning' | 'error'>,
+ default: 'default',
+ validator: typeValidator,
+ },
+ content: {
+ type: [String, Function, Object] as PropType VNode)>,
+ defualt: '',
+ },
+ duration: {
+ type: Number,
+ default: 2000,
+ },
+ customStyle: {
+ type: Object,
+ default: {},
+ },
+ icon: {
+ type: String,
+ defalt: '',
+ },
+ iconSize: {
+ type: [String, Number],
+ default: '36px',
+ },
+ iconPrefix: {
+ type: String,
+ default: 'nice2cu-icon',
+ },
+ loading: {
+ type: Boolean,
+ default: false,
+ },
+ loadingType: {
+ type: String as PropType<'circle' | 'time' | 'wave' | 'point' | 'rever' | 'bounce' | 'battery'>,
+ default: 'circle',
+ validator: loadingTypeValidator,
+ },
+ hasMask: {
+ type: Boolean,
+ default: false,
+ },
+ clearToast: Function,
+ onClose: Function,
+};
+
+export type ToastPropsType = ExtractPropTypes;
diff --git a/packages/nice2cu-ui/src/nToast/index.ts b/packages/nice2cu-ui/src/nToast/index.ts
new file mode 100644
index 0000000..a585c8c
--- /dev/null
+++ b/packages/nice2cu-ui/src/nToast/index.ts
@@ -0,0 +1,130 @@
+import { createVNode, render, toRaw, toRefs } from 'vue';
+import _toast from './Toast.vue';
+import { withInstall } from '../../utils/withInstall';
+import { CreateComponent } from '../../utils/components';
+
+const nToast = withInstall(_toast);
+
+const defaultToastOptions = {
+ id: '',
+ type: 'default',
+ content: '',
+ icon: '',
+ iconSize: '30px',
+ iconPrefix: 'nice2cu-icon',
+ loading: false,
+ duration: 2000,
+ hasMask: false,
+ customStyle: {},
+ clearToast: null,
+ onClose: null,
+};
+let cacheOptions: any[] = [];
+let cacheComp: any[] = [];
+let idsMap: string[] = [];
+let optsMap: any[] = [];
+
+export default nToast;
+
+export { nToast };
+
+const updateToast = (options: any, comp: any) => {
+ const container = document.getElementById(`NToast-${options.id}`);
+ if (container) {
+ const currentOpt = optsMap.find((item) => item.id === options.id);
+ if (currentOpt) {
+ options = { ...defaultToastOptions, ...currentOpt, ...options };
+ } else {
+ options = { ...defaultToastOptions, ...options };
+ }
+
+ const compData = toRaw(comp.instance);
+ const state = toRefs(compData.state);
+ for (const key in state) {
+ if (Object.prototype.hasOwnProperty.call(options, key)) {
+ state[key].value = options[key];
+ }
+ }
+
+ return compData;
+ }
+};
+
+const clearToast = (id?: string) => {
+ if (id) {
+ const container = document.getElementById(`NToast-${id}`);
+ optsMap = optsMap.filter((item) => item.id !== id);
+ idsMap = idsMap.filter((item) => item !== id);
+ const cacheOptionsData = cacheOptions.filter((item) => item.id === id);
+ cacheOptions = cacheOptions.filter((item) => item.id !== id);
+ cacheComp = cacheComp.filter((item) => item.id !== id);
+ if (container) {
+ if (cacheOptionsData.length > 0 && cacheOptionsData[0].onClose) {
+ cacheOptionsData[0].onClose();
+ }
+ document.body.removeChild(container);
+ }
+ } else {
+ idsMap.forEach((item) => {
+ const container = document.getElementById(`NToast-${item}`);
+ if (container) {
+ document.body.removeChild(container);
+ }
+ });
+ cacheOptions.forEach((item) => {
+ if (item.onClose) {
+ item.onClose();
+ }
+ });
+ optsMap = [];
+ idsMap = [];
+ cacheOptions = [];
+ cacheComp = [];
+ }
+};
+
+const createdToast = (options: any) => {
+ options.clearToast = clearToast;
+
+ let _id = null;
+ if (options.id) {
+ _id = options.id;
+ if (idsMap.find((item) => item === options.id)) {
+ const compData = cacheComp.find((item) => item.id === options.id);
+ return updateToast(options, compData.comp);
+ }
+ } else {
+ _id = new Date().getTime() + '';
+ }
+
+ options = { ...defaultToastOptions, ...options };
+ options.id = _id;
+
+ idsMap.push(options.id);
+ optsMap.push(options);
+ cacheOptions.push(options);
+
+ const comp = CreateComponent(options, { wrapper: _toast, name: 'NToast' });
+
+ cacheComp.push({ id: options.id, comp });
+
+ return toRaw(comp.instance);
+};
+
+export const Toast = {
+ showToast(options: any) {
+ return createdToast(options);
+ },
+ showToastLoading(options?: any) {
+ return createdToast({ ...{ content: '加载中...', loading: true }, ...options });
+ },
+ hideToastLoading(id?: string) {
+ return clearToast(id);
+ },
+};
+
+declare module 'vue' {
+ export interface GlobalComponents {
+ nToast: typeof nToast;
+ }
+}
diff --git a/packages/nice2cu-ui/src/nToast/style/toast.less b/packages/nice2cu-ui/src/nToast/style/toast.less
new file mode 100644
index 0000000..89ee44b
--- /dev/null
+++ b/packages/nice2cu-ui/src/nToast/style/toast.less
@@ -0,0 +1,55 @@
+.n-toast {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ min-width: 100px;
+ background-color: rgba(0, 0, 0, .7);
+ color: #fff;
+ padding: 8px 12px;
+ border-radius: 5px;
+ z-index: 9999;
+ text-align: center;
+ font-size: 14px;
+ color: rgba(255, 255, 255, .87);
+ border-color: currentColor;
+
+ &__mask {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ z-index: 9998;
+ overflow: hidden;
+ user-select: none;
+ }
+
+ &-inner {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ padding: 10px 0;
+ }
+}
+
+.toast-fade-enter-active {
+ animation: toast-fade-in 0.2s;
+}
+
+.toast-fade-leave-active {
+ animation: toast-fade-in 0.2s reverse;
+}
+
+@keyframes toast-fade-in {
+ 0% {
+ transform: translate(-50%, -50%) scale(0);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translate(-50%, -50%) scale(1);
+ opacity: 1;
+ }
+}
\ No newline at end of file
diff --git a/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.ttf b/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.ttf
index 12addc6..74d9b88 100644
Binary files a/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.ttf and b/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.ttf differ
diff --git a/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff b/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff
index 8c7098a..536b3d1 100644
Binary files a/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff and b/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff differ
diff --git a/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff2 b/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff2
index a4dd794..5e6379d 100644
Binary files a/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff2 and b/packages/nice2cu-ui/theme-chalk/font/nice2cuUI-icon.woff2 differ
diff --git a/packages/nice2cu-ui/theme-chalk/mixins/font.less b/packages/nice2cu-ui/theme-chalk/mixins/font.less
index 995acbb..65c8a7c 100644
--- a/packages/nice2cu-ui/theme-chalk/mixins/font.less
+++ b/packages/nice2cu-ui/theme-chalk/mixins/font.less
@@ -13,6 +13,18 @@
-moz-osx-font-smoothing: grayscale;
}
+.n-error:before {
+ content: "\e7f9";
+}
+
+.n-success:before {
+ content: "\e7f7";
+}
+
+.n-warning:before {
+ content: "\e7f8";
+}
+
.n-sey-garbage-outline:before {
content: "\e7f5";
}
diff --git a/packages/nice2cu-ui/theme-chalk/mixins/variable.less b/packages/nice2cu-ui/theme-chalk/mixins/variable.less
index f801d65..16b43fe 100644
--- a/packages/nice2cu-ui/theme-chalk/mixins/variable.less
+++ b/packages/nice2cu-ui/theme-chalk/mixins/variable.less
@@ -51,7 +51,7 @@
--button-small-padding: 0 12px;
--button-small-height: 28px;
--button-normal-padding: 0 15px;
- --button-normal-height: 30px;
+ --button-normal-height: 34px;
--button-large-padding: 0 18px;
--button-large-height: 40px;
--button-disabled-color: var(--color-disabled);
diff --git a/packages/nice2cu-ui/utils/components.ts b/packages/nice2cu-ui/utils/components.ts
new file mode 100644
index 0000000..bc95098
--- /dev/null
+++ b/packages/nice2cu-ui/utils/components.ts
@@ -0,0 +1,46 @@
+import { createApp, Component } from 'vue';
+import { isString, isFunction } from './tools';
+
+export const CreateComponent = (options: any, component: any) => {
+ let elWrap: HTMLElement = document.body;
+ const wrapperContainer = (options.wrapper as string) || 'body';
+
+ if (wrapperContainer != 'body') {
+ if (isString(wrapperContainer)) {
+ elWrap = document.querySelector(wrapperContainer) as HTMLElement;
+ } else {
+ elWrap = options.wrapper as HTMLElement;
+ }
+ }
+
+ const div = document.createElement('div');
+ const name = component.name ? component.name + '-' : '';
+ const id = options.id || new Date().getTime();
+ div.id = name + id;
+
+ let Wrapper = {};
+
+ if (isFunction(component.wrapper)) {
+ Wrapper = component.wrapper(elWrap, div);
+ } else {
+ Wrapper = component.wrapper;
+ }
+
+ const instance: Component = createApp(Wrapper, options);
+
+ const componens = component.components;
+
+ componens &&
+ componens.forEach((comp: Component) => {
+ instance.use(comp);
+ });
+ elWrap.appendChild(div);
+
+ return {
+ instance: instance.mount(div),
+ unmount: () => {
+ instance.unmount();
+ elWrap.removeChild(div);
+ },
+ };
+};
diff --git a/packages/nice2cu-ui/utils/tools.ts b/packages/nice2cu-ui/utils/tools.ts
index 289b115..13e2d43 100644
--- a/packages/nice2cu-ui/utils/tools.ts
+++ b/packages/nice2cu-ui/utils/tools.ts
@@ -26,6 +26,8 @@ export const isPromise = (val: unknown): val is Promise => val instanceof P
export const isSameVNodeType = (node1: VNode, node2: VNode) => node1.type === node2.type && node1.key === node2.key;
+export const isFunction = (val: unknown): val is unknown => typeof val === 'function';
+
export const isElement = (node: Element) => {
const ELEMENT_NODE_TYPE = 1;
return node.tagName !== 'HTML' && node.tagName !== 'BODY' && node.nodeType === ELEMENT_NODE_TYPE;