{{ activity.description }}
+ +{{ announcement.content.substring(0, 100) }}...
+{{ announcement.content.substring(0, 80) }}...
+为了感谢各位用户的支持,我们特别推出新年特惠活动!
+ +2025年1月1日 00:00 - 2025年1月31日 23:59
+ ++ 机会难得,不要错过! ++ `, + coverImage: 'https://images.unsplash.com/photo-1607827448387-a67db1383b59?w=1200&h=600&fit=crop', + startTime: '2025-01-01T00:00:00Z', + endTime: '2025-01-31T23:59:59Z', + status: 'active', + createdAt: '2024-12-25T10:00:00Z', + updatedAt: '2024-12-26T15:30:00Z', + }, + { + id: 2, + title: 'AI功能免费体验', + description: '全新AI功能上线,限时免费体验。包括智能对话、图像生成、代码辅助等多项功能。', + content: ` +
我们很高兴地宣布,全新的AI功能已经正式上线!
+ +2025年1月1日 - 2025年2月28日
+ +在体验期间,所有功能完全免费使用!
+ `, + coverImage: 'https://images.unsplash.com/photo-1557683316-973673baf926?w=1200&h=600&fit=crop', + startTime: '2025-01-01T00:00:00Z', + endTime: '2025-02-28T23:59:59Z', + status: 'active', + createdAt: '2024-12-28T08:00:00Z', + updatedAt: '2024-12-28T08:00:00Z', + }, + { + id: 3, + title: '推荐好友得奖励', + description: '邀请好友注册使用,双方均可获得积分奖励。推荐越多,奖励越多!', + content: ` +邀请您的朋友一起体验我们的服务,双方都能获得丰厚奖励!
+ +尊敬的用户:
+ +为了给您提供更好的服务体验,我们计划于2025年1月10日 22:00 - 2025年1月11日 02:00对系统进行维护升级。
+ +维护期间,系统将暂时无法访问,给您带来不便敬请谅解。
+ +如有紧急问题,请联系客服:service@example.com
+ +感谢您的理解与支持!
+ `, + type: 'latest', + isImportant: true, + publishTime: '2025-01-05T10:00:00Z', + createdAt: '2025-01-05T09:30:00Z', + }, + { + id: 2, + title: '隐私政策更新通知', + content: ` +尊敬的用户:
+ +我们更新了隐私政策,新政策将于2025年1月15日生效。
+ +详细内容请查看完整的隐私政策。
+ +如有疑问,欢迎联系我们。
+ `, + type: 'latest', + isImportant: false, + publishTime: '2025-01-03T14:00:00Z', + createdAt: '2025-01-03T13:30:00Z', + }, + { + id: 3, + title: 'API接口升级通知', + content: ` +开发者们注意:
+ +我们的API接口将进行版本升级,新版本为v2.0。
2025年2月1日
+ +旧版本API将继续维护至2025年6月1日。
+ `, + type: 'history', + isImportant: false, + publishTime: '2024-12-28T10:00:00Z', + createdAt: '2024-12-28T09:00:00Z', + }, + { + id: 4, + title: '新年假期客服安排', + content: ` +尊敬的用户:
+ +新年假期期间(1月1日-1月3日),客服工作时间调整为:
+ +1月4日起恢复正常工作时间。
+ `, + type: 'history', + isImportant: false, + publishTime: '2024-12-25T15:00:00Z', + createdAt: '2024-12-25T14:00:00Z', + }, + { + id: 5, + title: '用户协议更新', + content: ` +我们更新了用户服务协议,主要涉及:
+ +继续使用服务即表示您同意新的用户协议。
+ `, + type: 'history', + isImportant: false, + publishTime: '2024-12-20T10:00:00Z', + createdAt: '2024-12-20T09:00:00Z', + }, +] + +// 完整的系统公告响应数据 +export const mockSystemAnnouncementData: SystemAnnouncementResponse = { + carousels: mockCarousels, + activities: mockActivities, + announcements: mockAnnouncements, +} + +/** + * 模拟API延迟 + */ +export function mockDelay(ms: number = 500): Promise{{ activityDetail.description }}
+活动详细内容HTML格式
", + "coverImage": "https://example.com/activity/cover1.jpg", + "startTime": "2025-01-01T00:00:00Z", + "endTime": "2025-01-31T23:59:59Z", + "status": "active", + "createdAt": "2025-01-01T00:00:00Z", + "updatedAt": "2025-01-02T00:00:00Z" + } + ], + "announcements": [ + { + "id": 1, + "title": "系统升级公告", + "content": "系统将于今晚进行维护升级
", + "type": "latest", + "isImportant": true, + "publishTime": "2025-01-05T10:00:00Z", + "createdAt": "2025-01-05T09:00:00Z", + "updatedAt": "2025-01-05T10:00:00Z" + } + ] + }, + "message": "获取成功" +} +``` + +### 字段说明 + +#### carousels(轮播图) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| id | number/string | 是 | 轮播图ID | +| imageUrl | string | 是 | 图片URL | +| link | string | 否 | 点击跳转链接 | +| title | string | 否 | 轮播图标题 | + +#### activities(活动) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| id | number/string | 是 | 活动ID | +| title | string | 是 | 活动标题 | +| description | string | 是 | 活动简介 | +| content | string | 是 | 活动详细内容(HTML格式) | +| coverImage | string | 否 | 封面图URL | +| startTime | string | 否 | 开始时间(ISO 8601格式) | +| endTime | string | 否 | 结束时间(ISO 8601格式) | +| status | string | 是 | 状态:active(进行中), inactive(未开始), expired(已结束) | +| createdAt | string | 是 | 创建时间(ISO 8601格式) | +| updatedAt | string | 否 | 更新时间(ISO 8601格式) | + +#### announcements(公告) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| id | number/string | 是 | 公告ID | +| title | string | 是 | 公告标题 | +| content | string | 是 | 公告内容(HTML格式) | +| type | string | 是 | 类型:latest(最新公告), history(历史公告) | +| isImportant | boolean | 否 | 是否重要公告(显示警告图标) | +| publishTime | string | 是 | 发布时间(ISO 8601格式) | +| createdAt | string | 是 | 创建时间(ISO 8601格式) | +| updatedAt | string | 否 | 更新时间(ISO 8601格式) | + +--- + +## 2. 获取活动详情 + +### 接口信息 + +- **路径**: `GET /announcement/activity/{id}` +- **描述**: 获取单个活动的详细信息 +- **权限**: 无需登录即可访问 + +### 请求参数 + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| id | path | string/number | 是 | 活动ID | + +### 响应数据结构 + +```typescript +{ + "success": true, + "data": { + "id": 1, + "title": "新年特惠活动", + "description": "参与活动即可获得丰厚奖励", + "content": "活动详细内容HTML格式...
", + "coverImage": "https://example.com/activity/cover1.jpg", + "startTime": "2025-01-01T00:00:00Z", + "endTime": "2025-01-31T23:59:59Z", + "status": "active", + "createdAt": "2025-01-01T00:00:00Z", + "updatedAt": "2025-01-02T00:00:00Z", + "views": 1234, + "participantCount": 567 + }, + "message": "获取成功" +} +``` + +### 额外字段说明 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| views | number | 否 | 浏览次数 | +| participantCount | number | 否 | 参与人数 | + +--- + +## 3. 获取公告详情 + +### 接口信息 + +- **路径**: `GET /announcement/detail/{id}` +- **描述**: 获取单个公告的详细信息 +- **权限**: 无需登录即可访问 + +### 请求参数 + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| id | path | string/number | 是 | 公告ID | + +### 响应数据结构 + +```typescript +{ + "success": true, + "data": { + "id": 1, + "title": "系统升级公告", + "content": "系统将于今晚进行维护升级,预计时间为晚上10点至次日凌晨2点...
", + "type": "latest", + "isImportant": true, + "publishTime": "2025-01-05T10:00:00Z", + "createdAt": "2025-01-05T09:00:00Z", + "updatedAt": "2025-01-05T10:00:00Z", + "views": 5678 + }, + "message": "获取成功" +} +``` + +### 额外字段说明 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| views | number | 否 | 浏览次数 | + +--- + +## 错误响应 + +所有接口在出错时应返回统一的错误格式: + +```typescript +{ + "success": false, + "data": null, + "message": "错误描述信息", + "errorCode": "ERROR_CODE" // 可选的错误码 +} +``` + +### 常见错误码 + +| 状态码 | 说明 | +|--------|------| +| 404 | 资源不存在 | +| 500 | 服务器内部错误 | + +--- + +## 注意事项 + +1. **时间格式**: 所有时间字段使用 ISO 8601 格式(如:`2025-01-05T10:00:00Z`) +2. **HTML内容**: content 字段包含HTML格式的内容,前端会进行渲染,请确保内容安全,防止XSS攻击 +3. **图片URL**: 所有图片URL应该是完整的可访问地址 +4. **状态管理**: 活动状态(active/inactive/expired)应该根据当前时间和活动时间自动判断 +5. **公告分类**: 公告的 type 字段(latest/history)可以根据发布时间自动分类,或由管理员手动指定 +6. **浏览统计**: views 字段建议在每次访问详情页时自动递增 + +--- + +## 前端状态管理 + +前端使用 Pinia 管理公告弹窗的显示状态: + +- **今日关闭**: 24小时内不再显示 +- **本周关闭**: 7天内不再显示 +- **关闭公告**: 永久不再显示(除非用户清除浏览器缓存) + +这些状态存储在浏览器的 localStorage 中,不需要后端接口支持。 diff --git a/Yi.Ai.Vue3/系统公告功能使用说明.md b/Yi.Ai.Vue3/系统公告功能使用说明.md new file mode 100644 index 00000000..0d832488 --- /dev/null +++ b/Yi.Ai.Vue3/系统公告功能使用说明.md @@ -0,0 +1,337 @@ +# 系统公告功能使用说明 + +## 功能概述 + +本次更新为项目添加了完整的系统公告弹窗功能,包括活动展示、公告通知、轮播图等。用户可以通过不同的关闭选项来控制弹窗的显示频率。 + +--- + +## 已实现的功能 + +### 1. 系统公告弹窗 + +- **自动弹出**: 用户进入应用时自动检测并显示公告弹窗 +- **手动打开**: 右上角有公告按钮(铃铛图标),随时可以点击打开公告弹窗 +- **未读提示**: 公告按钮上显示红色徽章,标识最新公告数量 +- **Tab切换**: 支持"活动"和"公告"两个Tab页面 +- **关闭选项**: 提供三种关闭方式 + - 今日关闭:24小时内不再自动弹出,但仍可通过按钮手动打开 + - 本周关闭:7天内不再自动弹出,但仍可通过按钮手动打开 + - 关闭公告:永久不再自动弹出(除非清除浏览器缓存),但仍可通过按钮手动打开 + +### 2. 活动页面 + +- **轮播图**: 顶部展示活动轮播图,支持自动播放 +- **活动列表**: 显示所有活动,包含标题、简介、状态标签 +- **状态标识**: + - 进行中:绿色标签 + - 已结束:灰色标签 +- **查看详情**: 点击可跳转到活动详情页面 + +### 3. 公告页面 + +- **最新公告**: 顶部显示最新发布的公告,带蓝色边框高亮 +- **重要标识**: 重要公告显示警告图标 +- **历史公告**: 使用时间线形式展示历史公告 +- **查看详情**: 点击可跳转到公告详情页面 + +### 4. 详情页面 + +#### 活动详情页面 +- 活动标题和状态 +- 浏览次数和参与人数 +- 活动封面图 +- 活动简介 +- 活动时间信息(开始、结束、发布、更新时间) +- 完整的活动内容(支持HTML格式) + +#### 公告详情页面 +- 公告标题和类型 +- 重要公告标识(带动画效果) +- 浏览次数 +- 发布时间 +- 完整的公告内容(支持HTML格式) +- 创建和更新时间 + +--- + +## 文件结构 + +``` +Yi.Ai.Vue3/ +├── src/ +│ ├── api/ +│ │ └── announcement/ +│ │ ├── index.ts # API接口定义 +│ │ └── types.ts # TypeScript类型定义 +│ ├── components/ +│ │ └── SystemAnnouncementDialog/ +│ │ └── index.vue # 系统公告弹窗组件 +│ ├── layouts/ +│ │ └── components/ +│ │ └── Header/ +│ │ ├── components/ +│ │ │ └── AnnouncementBtn.vue # 公告按钮组件(新增) +│ │ └── index.vue # Header组件(已更新) +│ ├── pages/ +│ │ ├── activity/ +│ │ │ └── detail.vue # 活动详情页面 +│ │ └── announcement/ +│ │ └── detail.vue # 公告详情页面 +│ ├── stores/ +│ │ └── modules/ +│ │ └── announcement.ts # 公告状态管理 +│ ├── data/ +│ │ └── mockAnnouncementData.ts # 模拟数据 +│ ├── routers/ +│ │ └── modules/ +│ │ └── staticRouter.ts # 路由配置(已更新) +│ ├── utils/ +│ │ └── request.ts # HTTP请求工具(已修复Pinia初始化问题) +│ └── App.vue # 主应用文件(已更新) +├── 系统公告API接口文档.md # API接口文档 +└── 系统公告功能使用说明.md # 本文档 +``` + +--- + +## 如何使用 + +### 开发环境测试(使用模拟数据) + +1. **导入模拟数据** + +在 `src/App.vue` 中临时替换API调用: + +```typescript +// 导入模拟数据函数 +import { getMockSystemAnnouncements } from '@/data/mockAnnouncementData' + +// 替换 getSystemAnnouncements() 为 getMockSystemAnnouncements() +onMounted(async () => { + if (announcementStore.shouldShowDialog) { + try { + // 使用模拟数据 + const res = await getMockSystemAnnouncements() + if (res.data) { + announcementStore.setAnnouncementData(res.data) + announcementStore.openDialog() + } + } + catch (error) { + console.error('获取系统公告失败:', error) + } + } +}) +``` + +2. **同样的方式更新详情页面** + +在 `src/pages/activity/detail.vue` 和 `src/pages/announcement/detail.vue` 中也可以使用模拟数据函数进行测试。 + +3. **启动开发服务器** + +```bash +npm run dev +``` + +4. **测试功能** + +- 打开浏览器访问应用 +- 应该会自动弹出系统公告弹窗 +- 测试不同的关闭选项 +- 点击"查看详情"按钮测试跳转 + +### 生产环境部署(使用真实API) + +1. **后端实现API接口** + +参考 `系统公告API接口文档.md` 实现以下三个接口: +- `GET /announcement/system` - 获取系统公告数据 +- `GET /announcement/activity/{id}` - 获取活动详情 +- `GET /announcement/detail/{id}` - 获取公告详情 + +2. **确认API调用** + +确保 `src/App.vue` 和详情页面使用的是真实的API函数(默认配置): +- `getSystemAnnouncements()` +- `getActivityDetail(id)` +- `getAnnouncementDetail(id)` + +3. **构建部署** + +```bash +npm run build +``` + +--- + +## 自定义配置 + +### 修改关闭时间 + +在 `src/stores/modules/announcement.ts` 中修改时间计算逻辑: + +```typescript +const shouldShowDialog = computed(() => { + // ... 现有代码 + + if (closeType.value === 'today') { + // 修改为其他时间,如12小时 + return elapsed > 12 * 60 * 60 * 1000 + } + + if (closeType.value === 'week') { + // 修改为其他时间,如3天 + return elapsed > 3 * 24 * 60 * 60 * 1000 + } + + // ... 现有代码 +}) +``` + +### 修改弹窗样式 + +在 `src/components/SystemAnnouncementDialog/index.vue` 中修改样式: + +- 修改弹窗宽度:`width="700px"` 改为其他值 +- 修改轮播图高度:`height="250px"` 改为其他值 +- 修改CSS样式:在 `