# 小程序端 OA 功能实现计划 ## Context Web 管理端(`backend/`)已具备完整的 OA 四大功能(通知公告、文档库、薪酬工资单、员工档案), 但移动端(`uniapp/`)目前只有统一 webview 兜底,OA 子系统里除「日程提醒/记事本」外均无原生页面。 本次目标:参照 `backend/` 对应功能,在小程序端提供 OA 四大功能的原生体验。 **已确认的范围与约束** - 四大功能:通知公告(只读浏览)、文档库(浏览+下载+收藏)、薪酬工资单(**仅本人**)、员工档案(**仅本人**、只读)。 - 后端管理端 OA 接口均为 `/backend/oa/*` 且强制 `user_type=backend`,移动端令牌调不到 → 必须新增面向客户端的 `/app/oa/*` 只读接口。 - 写操作(发布公告、上传文档、编辑工资单、维护档案)继续留在 Web 端。 - 仅本人数据通过「登录账号 → 员工」映射解析(与 `backend_auth.go` 一致)。 - 微信小程序为主端,兼容 H5/APK;沿用既有 `Sub*`/工具页的卡片风格与 `FaIcon` 图标。 ## 现状关键参考 | 用途 | 位置 | | --- | --- | | 移动端控制器鉴权/响应范式 | [app_reminder.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/controllers/app_reminder.go) | | 移动端路由注册 | [app.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/routers/app/app.go) | | 公告控制器/模型 | [backend_oa_notice.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/controllers/backend_oa_notice.go) / [oa_notice.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/models/oa_notice.go) | | 文档控制器/服务/模型 | [backend_oa_document.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/controllers/backend_oa_document.go) / [oa_document.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/services/oa_document.go) / [oa_document.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/models/oa_document.go) | | 薪酬控制器/模型 | [backend_oa_compensation.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/controllers/backend_oa_compensation.go) / [backend_oa_compensation.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/models/backend_oa_compensation.go) | | 员工档案控制器/模型 | [backend_employee_file.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/controllers/backend_employee_file.go) / [backend_employee_file.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/models/backend_employee_file.go) | | 账号→员工映射范式 | [backend_auth.go](file:///e:/Demo/Go/yunzerwebsiteallinone/go/controllers/backend_auth.go#L266-L289) | | 前端请求封装 | [request.js](file:///e:/Demo/Go/yunzerwebsiteallinone/uniapp/api/request.js) | | 前端 API 封装范式 | [schedule.js](file:///e:/Demo/Go/yunzerwebsiteallinone/uniapp/api/schedule.js) | | 列表/详情页样式范式 | [schedule/index.vue](file:///e:/Demo/Go/yunzerwebsiteallinone/uniapp/pages/tools/schedule/index.vue) | | 菜单跳转分发 | [nav.js](file:///e:/Demo/Go/yunzerwebsiteallinone/uniapp/utils/nav.js) | | OA 概览页组件 | [SubHome.vue](file:///e:/Demo/Go/yunzerwebsiteallinone/uniapp/components/sub/SubHome.vue) | ## 一、后端:新增客户端 OA 只读接口 ### 1. 新增 `go/controllers/app_oa.go` `AppOaController` + 复用式辅助方法: - `oaClaims()`:允许 `backend/app/platform`(与 `AppReminderController.appClaims` 同口径)。 - `oaOk/oaErr()`:统一 `{code,msg,data}` 响应。 - `oaTenantUID(claims)`:`services.ResolveTenantUID(tid, claims.UserID)`。 - `oaMyEmployee(tid, userID) (*models.BackendEmployee, bool)`:查 `SystemTenantUser`(uid+tid)取 `account`,再按 `tid + account` 查 `BackendEmployee`(对齐 `backend_auth.go` L266-289)。 ### 2. 接口清单 | 方法 | 路由 | 说明 | 复用 | | --- | --- | --- | --- | | GET | `/app/oa/notice/list` | 仅 `status=1`、`is_deleted=0`、`tid`;`is_top` 优先 + `publish_time` 倒序;`keyword/page/pageSize` | `models.OaNotice` | | GET | `/app/oa/notice/:id` | 详情,`read_count+1`(沿用 Raw UPDATE 写法) | 同上 | | GET | `/app/oa/document/categories` | `scope=shared/personal/all` 分类树 | `services.OaDocCategoryTree` | | GET | `/app/oa/document/list` | 文档分页(scope/category_id/uncategorized/keyword/mine/star/doc_type) | `services.OaDocList` | | GET | `/app/oa/document/:id` | 文档详情(累加查看数) | `services.OaDocView` | | GET | `/app/oa/document/download/:id` | 记录下载数并返回下载地址 | `services.OaDocDownload` | | POST | `/app/oa/document/:id/star` | 收藏/取消收藏 | `services.OaDocToggleStar` | | GET | `/app/oa/compensation/payrolls` | **仅本人**薪资单,`employee_id = 我的员工ID` + `is_deleted=0`;`payroll_month` 可选 | `payrollMap()`(包级函数,可直接复用) | | GET | `/app/oa/compensation/payrolls/:id` | 明细 + 自定义增减项,二次校验 `employee_id == 我的员工ID` | `models.BackendOaPayrollItem` | | GET | `/app/oa/employee-file` | **仅本人**档案 + 子记录(教育/工作/合同/证照) | `(&BackendEmployeeFileController{}).efAssembleDTOList`、`efFileCompleteness`、`efOrgNameMap`(均只依赖 `models.Orm`,零值控制器可安全调用) | ### 3. 路由注册(`go/routers/app/app.go`) 追加 `// OA 协同办公` 段。**注意 beego 按注册顺序匹配**:字面量路由必须排在 `:id` 通配之前 (如 `document/categories`、`document/list`、`document/download/:id` 先于 `document/:id`)。 ## 二、前端:API 封装与页面 ### 1. 新增 `uniapp/api/oa.js` 依据 [schedule.js](file:///e:/Demo/Go/yunzerwebsiteallinone/uniapp/api/schedule.js) 范式封装: `fetchNotices/getNotice`、`fetchDocCategories/fetchDocs/getDoc/downloadDoc/toggleDocStar`、 `fetchPayrolls/getPayroll`、`getMyEmployeeFile`,并导出展示用枚举标签 (公告类型/级别、文档类型、薪资单状态、在职状态、婚姻状况)。 ### 2. 新增页面(统一沿用卡片 + `FaIcon` + `page-common.scss`) | 页面 | 文件 | 内容 | | --- | --- | --- | | 公告列表 | `pages/oa/notice/index.vue` | 搜索、置顶/重要标记、发布人+时间+阅读数,点击进详情 | | 公告详情 | `pages/oa/notice/detail.vue` | 标题、类型/级别标签、发布信息、正文 | | 文档库 | `pages/oa/document/index.vue` | 共享/私密空间切换、分类横向筛选、搜索、文档列表(类型图标+大小+分类) | | 文档详情 | `pages/oa/document/detail.vue` | 元信息、摘要、下载(`uni.downloadFile`+`uni.openDocument`,失败降级复制链接)、收藏切换 | | 我的工资单 | `pages/oa/compensation/index.vue` | 月份筛选、实发金额高亮、发放状态,点击进明细 | | 工资单明细 | `pages/oa/compensation/detail.vue` | 应发/扣款分项、社保公积金个税、自定义增减项、实发合计 | | 我的档案 | `pages/oa/employeefile/index.vue` | 基本信息、在岗状态、完整度、教育/工作/合同经历列表(只读) | ### 3. 注册路由(`uniapp/pages.json`) `pages` 数组追加上述 7 个页面,`navigationBarTitleText` 分别为 「通知公告 / 公告详情 / 文档库 / 文档详情 / 我的工资单 / 工资单明细 / 我的档案」, 背景统一 `#F8FAFC`。 ### 4. 菜单跳转映射(`uniapp/utils/nav.js`) 在 `NATIVE_RULES` 中补充 OA 原生路由(顺序放在既有规则之后,模式从具体到宽泛): - 通知公告:「通知公告|公告|notice」 - 文档库:「文档库|文档管理|文档图谱|document」 - 薪酬工资单:「薪酬|工资|薪资|compensation|payroll」 - 员工档案:「员工档案|人事档案|档案|employeefile|employeeFile」 ### 5. OA 概览页新增「最新公告」卡片(`SubHome.vue`) 在「日程待办」区块后新增一个 `v-if="sub.module === 'oa'"` 的区块: 调用 `/app/oa/notice/list`(pageSize=3)展示标题 + 发布时间,「全部」跳转公告列表页。 仅对 OA 生效,不影响 crm/erp/cms/tools 概览。 ## 三、验证 1. **后端编译**:`cd go && go build ./...` 通过。 2. **前端编译**:`cd uniapp && npm run dev:mp-weixin`,确认产物 `dist/dev/mp-weixin` 无报错。 3. **接口自测**(若可连库):以 app 令牌请求 `/app/oa/notice/list`、`/app/oa/document/list?scope=shared`、 `/app/oa/compensation/payrolls`、`/app/oa/employee-file`,确认鉴权、租户隔离与本人限制生效。 4. **端上验证**:微信开发者工具打开 OA 子系统,从菜单进入四个功能页,检查列表/详情/下载/收藏与公告卡片。 (注:数据库当前连接超时,接口数据验证受限于环境,必要时由用户提供实际层级/菜单信息。)