From 02c00222d96874b92fe3524ae7a0dfcb802eadb8 Mon Sep 17 00:00:00 2001
From: gaoziman <2942894660@qq.com>
Date: Wed, 5 Nov 2025 23:52:21 +0800
Subject: [PATCH] =?UTF-8?q?feat(=E5=B7=A5=E5=85=B7=E7=B1=BB):=20=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=E6=B6=88=E6=81=AF=E6=8F=90=E7=A4=BA=E5=92=8C=E4=B8=BB?=
=?UTF-8?q?=E9=A2=98=E8=89=B2=E5=B7=A5=E5=85=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- message: 封装统一的消息提示API(支持info/success/warning/error)
- notification: 封装通知API
- modal: 封装对话框API(支持confirm/prompt)
- initThemeColor: 主题色初始化工具
- 完善TypeScript类型定义
---
src/utils/initThemeColor.ts | 22 ++
src/utils/message/README.md | 598 ++++++++++++++++++++++++++++++++++++
src/utils/message/index.ts | 520 +++++++++++++++++++++++++++++++
src/utils/message/types.ts | 108 +++++++
4 files changed, 1248 insertions(+)
create mode 100644 src/utils/initThemeColor.ts
create mode 100644 src/utils/message/README.md
create mode 100644 src/utils/message/index.ts
create mode 100644 src/utils/message/types.ts
diff --git a/src/utils/initThemeColor.ts b/src/utils/initThemeColor.ts
new file mode 100644
index 0000000..7747c45
--- /dev/null
+++ b/src/utils/initThemeColor.ts
@@ -0,0 +1,22 @@
+import { generate, getRgbStr } from '@arco-design/color';
+
+/**
+ * 初始化主题色 - 生成并注入完整的10个梯度色CSS变量
+ * @param themeColor 主题色(HEX格式,如 #006266)
+ * @param isDark 是否为暗色模式
+ */
+export function initThemeColor(themeColor: string, isDark = false) {
+ // 使用 Arco Design 的颜色生成算法生成10个梯度色
+ const colorList = generate(themeColor, {
+ list: true,
+ dark: isDark,
+ });
+
+ // 将生成的梯度色注入到 document.body 的 CSS 变量中
+ colorList.forEach((color, index) => {
+ const rgbStr = getRgbStr(color);
+ document.body.style.setProperty(`--arcoblue-${index + 1}`, rgbStr);
+ });
+}
+
+export default initThemeColor;
diff --git a/src/utils/message/README.md b/src/utils/message/README.md
new file mode 100644
index 0000000..2d7b21c
--- /dev/null
+++ b/src/utils/message/README.md
@@ -0,0 +1,598 @@
+# 消息提示工具类使用文档
+
+这是一个基于 Arco Design 封装的统一消息提示工具类,提供了 Message、Notification 和 Modal 三种类型的 API,用于在 React 应用中展示各种提示信息。
+
+## 特性
+
+✅ **统一的 API 设计** - 提供一致的调用方式,降低学习成本
+✅ **完整的 TypeScript 支持** - 提供完整的类型定义
+✅ **Promise 化** - Modal API 支持 Promise,方便异步处理
+✅ **主题自适应** - 自动适配系统主题(亮色/暗色模式)
+✅ **错误处理** - 内置完善的错误处理机制
+✅ **易于使用** - 简洁的 API 设计,开箱即用
+
+## 安装
+
+该工具类已经集成在项目中,无需额外安装。直接导入使用即可:
+
+```typescript
+import { message, notification, modal } from '@/utils/message';
+// 或者
+import coiMessage from '@/utils/message';
+```
+
+## API 文档
+
+### Message API
+
+用于显示轻量级的提示信息,默认 3 秒后自动关闭。
+
+#### 基础用法
+
+```typescript
+import { message } from '@/utils/message';
+
+// 信息提示
+message.info('这是一条信息提示');
+
+// 成功提示
+message.success('操作成功!');
+
+// 警告提示
+message.warning('请注意!');
+
+// 错误提示
+message.error('操作失败,请重试');
+```
+
+#### 自定义配置
+
+```typescript
+// 自定义显示时长
+message.success('保存成功', { duration: 5000 });
+
+// 显示关闭按钮
+message.info('这是一条可以手动关闭的消息', { closable: true });
+
+// 关闭回调
+message.success('操作成功', {
+ duration: 2000,
+ onClose: () => {
+ console.log('消息已关闭');
+ },
+});
+
+// 自定义图标
+import { IconCheckCircle } from '@arco-design/web-react/icon';
+
+message.success('自定义图标', {
+ icon: ,
+});
+```
+
+#### 手动关闭
+
+```typescript
+// 获取消息实例,手动控制关闭
+const instance = message.info('这是一条消息', { duration: 0 });
+
+// 3 秒后手动关闭
+setTimeout(() => {
+ instance.close();
+}, 3000);
+```
+
+#### 清空所有消息
+
+```typescript
+// 清空所有正在显示的消息
+message.clear();
+```
+
+#### MessageOptions 配置项
+
+| 参数 | 说明 | 类型 | 默认值 |
+| -------- | ---------------------------------- | ---------- | ------ |
+| duration | 显示时长(毫秒),0 表示不自动关闭 | number | 3000 |
+| closable | 是否显示关闭按钮 | boolean | false |
+| onClose | 关闭回调 | () => void | - |
+| icon | 自定义图标 | ReactNode | - |
+| id | 唯一标识 | string | - |
+
+---
+
+### Notification API
+
+用于显示通知提醒消息,相比 Message 可以展示更多内容,默认 4.5 秒后自动关闭。
+
+#### 基础用法
+
+```typescript
+import { notification } from '@/utils/message';
+
+// 信息通知
+notification.info({
+ title: '通知标题',
+ content: '这是通知内容',
+});
+
+// 成功通知
+notification.success({
+ title: '操作成功',
+ content: '您的数据已保存',
+});
+
+// 警告通知
+notification.warning({
+ title: '警告',
+ content: '您的账户即将到期',
+});
+
+// 错误通知
+notification.error({
+ title: '错误',
+ content: '网络连接失败,请检查您的网络设置',
+});
+```
+
+#### 自定义配置
+
+```typescript
+// 自定义位置
+notification.success({
+ title: '保存成功',
+ content: '数据已成功保存',
+ position: 'topLeft', // topLeft, topRight, bottomLeft, bottomRight
+});
+
+// 自定义显示时长
+notification.info({
+ title: '提示',
+ content: '这条通知将显示 10 秒',
+ duration: 10000,
+});
+
+// 不自动关闭
+notification.warning({
+ title: '重要提示',
+ content: '请注意查看',
+ duration: 0,
+ closable: true,
+});
+
+// 关闭回调
+notification.success({
+ title: '上传完成',
+ content: '文件已成功上传',
+ onClose: () => {
+ console.log('通知已关闭');
+ },
+});
+```
+
+#### 手动关闭
+
+```typescript
+// 获取通知实例,手动控制关闭
+const instance = notification.info({
+ title: '通知',
+ content: '这是一条通知',
+ duration: 0,
+});
+
+// 5 秒后手动关闭
+setTimeout(() => {
+ instance.close();
+}, 5000);
+```
+
+#### 清空所有通知
+
+```typescript
+// 清空所有正在显示的通知
+notification.clear();
+```
+
+#### NotificationOptions 配置项
+
+| 参数 | 说明 | 类型 | 默认值 |
+| -------- | ---------------------------------- | -------------------------------------------------------- | ---------- |
+| title | 标题 | ReactNode | - |
+| content | 内容 | ReactNode | 必填 |
+| duration | 显示时长(毫秒),0 表示不自动关闭 | number | 4500 |
+| closable | 是否显示关闭按钮 | boolean | false |
+| onClose | 关闭回调 | () => void | - |
+| icon | 自定义图标 | ReactNode | - |
+| id | 唯一标识 | string | - |
+| position | 位置 | 'topLeft' \| 'topRight' \| 'bottomLeft' \| 'bottomRight' | 'topRight' |
+
+---
+
+### Modal API
+
+用于显示对话框,支持确认、提示、输入等多种场景。所有方法都返回 Promise。
+
+#### 确认对话框
+
+```typescript
+import { modal } from '@/utils/message';
+
+// 基础确认
+const result = await modal.confirm({
+ title: '确认删除',
+ content: '确定要删除这条记录吗?此操作不可恢复。',
+});
+
+if (result) {
+ console.log('用户点击了确定');
+} else {
+ console.log('用户点击了取消');
+}
+
+// 自定义按钮文本
+modal.confirm({
+ title: '确认提交',
+ content: '确定要提交表单吗?',
+ okText: '提交',
+ cancelText: '再想想',
+ onOk: async () => {
+ // 异步操作
+ await submitForm();
+ message.success('提交成功');
+ },
+ onCancel: () => {
+ message.info('已取消提交');
+ },
+});
+```
+
+#### 信息提示对话框
+
+```typescript
+// 信息提示
+modal.info({
+ title: '提示',
+ content: '这是一条信息提示',
+});
+
+// 成功提示
+modal.success({
+ title: '操作成功',
+ content: '您的操作已成功完成!',
+});
+
+// 警告提示
+modal.warning({
+ title: '警告',
+ content: '您的账户即将到期,请及时续费',
+});
+
+// 错误提示
+modal.error({
+ title: '错误',
+ content: '操作失败,请稍后重试',
+});
+
+// 简单提示(alert 是 warning 的别名)
+modal.alert({
+ title: '提示',
+ content: '请注意查看',
+});
+```
+
+#### 输入对话框
+
+```typescript
+// 基础输入
+const value = await modal.prompt({
+ title: '请输入名称',
+ placeholder: '请输入您的名称',
+ defaultValue: '',
+});
+
+if (value !== null) {
+ console.log('用户输入:', value);
+} else {
+ console.log('用户取消了输入');
+}
+
+// 必填校验
+const username = await modal.prompt({
+ title: '修改用户名',
+ placeholder: '请输入新的用户名',
+ required: true,
+ defaultValue: 'admin',
+});
+
+// 自定义校验
+const email = await modal.prompt({
+ title: '请输入邮箱',
+ placeholder: '请输入您的邮箱地址',
+ required: true,
+ validator: (value) => {
+ const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!emailReg.test(value)) {
+ return '请输入正确的邮箱格式';
+ }
+ return true;
+ },
+});
+
+// 密码输入
+const password = await modal.prompt({
+ title: '请输入密码',
+ inputType: 'password',
+ placeholder: '请输入密码',
+ required: true,
+});
+
+// 多行文本输入
+const description = await modal.prompt({
+ title: '请输入描述',
+ inputType: 'textarea',
+ placeholder: '请输入描述信息',
+ content: '描述信息将显示在产品详情页',
+});
+
+// 完整示例:带异步处理和错误处理
+const name = await modal.prompt({
+ title: '修改项目名称',
+ content: '请输入新的项目名称',
+ placeholder: '项目名称',
+ defaultValue: '我的项目',
+ required: true,
+ validator: (value) => {
+ if (value.length < 2) {
+ return '项目名称至少 2 个字符';
+ }
+ if (value.length > 50) {
+ return '项目名称不能超过 50 个字符';
+ }
+ return true;
+ },
+ onOk: async () => {
+ // 可以在这里执行异步操作
+ await updateProjectName(name);
+ },
+});
+```
+
+#### 自定义配置
+
+```typescript
+// 自定义宽度
+modal.confirm({
+ title: '确认操作',
+ content: '这是一个宽度为 600px 的对话框',
+ width: 600,
+});
+
+// 自定义按钮属性
+modal.confirm({
+ title: '危险操作',
+ content: '确定要执行此危险操作吗?',
+ okButtonProps: {
+ status: 'danger',
+ },
+ cancelButtonProps: {
+ type: 'outline',
+ },
+});
+
+// 点击遮罩层不关闭
+modal.confirm({
+ title: '重要确认',
+ content: '请认真阅读并确认',
+ maskClosable: false,
+});
+
+// 隐藏取消按钮
+modal.confirm({
+ title: '温馨提示',
+ content: '系统将在 5 分钟后进行维护',
+ showCancel: false,
+});
+```
+
+#### 销毁所有对话框
+
+```typescript
+// 销毁所有正在显示的对话框
+modal.destroyAll();
+```
+
+#### ModalOptions 配置项
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ----------------- | ------------------ | --------------------------- | ------ |
+| title | 标题 | ReactNode | - |
+| content | 内容 | ReactNode | 必填 |
+| okText | 确定按钮文本 | string | '确定' |
+| cancelText | 取消按钮文本 | string | '取消' |
+| okButtonProps | 确定按钮属性 | any | - |
+| cancelButtonProps | 取消按钮属性 | any | - |
+| onOk | 点击确定的回调 | () => void \| Promise | - |
+| onCancel | 点击取消的回调 | () => void | - |
+| width | 宽度 | number \| string | - |
+| showCancel | 是否显示取消按钮 | boolean | true |
+| icon | 自定义图标 | ReactNode | - |
+| maskClosable | 遮罩是否可点击关闭 | boolean | true |
+
+#### PromptOptions 配置项
+
+在 ModalOptions 基础上增加以下配置:
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ------------ | ---------------- | ------------------------------------ | -------- |
+| content | 提示内容(可选) | ReactNode | - |
+| placeholder | 输入框占位符 | string | '请输入' |
+| defaultValue | 默认值 | string | '' |
+| inputType | 输入框类型 | 'text' \| 'password' \| 'textarea' | 'text' |
+| validator | 验证规则 | (value: string) => boolean \| string | - |
+| required | 是否必填 | boolean | false |
+
+---
+
+## 完整示例
+
+### 示例 1:删除确认
+
+```typescript
+import { modal, message } from '@/utils/message';
+
+async function handleDelete(id: string) {
+ const confirmed = await modal.confirm({
+ title: '确认删除',
+ content: '确定要删除这条记录吗?此操作不可恢复。',
+ okText: '确定删除',
+ cancelText: '取消',
+ okButtonProps: {
+ status: 'danger',
+ },
+ });
+
+ if (confirmed) {
+ try {
+ await deleteRecord(id);
+ message.success('删除成功');
+ } catch (error) {
+ message.error('删除失败,请重试');
+ }
+ }
+}
+```
+
+### 示例 2:表单保存提示
+
+```typescript
+import { message, notification } from '@/utils/message';
+
+async function handleSubmit(formData: any) {
+ // 显示加载消息
+ const loadingMsg = message.info('正在保存...', { duration: 0 });
+
+ try {
+ await saveForm(formData);
+
+ // 关闭加载消息
+ loadingMsg.close();
+
+ // 显示成功通知
+ notification.success({
+ title: '保存成功',
+ content: '您的数据已成功保存',
+ duration: 3000,
+ });
+ } catch (error) {
+ // 关闭加载消息
+ loadingMsg.close();
+
+ // 显示错误消息
+ message.error('保存失败,请重试');
+ }
+}
+```
+
+### 示例 3:输入对话框
+
+```typescript
+import { modal, message } from '@/utils/message';
+
+async function handleRename(id: string, currentName: string) {
+ const newName = await modal.prompt({
+ title: '重命名',
+ content: '请输入新的名称',
+ placeholder: '请输入名称',
+ defaultValue: currentName,
+ required: true,
+ validator: (value) => {
+ if (value.length < 2) {
+ return '名称至少 2 个字符';
+ }
+ if (value.length > 20) {
+ return '名称不能超过 20 个字符';
+ }
+ return true;
+ },
+ });
+
+ if (newName !== null && newName !== currentName) {
+ try {
+ await updateName(id, newName);
+ message.success('重命名成功');
+ } catch (error) {
+ message.error('重命名失败');
+ }
+ }
+}
+```
+
+### 示例 4:批量操作确认
+
+```typescript
+import { modal, message } from '@/utils/message';
+
+async function handleBatchDelete(selectedIds: string[]) {
+ if (selectedIds.length === 0) {
+ message.warning('请先选择要删除的项目');
+ return;
+ }
+
+ const confirmed = await modal.confirm({
+ title: '批量删除确认',
+ content: `确定要删除选中的 ${selectedIds.length} 项记录吗?此操作不可恢复。`,
+ okText: `删除 ${selectedIds.length} 项`,
+ cancelText: '取消',
+ okButtonProps: {
+ status: 'danger',
+ },
+ });
+
+ if (confirmed) {
+ const loadingMsg = message.info('正在删除...', { duration: 0 });
+
+ try {
+ await batchDelete(selectedIds);
+ loadingMsg.close();
+ message.success(`成功删除 ${selectedIds.length} 项记录`);
+ } catch (error) {
+ loadingMsg.close();
+ message.error('删除失败,请重试');
+ }
+ }
+}
+```
+
+## 注意事项
+
+1. **Message 和 Notification 的区别**
+
+ - Message:轻量级提示,适合简短的反馈信息
+ - Notification:通知提醒,适合需要标题和详细内容的场景
+
+2. **Modal Promise 返回值**
+
+ - `confirm`、`warning`、`alert` 返回 `boolean`,true 表示确定,false 表示取消
+ - `info`、`success`、`error` 返回 `boolean`,通常只返回 true(点击确定)
+ - `prompt` 返回 `string | null`,string 表示用户输入,null 表示取消
+
+3. **异步操作处理**
+
+ - `onOk` 回调支持 `Promise`,会自动处理 loading 状态
+ - 如果 `onOk` 抛出异常,对话框不会关闭
+
+4. **样式和主题**
+
+ - 组件会自动适配系统主题(亮色/暗色模式)
+ - 使用 CSS 变量实现主题色适配
+
+5. **性能优化**
+ - 避免在循环中频繁调用 Message API
+ - 使用 `message.clear()` 可以清空所有正在显示的消息
+
+## 相关链接
+
+- [Arco Design 官方文档](https://arco.design/)
+- [Message 组件文档](https://arco.design/react/components/message)
+- [Notification 组件文档](https://arco.design/react/components/notification)
+- [Modal 组件文档](https://arco.design/react/components/modal)
diff --git a/src/utils/message/index.ts b/src/utils/message/index.ts
new file mode 100644
index 0000000..9e14d51
--- /dev/null
+++ b/src/utils/message/index.ts
@@ -0,0 +1,520 @@
+import {
+ Message as ArcoMessage,
+ Notification as ArcoNotification,
+ Modal as ArcoModal,
+} from '@arco-design/web-react';
+import type {
+ MessageType,
+ MessageOptions,
+ MessageInstance,
+ NotificationOptions,
+ NotificationInstance,
+ ModalOptions,
+ PromptOptions,
+} from './types';
+
+/**
+ * Message API 实现
+ */
+class MessageAPI {
+ private defaultDuration = 3000;
+
+ /**
+ * 显示消息的通用方法
+ */
+ private show(
+ type: MessageType,
+ content: string,
+ options?: MessageOptions
+ ): MessageInstance {
+ const { duration = this.defaultDuration, ...restOptions } = options || {};
+
+ const closeFunc = ArcoMessage[type]({
+ content,
+ duration,
+ ...restOptions,
+ });
+
+ return {
+ close: () => {
+ if (typeof closeFunc === 'function') {
+ closeFunc();
+ }
+ },
+ };
+ }
+
+ /**
+ * 显示信息提示
+ */
+ info(content: string, options?: MessageOptions): MessageInstance {
+ return this.show('info', content, options);
+ }
+
+ /**
+ * 显示成功提示
+ */
+ success(content: string, options?: MessageOptions): MessageInstance {
+ return this.show('success', content, options);
+ }
+
+ /**
+ * 显示警告提示
+ */
+ warning(content: string, options?: MessageOptions): MessageInstance {
+ return this.show('warning', content, options);
+ }
+
+ /**
+ * 显示错误提示
+ */
+ error(content: string, options?: MessageOptions): MessageInstance {
+ return this.show('error', content, options);
+ }
+
+ /**
+ * 清空所有消息
+ */
+ clear(): void {
+ ArcoMessage.clear();
+ }
+}
+
+/**
+ * Notification API 实现
+ */
+class NotificationAPI {
+ private defaultDuration = 4500;
+ private defaultPosition: NotificationOptions['position'] = 'topRight';
+
+ /**
+ * 显示通知的通用方法
+ */
+ private show(
+ type: MessageType,
+ options: NotificationOptions
+ ): NotificationInstance {
+ const {
+ duration = this.defaultDuration,
+ position = this.defaultPosition,
+ ...restOptions
+ } = options;
+
+ const closeFunc = ArcoNotification[type]({
+ duration,
+ position,
+ ...restOptions,
+ });
+
+ return {
+ close: () => {
+ if (typeof closeFunc === 'function') {
+ closeFunc();
+ }
+ },
+ };
+ }
+
+ /**
+ * 显示信息通知
+ */
+ info(options: NotificationOptions): NotificationInstance {
+ return this.show('info', options);
+ }
+
+ /**
+ * 显示成功通知
+ */
+ success(options: NotificationOptions): NotificationInstance {
+ return this.show('success', options);
+ }
+
+ /**
+ * 显示警告通知
+ */
+ warning(options: NotificationOptions): NotificationInstance {
+ return this.show('warning', options);
+ }
+
+ /**
+ * 显示错误通知
+ */
+ error(options: NotificationOptions): NotificationInstance {
+ return this.show('error', options);
+ }
+
+ /**
+ * 清空所有通知
+ */
+ clear(): void {
+ ArcoNotification.clear();
+ }
+}
+
+/**
+ * Modal API 实现
+ */
+class ModalAPI {
+ /**
+ * 确认对话框
+ */
+ confirm(options: ModalOptions): Promise {
+ return new Promise((resolve) => {
+ const {
+ title = '确认',
+ content,
+ okText = '确定',
+ cancelText = '取消',
+ showCancel = true,
+ onOk,
+ onCancel,
+ ...restOptions
+ } = options;
+
+ ArcoModal.confirm({
+ title,
+ content,
+ okText,
+ cancelText,
+ ...restOptions,
+ onOk: async () => {
+ try {
+ if (onOk) {
+ await onOk();
+ }
+ resolve(true);
+ } catch (error) {
+ console.error('Modal confirm onOk error:', error);
+ resolve(false);
+ }
+ },
+ onCancel: () => {
+ onCancel?.();
+ resolve(false);
+ },
+ });
+ });
+ }
+
+ /**
+ * 信息提示对话框
+ */
+ info(options: ModalOptions): Promise {
+ return new Promise((resolve) => {
+ const {
+ title = '提示',
+ content,
+ okText = '确定',
+ onOk,
+ ...restOptions
+ } = options;
+
+ ArcoModal.info({
+ title,
+ content,
+ okText,
+ ...restOptions,
+ onOk: async () => {
+ try {
+ if (onOk) {
+ await onOk();
+ }
+ resolve(true);
+ } catch (error) {
+ console.error('Modal info onOk error:', error);
+ resolve(false);
+ }
+ },
+ });
+ });
+ }
+
+ /**
+ * 成功提示对话框
+ */
+ success(options: ModalOptions): Promise {
+ return new Promise((resolve) => {
+ const {
+ title = '成功',
+ content,
+ okText = '确定',
+ onOk,
+ ...restOptions
+ } = options;
+
+ ArcoModal.success({
+ title,
+ content,
+ okText,
+ ...restOptions,
+ onOk: async () => {
+ try {
+ if (onOk) {
+ await onOk();
+ }
+ resolve(true);
+ } catch (error) {
+ console.error('Modal success onOk error:', error);
+ resolve(false);
+ }
+ },
+ });
+ });
+ }
+
+ /**
+ * 警告提示对话框
+ */
+ warning(options: ModalOptions): Promise {
+ return new Promise((resolve) => {
+ const {
+ title = '警告',
+ content,
+ okText = '确定',
+ cancelText = '取消',
+ showCancel = true,
+ onOk,
+ onCancel,
+ ...restOptions
+ } = options;
+
+ ArcoModal.warning({
+ title,
+ content,
+ okText,
+ cancelText,
+ ...restOptions,
+ onOk: async () => {
+ try {
+ if (onOk) {
+ await onOk();
+ }
+ resolve(true);
+ } catch (error) {
+ console.error('Modal warning onOk error:', error);
+ resolve(false);
+ }
+ },
+ onCancel: () => {
+ onCancel?.();
+ resolve(false);
+ },
+ });
+ });
+ }
+
+ /**
+ * 错误提示对话框
+ */
+ error(options: ModalOptions): Promise {
+ return new Promise((resolve) => {
+ const {
+ title = '错误',
+ content,
+ okText = '确定',
+ onOk,
+ ...restOptions
+ } = options;
+
+ ArcoModal.error({
+ title,
+ content,
+ okText,
+ ...restOptions,
+ onOk: async () => {
+ try {
+ if (onOk) {
+ await onOk();
+ }
+ resolve(true);
+ } catch (error) {
+ console.error('Modal error onOk error:', error);
+ resolve(false);
+ }
+ },
+ });
+ });
+ }
+
+ /**
+ * 警告对话框(别名)
+ */
+ alert(options: ModalOptions): Promise {
+ return this.warning(options);
+ }
+
+ /**
+ * 输入提示对话框
+ */
+ prompt(options: PromptOptions): Promise {
+ return new Promise((resolve) => {
+ const {
+ title = '输入',
+ content,
+ okText = '确定',
+ cancelText = '取消',
+ placeholder = '请输入',
+ defaultValue = '',
+ inputType = 'text',
+ validator,
+ required = false,
+ onOk,
+ onCancel,
+ ...restOptions
+ } = options;
+
+ let inputValue = defaultValue;
+ let errorMessage = '';
+
+ const validateInput = (): boolean => {
+ // 必填校验
+ if (required && !inputValue.trim()) {
+ errorMessage = '此项为必填项';
+ return false;
+ }
+
+ // 自定义校验
+ if (validator) {
+ const result = validator(inputValue);
+ if (result === false) {
+ errorMessage = '输入格式不正确';
+ return false;
+ }
+ if (typeof result === 'string') {
+ errorMessage = result;
+ return false;
+ }
+ }
+
+ errorMessage = '';
+ return true;
+ };
+
+ // 创建输入框内容
+ const renderContent = () => {
+ const container = document.createElement('div');
+
+ // 如果有提示内容,先显示提示内容
+ if (content) {
+ const contentDiv = document.createElement('div');
+ contentDiv.style.marginBottom = '12px';
+ if (typeof content === 'string') {
+ contentDiv.textContent = content;
+ }
+ container.appendChild(contentDiv);
+ }
+
+ // 创建输入框
+ const input = document.createElement(
+ inputType === 'textarea' ? 'textarea' : 'input'
+ );
+ input.className = 'arco-input';
+ input.placeholder = placeholder;
+ input.value = defaultValue;
+ input.style.width = '100%';
+
+ if (inputType === 'password') {
+ (input as HTMLInputElement).type = 'password';
+ }
+
+ if (inputType === 'textarea') {
+ (input as HTMLTextAreaElement).rows = 4;
+ input.className = 'arco-textarea';
+ }
+
+ input.addEventListener('input', (e) => {
+ inputValue = (e.target as HTMLInputElement | HTMLTextAreaElement)
+ .value;
+ // 清除错误信息
+ if (errorDiv.textContent) {
+ errorDiv.textContent = '';
+ errorDiv.style.display = 'none';
+ }
+ });
+
+ container.appendChild(input);
+
+ // 创建错误提示
+ const errorDiv = document.createElement('div');
+ errorDiv.style.color = '#f53f3f';
+ errorDiv.style.fontSize = '12px';
+ errorDiv.style.marginTop = '8px';
+ errorDiv.style.display = 'none';
+ container.appendChild(errorDiv);
+
+ // 自动聚焦
+ setTimeout(() => {
+ input.focus();
+ }, 100);
+
+ return { container, input, errorDiv };
+ };
+
+ const { container, errorDiv } = renderContent();
+
+ ArcoModal.confirm({
+ title,
+ content: container as any,
+ okText,
+ cancelText,
+ ...restOptions,
+ onOk: async () => {
+ if (!validateInput()) {
+ errorDiv.textContent = errorMessage;
+ errorDiv.style.display = 'block';
+ throw new Error(errorMessage); // 阻止对话框关闭
+ }
+
+ try {
+ if (onOk) {
+ await onOk();
+ }
+ resolve(inputValue);
+ } catch (error) {
+ console.error('Modal prompt onOk error:', error);
+ errorDiv.textContent =
+ error instanceof Error ? error.message : '操作失败';
+ errorDiv.style.display = 'block';
+ throw error; // 阻止对话框关闭
+ }
+ },
+ onCancel: () => {
+ onCancel?.();
+ resolve(null);
+ },
+ });
+ });
+ }
+
+ /**
+ * 销毁所有对话框
+ */
+ destroyAll(): void {
+ ArcoModal.destroyAll();
+ }
+}
+
+// 创建单例实例
+export const message = new MessageAPI();
+export const notification = new NotificationAPI();
+export const modal = new ModalAPI();
+
+// 默认导出一个包含所有 API 的对象
+const coiMessage = {
+ message,
+ notification,
+ modal,
+};
+
+export default coiMessage;
+
+// 导出类型
+export type {
+ MessageType,
+ MessageOptions,
+ MessageInstance,
+ NotificationOptions,
+ NotificationInstance,
+ ModalOptions,
+ PromptOptions,
+} from './types';
diff --git a/src/utils/message/types.ts b/src/utils/message/types.ts
new file mode 100644
index 0000000..c678c2b
--- /dev/null
+++ b/src/utils/message/types.ts
@@ -0,0 +1,108 @@
+import { ReactNode } from 'react';
+
+/**
+ * 消息类型
+ */
+export type MessageType = 'info' | 'success' | 'warning' | 'error';
+
+/**
+ * Message 配置选项
+ */
+export interface MessageOptions {
+ /** 显示时长(毫秒),0 表示不自动关闭 */
+ duration?: number;
+ /** 是否显示关闭按钮 */
+ closable?: boolean;
+ /** 关闭回调 */
+ onClose?: () => void;
+ /** 自定义图标 */
+ icon?: ReactNode;
+ /** 唯一标识 */
+ id?: string;
+}
+
+/**
+ * Notification 配置选项
+ */
+export interface NotificationOptions {
+ /** 标题 */
+ title?: ReactNode;
+ /** 内容 */
+ content: ReactNode;
+ /** 显示时长(毫秒),0 表示不自动关闭 */
+ duration?: number;
+ /** 是否显示关闭按钮 */
+ closable?: boolean;
+ /** 关闭回调 */
+ onClose?: () => void;
+ /** 自定义图标 */
+ icon?: ReactNode;
+ /** 唯一标识 */
+ id?: string;
+ /** 位置 */
+ position?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
+}
+
+/**
+ * Modal 配置选项
+ */
+export interface ModalOptions {
+ /** 标题 */
+ title?: ReactNode;
+ /** 内容 */
+ content: ReactNode;
+ /** 确定按钮文本 */
+ okText?: string;
+ /** 取消按钮文本 */
+ cancelText?: string;
+ /** 确定按钮类型 */
+ okButtonProps?: any;
+ /** 取消按钮类型 */
+ cancelButtonProps?: any;
+ /** 点击确定的回调 */
+ onOk?: () => void | Promise;
+ /** 点击取消的回调 */
+ onCancel?: () => void;
+ /** 宽度 */
+ width?: number | string;
+ /** 是否显示取消按钮 */
+ showCancel?: boolean;
+ /** 自定义图标 */
+ icon?: ReactNode;
+ /** 遮罩是否可点击关闭 */
+ maskClosable?: boolean;
+}
+
+/**
+ * Prompt Modal 配置选项
+ */
+export interface PromptOptions extends Omit {
+ /** 提示内容 */
+ content?: ReactNode;
+ /** 输入框占位符 */
+ placeholder?: string;
+ /** 默认值 */
+ defaultValue?: string;
+ /** 输入框类型 */
+ inputType?: 'text' | 'password' | 'textarea';
+ /** 验证规则 */
+ validator?: (value: string) => boolean | string;
+ /** 是否必填 */
+ required?: boolean;
+}
+
+/**
+ * Message 实例返回类型
+ */
+export interface MessageInstance {
+ /** 关闭当前消息 */
+ close: () => void;
+}
+
+/**
+ * Notification 实例返回类型
+ */
+export interface NotificationInstance {
+ /** 关闭当前通知 */
+ close: () => void;
+}