# OA 通知公告 - 前端联调方案 ## 涉及页面 | 页面 | 路径 | 说明 | |------|------|------| | 通知公告列表 | `/bpm/oa/notice` | 新建:`src/views/bpm/oa/notice/index.vue` | | 通知公告详情 | `/bpm/oa/notice/detail` | 新建:`src/views/bpm/oa/notice/detail.vue` | ## API | 方法 | 路径 | 权限 | 说明 | |------|------|------|------| | POST | `/bpm/oa/notice/create` | `bpm:oa-notice:create` | 创建 | | PUT | `/bpm/oa/notice/update` | `bpm:oa-notice:update` | 修改 | | DELETE | `/bpm/oa/notice/delete` | `bpm:oa-notice:delete` | 删除 | | GET | `/bpm/oa/notice/page` | `bpm:oa-notice:query` | 分页列表 | | GET | `/bpm/oa/notice/get` | `bpm:oa-notice:query` | 详情(调用即标记已读) | | GET | `/bpm/oa/notice/my-unread-count` | - | 我的未读数量 | ### 请求参数 **POST `/bpm/oa/notice/create` & PUT `/bpm/oa/notice/update`:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | id | Long | 否(更新时必填) | 通知公告ID | | title | String | 是 | 标题,最长50字符 | | content | String | 是 | 内容 | | type | Integer | 是 | 类型:1=通知 2=公告 | | status | Integer | 是 | 状态:0=草稿 1=已发布 2=已撤销 | | sendScope | Integer | 是 | 发送范围:1=通知所有人 2=指定人 | | isTop | Integer | 否 | 是否置顶:0=否 1=是 | | userIds | List\ | 否(sendScope=2时必填) | 指定用户ID列表 | **GET `/bpm/oa/notice/page`:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | title | String | 否 | 标题,模糊匹配 | | type | Integer | 否 | 类型 | | status | Integer | 否 | 状态 | | sendScope | Integer | 否 | 发送范围 | | pageNo | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | **GET `/bpm/oa/notice/get`:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | id | Long | 是 | 通知公告ID | **DELETE `/bpm/oa/notice/delete`:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | id | Long | 是 | 通知公告ID | ### 响应格式 **分页列表 `GET /bpm/oa/notice/page` 响应:** ```json { "code": 0, "data": { "list": [ { "id": 1, "title": "关于放假的通知", "content": "根据国家规定...", "type": 1, "status": 1, "sendScope": 1, "isTop": 0, "publishUserId": 1, "publishTime": "2025-01-01 10:00:00", "createTime": "2025-01-01 10:00:00" } ], "total": 100 } } ``` **详情 `GET /bpm/oa/notice/get` 响应:** 与列表项相同结构,额外返回: | 字段 | 类型 | 说明 | |------|------|------| | userIds | List\ | 指定用户ID列表(仅 sendScope=2 时有值) | **我的未读数量 `GET /bpm/oa/notice/my-unread-count` 响应:** ```json { "code": 0, "data": 5 } ``` ## 字段展示规则 | 字段 | 列表 | 详情 | 说明 | |------|------|------|------| | title | ✅ | ✅ | 通知公告标题,置顶项前加 `[置顶]` 标识 | | type | ✅ | ✅ | 1=通知 2=公告,用 Tag 区分颜色 | | status | ✅ | ✅ | 0=草稿(灰色)1=已发布(绿色)2=已撤销(红色)| | sendScope | ✅ | ✅ | 1=通知所有人 2=指定人 | | isTop | ✅ | ✅ | 置顶项排在前面 | | publishUserId | - | ✅ | 发布人姓名(需关联用户表展示) | | publishTime | ✅ | ✅ | 发布时间 | | createTime | ✅ | ✅ | 创建时间 | | content | - | ✅ | 富文本内容 | | userIds | - | ✅ | 仅 sendScope=2 时展示指定人员列表 | ## 业务规则说明 | 场景 | 规则 | |------|------| | 创建时选择「通知所有人」 | 所有登录用户在列表页可见此公告 | | 创建时选择「指定人」且状态为「已发布」 | 仅创建者+被指定用户可见;系统自动给指定人发送站内信 | | 创建时状态为「草稿」 | 仅创建者本人可见,不发送通知 | | 点击详情 | 自动标记当前用户「已读」,再次打开不重复记录 | | 列表排序 | 按 isTop 降序,再按 id 降序 | | 修改公告 | 如果原来是草稿改为已发布,会触发发布时间更新和通知发送 | | 撤销公告 | 将状态改为「已撤销」后,列表仍可见但显示为撤销状态 | | 铃铛通知 | 指定人模式发布时发站内信(模板 code: `oa-notice-publish`),头部铃铛可显示未读数;通知所有人模式不逐条推送 | ## API 封装参考 新建 `src/api/bpm/oa/notice/index.ts`,参照 `src/api/bpm/oa/leave/index.ts` 模式: ```typescript import { requestClient } from '#/api/request'; export namespace OaNoticeApi { export interface NoticeVO { id: number; title: string; content: string; type: number; status: number; sendScope: number; isTop: number; publishUserId: number; publishTime: string; createTime: string; userIds?: number[]; } export interface NoticeSaveReqVO { id?: number; title: string; content: string; type: number; status: number; sendScope: number; isTop?: number; userIds?: number[]; } } const BASE = '/bpm/oa/notice'; export function getNoticePage(params: any) { return requestClient.get(`${BASE}/page`, { params }); } export function getNotice(id: number) { return requestClient.get(`${BASE}/get`, { params: { id } }); } export function createNotice(data: OaNoticeApi.NoticeSaveReqVO) { return requestClient.post(`${BASE}/create`, data); } export function updateNotice(data: OaNoticeApi.NoticeSaveReqVO) { return requestClient.put(`${BASE}/update`, data); } export function deleteNotice(id: number) { return requestClient.delete(`${BASE}/delete`, { params: { id } }); } export function getMyUnreadNoticeCount() { return requestClient.get(`${BASE}/my-unread-count`); } ``` ## 页面文件建议 | 文件 | 路径 | |------|------| | 列表页 | `src/views/bpm/oa/notice/index.vue` | | 详情页 | `src/views/bpm/oa/notice/detail.vue` | | 表单弹窗 | `src/views/bpm/oa/notice/modules/form.vue` | | 列表配置 | `src/views/bpm/oa/notice/data.ts` | ## 注意事项 - 列表页的可见数据由后端按 sendScope + 当前用户自动过滤,前端无需额外处理 - 创建/编辑表单中,「指定人」选择器仅在 sendScope=2 时显示 - 表单提交时 status 可直接选择「已发布」,此时会立即触发通知发送 - 已读状态由后端在调用 get 接口时自动标记,前端无需调用标记已读接口 - 头部铃铛的未读数如果能获取 `getUnreadNotifyMessageCount`,可以叠加 `getMyUnreadNoticeCount` 的结果展示 - 后端菜单需要配置 `component` 字段为 `bpm/oa/notice/index`,权限标识分别为 `bpm:oa-notice:create/update/delete/query` - 参考现有页面:列表页参照 `src/views/system/notice/index.vue`,表单弹窗参照 `src/views/bpm/oa/leave/create.vue`