From 1fd0c4992f3ca64f9e049ef1b4291aff3fed1735 Mon Sep 17 00:00:00 2001 From: Pipeline Agent Date: Tue, 18 Aug 2026 14:46:58 +0800 Subject: [PATCH] =?UTF-8?q?design:=20=E8=BF=AD=E4=BB=A31=E6=80=BB=E4=BD=93?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=96=87=E6=A1=A3=E8=90=BD=E4=BB=93=EF=BC=88?= =?UTF-8?q?=E6=9E=B6=E6=9E=84/=E6=95=B0=E6=8D=AE=E5=BA=9343=E8=A1=A8/API?= =?UTF-8?q?=E7=AB=AF=E7=82=B9=E6=B8=85=E5=8D=95/UI=E9=A1=B5=E9=9D=A2/?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E6=8B=86=E8=A7=A3=EF=BC=89=EF=BC=8Cocai=20?= =?UTF-8?q?=E5=8F=A3=E5=BE=84=20v2.0=EF=BC=8C=E8=A6=86=E7=9B=96=20F01~F15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/hr-system.md | 13 + apps/hr-web.md | 45 +++ docs/01-design/api-design.md | 201 +++++++++++ docs/01-design/architecture.md | 243 ++++++++++++++ docs/01-design/database-design.md | 355 ++++++++++++++++++++ docs/01-design/feature-list.md | 67 ++++ docs/01-design/iteration1-task-breakdown.md | 99 ++++++ docs/01-design/ui-design.md | 237 +++++++++++++ modules/hr-contract.md | 50 +++ modules/hr-flow.md | 49 +++ modules/hr-org.md | 55 +++ modules/hr-report.md | 46 +++ modules/hr-roster.md | 51 +++ modules/hr-system.md | 55 +++ 14 files changed, 1566 insertions(+) create mode 100644 apps/hr-system.md create mode 100644 apps/hr-web.md create mode 100644 docs/01-design/api-design.md create mode 100644 docs/01-design/architecture.md create mode 100644 docs/01-design/database-design.md create mode 100644 docs/01-design/feature-list.md create mode 100644 docs/01-design/iteration1-task-breakdown.md create mode 100644 docs/01-design/ui-design.md create mode 100644 modules/hr-contract.md create mode 100644 modules/hr-flow.md create mode 100644 modules/hr-org.md create mode 100644 modules/hr-report.md create mode 100644 modules/hr-roster.md create mode 100644 modules/hr-system.md diff --git a/apps/hr-system.md b/apps/hr-system.md new file mode 100644 index 0000000..f2f7b3c --- /dev/null +++ b/apps/hr-system.md @@ -0,0 +1,13 @@ +# 应用名称: 人事系统后端服务 (hr-system) —— 【已废弃】 + +## 1. 描述 +本应用为 v1 阶段规划的"人事系统核心后端服务",基于 Java/Spring Boot 口径。 + +**状态:已废弃(v1 遗留)。** + +v1 技术口径(Java/RESTful/JWT)与产线 ocai 规范冲突,已随 SRS v1 一并归档(见 `docs/_archive/`)。 +Web 版人事系统统一由应用 **hr-web** 承载(前端 bricks/dspy 声明式页面,后端 ahserver Python,数据层 apppublic/sqlor),见 `apps/hr-web.md`。 + +## 2. 处置说明 +- 关联仓库 `repos/hr-system`(git@git.opencomputing.cn:yumoqing/hr-system.git)仅保留初始提交,不再规划功能,后续可作为 ocai 规范模块仓复用或清理,由 PM 决定。 +- 请勿基于本应用新增需求或设计。 diff --git a/apps/hr-web.md b/apps/hr-web.md new file mode 100644 index 0000000..4ae8a73 --- /dev/null +++ b/apps/hr-web.md @@ -0,0 +1,45 @@ +# 应用名称: Web版人事系统 (hr-web) + +## 1. 应用描述 +对标钉钉睿人事的 Web 版人事管理系统(账号规模上限 100 人),覆盖组织人事底座(迭代1),后续按需扩展薪酬管理、招聘管理模块。 + +- 前端:基于 **bricks 组件体系 + dspy 声明式页面**(ocai 规范) +- 后端:基于 **ahserver(Python)** +- 数据层:基于 **apppublic/sqlor** +- 需求基线:`docs/00-requirement/requirement-spec.md`(SRS v2) +- 需求复核:`docs/00-requirement/iteration1-consistency-check.md`(F01~F15 与 SRS v2 一致性结论) +- 迭代1范围:组织人事底座,功能编号 F01~F15(逐项输入/处理/输出/验收标准见 `docs/00-requirement/iteration1-function-detail.md`) + +## 2. 包含模块 +每个应用至少关联一个模块,本应用关联以下 6 个模块(均为迭代1规划模块,F01~F15 全覆盖无遗漏): + +| 模块 | 说明文件 | 迭代1功能 | +|---|---|---| +| hr-org 组织人事 | modules/hr-org.md | F01 组织架构、F02 职位职级、F04 入职、F05 转正、F06 调动、F07 离职、F08 兼岗 | +| hr-roster 花名册 | modules/hr-roster.md | F03 花名册 | +| hr-flow 流程审批 | modules/hr-flow.md | F10 流程审批 | +| hr-contract 合同 | modules/hr-contract.md | F09 合同台账(不含电子签) | +| hr-report 报表 | modules/hr-report.md | F13 人事报表 | +| hr-system 权限日志与通用服务 | modules/hr-system.md | F11 权限、F12 操作日志、F14 工作台、F15 员工服务与提醒 | + +## 3. 部署环境(规划) +| 环境 | 用途 | 部署形态(规划) | +|---|---|---| +| dev | 开发联调 | 单实例容器部署:反向代理 + dspy 静态页 + ahserver 进程 + apppublic/sqlor | +| test | 测试验收 | 同 dev,独立数据空间 | +| prod | 生产(100 人规格) | 单实例容器部署 + 反向代理,数据定期备份 | + +## 4. 端口(规划,以设计阶段确认为准) +| 服务 | dev/test | prod | +|---|---|---| +| Web 访问(dspy 页面 + 静态资源) | 8080 | 443(HTTPS,反向代理) | +| ahserver 后端服务 | 9080 | 不直接暴露,由反向代理转发 | +| apppublic/sqlor 数据服务 | 随部署环境分配 | 仅内网访问 | + +## 5. 负责人 +待定(迭代启动会由 PM 指定应用负责人;需求文档责任人:需求分析师)。 + +## 6. 状态 +**规划中** + +> 备注:v1 遗留应用 `apps/hr-system.md`(Java/Spring Boot 口径)已废弃,由本应用取代;v1 代码仓 `repos/staff-mgr` 仅作归档参考,迭代1按 ocai 规范重建。 diff --git a/docs/01-design/api-design.md b/docs/01-design/api-design.md new file mode 100644 index 0000000..b5a2192 --- /dev/null +++ b/docs/01-design/api-design.md @@ -0,0 +1,201 @@ +# 迭代1总体设计 —— API/接口设计(hr-web,ocai 口径) + +- 版本:v2.0(迭代1-总体设计,取代 v1 Spring Boot/JWT RESTful 口径,v1 已归档至 `docs/_archive/01-design-v1-old/api-design.md`) +- 状态:提交审核 +- 规范依据:ocai 技能集 module-development-spec、dspy-file-implementation-spec、crud-definition-spec;架构基线 `docs/01-design/architecture.md` + +## 1. 接口范式与通用约定(取代 v1 RESTful/JWT) + +1. **端点形态**:全部接口为 `.dspy` 端点(受控 Python),路径 `/{module}/api/{name}.dspy`,由 ahserver wwwroot 自动路由,无需注册;GET query 与 POST body 统一解析进 `params_kw`。dspy 必须显式 `return`,且不得在 `async with db.sqlorContext` 块内 return(NoneType 陷阱)。 +2. **鉴权**:session cookie(Redis 会话)+ rbac 路径级角色控制;每条路径经各模块 `scripts/load_path.py` 注册,角色:`admin / hr / manager / employee / logined`;未注册路径默认拒绝。不使用 JWT。 +3. **数据范围**:查询类接口强制叠加 `get_data_scope(user_id)`(hr-system 提供),范围外数据不可见。 +4. **CRUD 列表/表单接口**:由 json/*.json 经 xls2ui 自动生成(列表查询、add/update/delete 包装 dspy),不在本文逐一列出;本文列出业务自定义端点。CRUD 自动生成部分约定 `new_data_url/update_data_url/delete_data_url` 位于 params 顶层。 +5. **统一响应结构**: + - 列表:`{"status":"success","data":{"rows":[...],"total":N}}`(DataViewer 强制格式) + - 业务:`{"status":"success"|"error","message":"...","data":{...}}` + - 错误返回 HTTP 200 + status=error(bricks 前端惯例),鉴权失败由框架返回 401/403。 +6. **错误码规范**(status=error 时 data.code): + +| code | 含义 | 典型场景 | +|---|---|---| +| PARAM_INVALID | 参数缺失/格式错误 | 必填项为空、日期格式错 | +| NOT_FOUND | 对象不存在 | id 无效 | +| DUPLICATE | 唯一冲突 | 工号/编码重复 | +| NO_PERMISSION | 数据范围外/角色不足 | 越权访问他人档案 | +| BLACKLIST_HIT | 黑名单命中 | 入职校验拦截 | +| STATUS_CONFLICT | 状态不允许 | 已离职再调动、重复审批 | +| FLOW_NOT_MATCH | 无匹配审批流 | 该员工类型/部门未配置流程 | +| SCOPE_OVERDRAFT | 编制/范围超限 | 预留(编制管理范围外) | +| INTERNAL_ERROR | 服务异常 | 兜底 | + +7. **审计**:所有写接口成功后调用 `write_audit_log(module,target_type,target_id,op,before,after)`(hr-system)。 + +## 2. 端点清单(按模块) + +> 角色列:A=admin,H=hr,M=manager,E=employee,L=任意登录。数据范围=是 表示叠加数据范围过滤。 +> CRUD 列:该表的标准增删改查由 json/*.json 自动生成,路径为 `/{module}/{tblname}_list`(页面) + `add_/update_/delete_{tblname}.dspy`。 + +### 2.1 hr-org(/hrorg,F01/F02/F04~F08) + +| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD | +|---|---|---|---|---|---|---| +| /hrorg/api/org_tree.dspy | GET | 组织树(支持 as_of 历史日期、status 过滤) | as_of?, status?, keyword? | 树形节点数组(id,name,parent_id,children,status,leader_name) | L | — | +| /hrorg/api/org_unit_create.dspy | POST | 新建组织(编码唯一校验、写 org_unit_change) | org_code,org_name,parent_id,org_type,leader_id,effective_date,自定义字段kv | {id} | A,H | org_unit | +| /hrorg/api/org_unit_update.dspy | POST | 编辑组织(留痕) | id,... | {} | A,H | org_unit | +| /hrorg/api/org_unit_move.dspy | POST | 移动组织(变更上级) | id,new_parent_id,effective_date | {} | A,H | — | +| /hrorg/api/org_unit_disable.dspy | POST | 停用组织(校验无在职员工引用) | id | {} | A,H | — | +| /hrorg/api/org_change_timeline.dspy | GET | 组织时间轴 | org_id | {rows:[{change_type,before_json,after_json,operator,created_at}]} | L | — | +| /hrorg/api/org_import.dspy | POST | Excel 批量导入组织(后台任务+结果文件) | file(上传) | {task_id} | A,H | — | +| /hrorg/api/org_import_result.dspy | GET | 导入结果(成功/失败行下载) | task_id | {rows,total,error_file} | A,H | — | +| /hrorg/api/org_chart_export.dspy | GET | 架构图导出(图片/XMind) | as_of?, root_id?, fmt=png/xmind | 文件下载 | A,H | — | +| /hrorg/api/org_field_def_save.dspy | POST | 组织字段自定义 | fields[] | {} | A,H | org_field_def | +| /hrorg/api/job_import.dspy / job_export.dspy | POST/GET | 职务批量导入导出 | file / 筛选条件 | {task_id} / 文件 | A,H | org_job | +| /hrorg/api/position_import.dspy / position_export.dspy | POST/GET | 职位批量导入导出 | file / dept_id?,status? | {task_id} / 文件 | A,H | org_position | +| /hrorg/api/job_options.dspy / position_options.dspy / grade_options.dspy / rank_options.dspy / sequence_options.dspy / org_options.dspy / company_options.dspy | GET | 主数据下拉选项(状态=active;供花名册/异动表单引用) | 无/keyword | {rows:[{id,name}]} | L | org_job 等 | +| /hrorg/api/entry_approval.dspy | POST | 发起入职审批(单个,匹配审批流) | name,id_number,employee_type,org_id,position_id,hire_date,... | {instance_id} 或 BLACKLIST_HIT/FLOW_NOT_MATCH | A,H | org_entry | +| /hrorg/api/entry_manual.dspy | POST | 手动入职(批量,直接入花名册或待入职) | entries[]:{...}, to=pending/roster | {entered:[],pending:[],blocked:[]} | A,H | — | +| /hrorg/api/entry_invite_register.dspy | POST | 邀请待入职填写登记表(站内消息) | entry_ids[] | {} | A,H | — | +| /hrorg/api/entry_register_submit.dspy | POST | 待入职员工提交登记表 | entry_id,字段kv | {} | E(本人) | — | +| /hrorg/api/entry_blacklist_check.dspy | GET | 黑名单校验 | id_number 或 name | {hit:bool,blacklist_id?} | A,H | — | +| /hrorg/api/entry_notify.dspy | POST | 入职通知/欢迎(模板填充发送) | entry_ids[],template_id | {} | A,H | — | +| /hrorg/api/regular_apply.dspy | POST | 发起转正审批(自助/代发) | employee_id,regular_date | {instance_id} | E(自助),H,M | org_regularization | +| /hrorg/api/regular_manual.dspy | POST | 手动转正(直接更新花名册) | employee_id,regular_date | {} | A,H | — | +| /hrorg/api/transfer_apply.dspy | POST | 发起调动审批(支持批量人员) | transfer_type,effective_date,details[]:{employee_id,to_org_id,to_position_id,...} | {instance_id} | A,H,M | org_transfer | +| /hrorg/api/transfer_cancel.dspy | POST | 取消调动(保留历史不改现职) | transfer_id | {} | A,H | — | +| /hrorg/api/leave_apply.dspy | POST | 发起离职审批(自助/代发) | employee_id,leave_type,leave_reason,leave_date | {instance_id} | E(自助),H,M | org_leave | +| /hrorg/api/leave_manual.dspy | POST | 手动离职(直接入待离职/已离职) | employee_id,leave_date,leave_reason | {} | A,H | — | +| /hrorg/api/leave_handover_save.dspy | POST | 离职交接项保存 | leave_id,items[] | {} | A,H,M | org_leave_handover | +| /hrorg/api/leave_certificate.dspy | GET | 离职证明生成下载 | employee_id | 文件 | E(本人),A,H | — | +| /hrorg/api/blacklist_add.dspy | POST | 一键加入黑名单 | leave_id 或 id_number_hash,reason | {} | A,H | org_blacklist | +| /hrorg/api/concurrent_apply.dspy | POST | 发起兼岗审批 | employee_id,org_id,position_id,start_date,end_date | {instance_id} | A,H,M | org_concurrent_post | +| /hrorg/api/workbench_transfer.dspy | GET | 工作台入转调离汇总(经理/管理员视图) | scope=team/all | {entry_n,regular_n,transfer_n,leave_n,rows} | M,H,A | — | + +### 2.2 hr-roster(/hrroster,F03) + +| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD | +|---|---|---|---|---|---|---| +| /hrroster/api/roster_list.dspy | GET | 花名册列表(主表条件分页 + EAV 拼装 + 范围过滤 + 脱敏) | keyword?,org_id?,status?,type?,field_filters?,page,size | {rows,total} | A,H(范围),M(团队) | roster_employee | +| /hrroster/api/roster_employee_create.dspy | POST | 新增员工(自动生成工号、写时间轴) | 主档字段+自定义字段kv | {id,employee_no} | A,H | roster_employee | +| /hrroster/api/roster_employee_update.dspy | POST | 更新员工(含自助修改路径:可改范围+可选审核) | id,字段kv | {} 或 {need_audit:true,instance_id} | A,H,E(本人受限) | roster_employee | +| /hrroster/api/employee_detail.dspy | GET | 员工档案详情(主档+分组字段+兼岗+合同摘要,按角色脱敏/字段可见) | id | {main,groups:[{group_name,fields:[...]}],concurrent,contracts} | L(按范围) | — | +| /hrroster/api/roster_field_def_save.dspy | POST | 字段定义维护(类型/必填/敏感/自助/审核/适用类型/排序) | fields[] | {} | A,H | roster_field_def | +| /hrroster/api/roster_field_group_save.dspy | POST | 分组维护(含拖拽排序持久化) | groups[] | {} | A,H | roster_field_group | +| /hrroster/api/roster_type_rule_save.dspy | POST | 员工类型字段规则 | employee_type,field_rules_json | {} | A,H | roster_type_rule | +| /hrroster/api/empno_rule_save.dspy | POST | 工号规则维护 | rules[] | {} | A,H | roster_empno_rule | +| /hrroster/api/check_employee_no.dspy | GET | 工号查重 | employee_no,exclude_id? | {exists} | A,H | — | +| /hrroster/api/roster_import.dspy | POST | 自定义导入(批量新增/批量修改,模板按当前字段定义生成) | file,mode=new/update | {task_id} | A,H | — | +| /hrroster/api/roster_import_template.dspy | GET | 导入模板下载(按字段定义+类型规则) | employee_type? | 文件 | A,H | — | +| /hrroster/api/roster_export.dspy | GET | 自定义导出(指定数据日期/字段/顺序) | as_of?,field_ids[],filters | {task_id}→文件 | A,H | — | +| /hrroster/api/timeline.dspy | GET | 员工时间轴(全周期记录) | employee_id,event_type? | {rows:[{event_type,event_date,title,content_json}]} | L(按范围) | — | +| /hrroster/api/timeline_add.dspy | POST | 时间轴记录编辑 | employee_id,event_type,event_date,title,content | {} | A,H | — | +| /hrroster/api/file_preview_url.dspy | GET | 附件在线预览 URL(files/ 受控访问) | file_id | {url} | L(按范围) | — | +| /hrroster/api/roster_writeback.dspy | 内部 | 异动回写入口(仅 hr-org/hr-flow 服务内调用,注册于 ServerEnv,不注册 HTTP 路径) | biz_type,biz_id,instance_id | {} | 服务内 | — | + +### 2.3 hr-flow(/hrflow,F10) + +| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD | +|---|---|---|---|---|---|---| +| /hrflow/api/form_def_save.dspy | POST | 表单定义维护(引用花名册字段) | form_code,form_name,biz_type,fields_json | {id} | A,H | flow_form_def | +| /hrflow/api/flow_def_save.dspy | POST | 流程定义(匹配条件、版本) | flow_code,form_id,biz_type,match_cond_json | {id} | A,H | flow_def | +| /hrflow/api/flow_node_save.dspy | POST | 节点维护(审批人/通过规则/字段权限/抄送) | flow_id,nodes[] | {} | A,H | flow_node_def | +| /hrflow/api/flow_role_save.dspy | POST | 审批角色(流程范围/操作权限/数据范围) | role_name,flow_scope_json,op_perm_json,data_scope_json | {id} | A | flow_role | +| /hrflow/api/flow_match.dspy | GET | 按员工类型/部门匹配流程 | biz_type,employee_type,org_id | {flow_id,flow_name} 或 FLOW_NOT_MATCH | 服务内/HR | — | +| /hrflow/api/flow_start.dspy | POST | 发起审批(通用:业务模块统一入口) | biz_type,biz_id,form_data_json | {instance_id,inst_no} | L | — | +| /hrflow/api/task_todo.dspy | GET | 我的待办 | page,size | {rows,total} | L | — | +| /hrflow/api/task_done.dspy | GET | 已办 | page,size | {rows,total} | L | — | +| /hrflow/api/inst_mine.dspy | GET | 我发起的 | status?,page,size | {rows,total} | L | — | +| /hrflow/api/inst_received.dspy | GET | 我收到的(抄送/知会) | page,size | {rows,total} | L | — | +| /hrflow/api/inst_detail.dspy | GET | 审批单详情(表单数据+流转记录+字段权限) | instance_id | {form_data,nodes:[{op,operator,time,comment}],status} | L(参与者) | — | +| /hrflow/api/task_approve.dspy | POST | 同意 | task_id,comment? | {} | L(任务归属) | — | +| /hrflow/api/task_reject.dspy | POST | 驳回 | task_id,comment | {} | L(任务归属) | — | +| /hrflow/api/task_forward.dspy | POST | 转交 | task_id,to_user_id | {} | L(任务归属) | — | +| /hrflow/api/inst_withdraw.dspy | POST | 撤回(发起人,仅首节点未处理) | instance_id | {} | L(发起人) | — | +| /hrflow/api/inst_query.dspy | GET | 审批数据查询(表单/状态/发起人/编号/时间) | form_name?,status?,initiator?,inst_no?,date_range | {rows,total} | A,H | — | +| /hrflow/api/inst_export.dspy | GET | 审批数据导出 | 同上 | 文件 | A,H | — | +| /hrflow/api/inst_print.dspy | GET | 审批单打印视图 | instance_id | 打印 HTML | L(参与者) | — | + +### 2.4 hr-contract(/hrcontract,F09) + +| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD | +|---|---|---|---|---|---|---| +| /hrcontract/api/contract_list.dspy | GET | 合同台账列表(范围过滤) | employee_id?,status?,type_id?,end_before? | {rows,total} | A,H | contract_info | +| /hrcontract/api/contract_create.dspy | POST | 新增合同(模板引用) | employee_id,type_id,company_id,start_date,end_date,file | {id} | A,H | contract_info | +| /hrcontract/api/contract_import.dspy | POST | 批量导入 | file | {task_id} | A,H | — | +| /hrcontract/api/contract_apply.dspy | POST | 合同审批(新签/续签/变更/终止) | contract_id?,biz_type=contract_sign/renew/change/stop,form_data_json | {instance_id} | A,H | — | +| /hrcontract/api/contract_remind_rule_save.dspy | POST | 到期提醒规则 | rule_name,days_before,target_role,content_template | {id} | A,H | contract_remind_rule | +| /hrcontract/api/contract_template_save.dspy | POST | 模板维护 | template_name,type_id,file,field_marks_json | {id} | A,H | contract_template | +| /hrcontract/api/contract_expire_soon.dspy | GET | 即将到期列表(工作台/提醒) | days | {rows} | A,H | — | +| /hrcontract/api/esign_stub.dspy | POST | 电子签预留桩(返回未启用提示) | contract_id | {status:'error',code:'NOT_ENABLED'} | A,H | — | + +### 2.5 hr-report(/hrreport,F13,全部只读) + +| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | +|---|---|---|---|---|---| +| /hrreport/api/roster_analysis.dspy | GET | 花名册多维分布(维度可自定义) | dim=type/status/age/edu/location/gender/custom_field_id | {rows:[{dim_value,count}],total} | A,H,M(范围) | +| /hrreport/api/entry_analysis.dspy | GET | 入职数量与趋势 | dim=org/location/position,period=month/quarter | {trend:[],rows:[]} | A,H,M | +| /hrreport/api/regular_analysis.dspy | GET | 转正分析与近期待转正 | period? | {trend:[],upcoming:[]} | A,H,M | +| /hrreport/api/transfer_analysis.dspy | GET | 近期调动分析 | date_range? | {rows:[{type,count}]} | A,H,M | +| /hrreport/api/leave_analysis.dspy | GET | 离职分析(待离职数/原因/离职率/同环比) | period? | {pending_n,reasons:[],rate:{cur,yoy,mom}} | A,H,M | +| /hrreport/api/team_stats.dspy | GET | 团队人事统计(经理工作台卡片) | org_id? | {headcount,entry_n,leave_n,...} | M,H,A | + +### 2.6 hr-system(/hrsystem,F11/F12/F14/F15) + +| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD | +|---|---|---|---|---|---|---| +| /hrsystem/api/role_save.dspy | POST | 管理角色创建与权限设置(rbac 角色+路径) | role_name,paths[] | {id} | A | sys_role(rbac) | +| /hrsystem/api/data_scope_save.dspy | POST | 人员范围(组织维度/花名册字段维度) | admin_user_id,scope_type,org_ids[]/field_ids[] | {} | A | sys_data_scope | +| /hrsystem/api/admin_save.dspy | POST | 管理员管理(创建/调整权限) | user_id,roles[] | {} | A | — | +| /hrsystem/api/get_data_scope.dspy | 内部 | 数据范围查询(ServerEnv 注册,供各模块查询叠加) | user_id | {scope_type,org_ids,field_ids} | 服务内 | — | +| /hrsystem/api/audit_log_list.dspy | GET | 操作日志查询(时间/类型/模块) | module?,operation?,date_range,target? | {rows,total} | A | sys_audit_log | +| /hrsystem/api/audit_log_detail.dspy | GET | 日志详情(前后对比) | id | {before_json,after_json,operator,ip,time} | A | — | +| /hrsystem/api/workbench_employee.dspy | GET | 员工工作台聚合(档案摘要/待办数/可发起流程) | — | {profile,todo_n,flows:[...]} | E | — | +| /hrsystem/api/workbench_manager.dspy | GET | 经理工作台聚合(团队统计/待审批/关怀提醒) | — | {stats,todos:[],care:[...]} | M | — | +| /hrsystem/api/workbench_admin.dspy | GET | 管理员工作台聚合(人事统计/合同到期/提醒) | — | {stats,contracts:[],care:[...]} | A,H | — | +| /hrsystem/api/remind_rule_save.dspy | POST | 通用提醒规则(多场景自定义) | scene_code,rule_name,days_before,content_template,target_role | {id} | A,H | sys_remind_rule | +| /hrsystem/api/care_config_save.dspy | POST | 生日/周年关怀文案配置 | care_type,template,enable | {} | A,H | sys_care_config | +| /hrsystem/api/announcement_save.dspy | POST | 公告发布 | title,content,publish_scope_json | {id} | A,H | sys_announcement | +| /hrsystem/api/policy_save.dspy | POST | 政策发布(查阅范围/下载权限) | title,file,view_scope_json,downloadable | {id} | A,H | sys_policy | +| /hrsystem/api/message_list.dspy | GET | 我的站内消息 | is_read?,msg_type? | {rows,total} | L | — | +| /hrsystem/api/message_read.dspy | POST | 标记已读 | ids[] | {} | L | — | +| /hrsystem/api/remind_scan.dspy | 内部 | 提醒扫描(cron/启动任务:转正/合同/生日等到期扫描推送) | — | {sent_n} | 服务内 | — | + +### 2.7 appbase/rbac 沿用(不自研) + +登录/登出、用户管理、字典 appcodes 维护、rbac 角色路径绑定由 appbase/rbac 包自带页面与端点承载(`/appbase/*`、`/rbac/*`),迭代1仅在各模块 init/data.json 中初始化字典与角色。 + +## 3. 典型调用链示例 + +### 3.1 转正审批(F05 流程2) +1. `POST /hrorg/api/regular_apply.dspy` {employee_id, regular_date} → hr-org 校验员工状态(probation); +2. 内部调用 `flow_match(biz_type=regular, employee_type, org_id)` → `POST /hrflow/api/flow_start.dspy` {biz_type:'regular', biz_id:regularization_id, form_data_json} → 生成 flow_instance + 首节点 flow_task,发站内消息给审批人; +3. 审批人 `POST /hrflow/api/task_approve.dspy` → 全部节点通过 → flow_instance.inst_status=approved; +4. hr-flow 完成回调 → hr-org `regular_confirm` → hr-roster `roster_writeback`:roster_employee.employee_status=regular、regular_date 更新,写 roster_timeline; +5. 各步均写 sys_audit_log;转正提醒由 `remind_scan` 按预计日期提前推送管理员与直属主管。 + +### 3.2 花名册列表(F03) +`GET /hrroster/api/roster_list.dspy?keyword=张&org_id=..&status=regular&page=1&size=50` → 权限校验(数据范围 org_ids/field_ids)→ 主表条件分页 → 值表批量拼装显示字段 → 敏感字段按角色脱敏 → `{"status":"success","data":{"rows":[...],"total":N}}`。 + +### 3.3 入职黑名单拦截(F04) +`POST /hrorg/api/entry_approval.dspy` → id_number 哈希匹配 org_blacklist → 命中返回 `{"status":"error","data":{"code":"BLACKLIST_HIT"}}`,前端待入职列表高亮标注;手动入职返回 blocked 名单。 + +## 4. 与 v1 接口的替代关系(衔接 staff-mgr) + +| v1 端点(JWT RESTful) | 迭代1替代 | +|---|---| +| POST /api/v1/staff | /hrorg/api/entry_manual.dspy 或 /hrroster/api/roster_employee_create.dspy | +| GET /api/v1/staff | /hrroster/api/roster_list.dspy(+ CRUD 列表页) | +| GET /api/v1/staff/{id} | /hrroster/api/employee_detail.dspy | +| PUT /api/v1/staff/{id} | /hrroster/api/roster_employee_update.dspy | +| DELETE /api/v1/staff/{id}、batch-delete | 离职流程 /hrorg/api/leave_manual.dspy(迭代1不做删除语义,裁决 Q6) | +| GET /api/v1/staff/{id}/change-logs | /hrroster/api/timeline.dspy | +| GET /api/v1/staff/audit-logs | /hrsystem/api/audit_log_list.dspy | +| GET /api/v1/staff/check/employee-no | /hrroster/api/check_employee_no.dspy | +| GET /api/v1/staff/departments | /hrorg/api/org_tree.dspy | + +## 5. 安全设计要点 + +1. 所有路径 load_path.py 注册;未注册即拒绝(含 .css/.js 静态资源)。 +2. 敏感字段(身份证全角色脱敏前3后3;手机前3后4;职级/薪资类字段仅 admin/hr)由 roster_field_def.sensitive + 角色矩阵驱动,服务端脱敏后返回。 +3. 全部 SQL 经 sqlor 绑定参数(`${var}$` 占位),禁止拼接用户输入。 +4. 审批操作校验任务归属人;员工自助类接口校验本人(或白名单字段)。 +5. 导入导出、登录、权限变更全量写 sys_audit_log(含 IP)。 diff --git a/docs/01-design/architecture.md b/docs/01-design/architecture.md new file mode 100644 index 0000000..2f48955 --- /dev/null +++ b/docs/01-design/architecture.md @@ -0,0 +1,243 @@ +# 迭代1总体设计 —— 系统架构与技术选型(hr-web) + +- 版本:v1.1(迭代1-总体设计;v1.1 变更:database/api/ui 三份配套文档已按 ocai 口径重写为 v2.0,表数量与端点数量同步修正) +- 状态:提交审核 +- 需求基线:`docs/00-requirement/requirement-spec.md`(SRS v2)+ `docs/00-requirement/iteration1-function-detail.md`(F01~F15) +- 应用定义:`apps/hr-web.md`;模块定义:`modules/hr-org.md`、`hr-roster.md`、`hr-flow.md`、`hr-contract.md`、`hr-report.md`、`hr-system.md` +- 开发规范:ocai 技能集 —— web-application-spec、module-development-spec、database-table-definition-spec、crud-definition-spec、dspy-file-implementation-spec + +## 0. 审核退回意见响应索引 + +PM 退回意见要求交付件至少包含 6 项内容,落点如下: + +| # | 退回意见要求 | 落点文档/章节 | +|---|---|---| +| 1 | 系统总体架构与模块划分(hr-system、staff-mgr 职责边界) | 本文 §2、§4、§6 | +| 2 | 数据库设计(核心表、字段、索引、关系、迁移策略) | `database-design.md` 全文(§4 表结构、§5 索引策略、§7 迁移策略) | +| 3 | API 设计(路径、方法、请求/响应、鉴权、错误码) | `api-design.md` 全文(§1 通用约定、§2 端点清单、§3 示例) | +| 4 | UI 设计(页面结构、核心交互、组件/路由) | `ui-design.md` 全文(§2 路由、§3 组件树、§4 交互流程) | +| 5 | 与现有 staff-mgr 员工管理模块的衔接方案 | 本文 §6 + `database-design.md` §6 数据迁移 | +| 6 | 技术可行性说明与后续开发任务拆解 | `iteration1-task-breakdown.md` 全文 | + +## 1. 概述 + +迭代1交付「Web 版人事系统(hr-web)」组织人事底座,功能范围 F01~F15:组织架构、职位职级体系、花名册、入职/转正/调动/离职/兼岗、合同台账(不含电子签)、流程审批、权限/日志、报表、工作台、员工服务与提醒。规模规格 100 人账号。 + +设计原则: +1. **全栈遵循 ocai 规范**:前端 bricks 组件体系(.ui 纯 JSON 声明式页面 + dspy 驱动的 CRUD),后端 ahserver(Python/aiohttp),数据层 apppublic/sqlor,基础模块 appbase(字典/用户)+ rbac(角色权限)。 +2. **配置驱动**:表结构(models/*.json)、CRUD 界面(json/*.json)、字典(appcodes)全部声明式定义,减少硬编码,支撑 SRS 的"字段/流程/表单自定义"诉求。 +3. **模块宿主无关**:每个模块仅依赖基础包与自己的数据表,通过 `load_{module}()` 注册 ServerEnv,可被任意宿主应用加载(module-development-spec)。 +4. **单一事实来源**:花名册(roster_employee)是全系统员工数据唯一事实来源,入转调离审批通过后统一回写花名册。 + +## 2. 总体架构 + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ 浏览器(PC Web 为主) │ +│ bricks.js 渲染引擎:.ui(JSON) 页面 + DataViewer/Tree/Form/Chart │ +└──────────────────────────────┬─────────────────────────────────────┘ + │ HTTP(S) session cookie(Redis 会话) +┌──────────────────────────────▼─────────────────────────────────────┐ +│ nginx 反向代理(prod: 443) │ +└──────────────────────────────┬─────────────────────────────────────┘ +┌──────────────────────────────▼─────────────────────────────────────┐ +│ ahserver 应用进程(hr-web,dev:9080) │ +│ 路由:wwwroot 自动路由 /{module}/{file}.ui|.dspy|.css|.js │ +│ processors: .tmpl→tmpl, .ui→bui, .dspy→dspy │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ 业务模块(load_xxx 注册 ServerEnv) │ │ +│ │ hr-org | hr-roster | hr-flow | hr-contract | hr-report | │ │ +│ │ hr-system │ │ +│ ├─────────────────────────────────────────────────────────────┤ │ +│ │ 基础模块:appbase(users/appcodes 字典)+ rbac(角色/权限) │ │ +│ │ bricks_for_python(UiWindow 等 pybricks) │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +└──────────┬───────────────────────────────┬─────────────────────────┘ + │ sqlor 连接池(sor.C/U/D/R/I/sqlExe) │ Redis session +┌──────────▼──────────┐ ┌────────▼────────┐ +│ MySQL 8.0(库 hr) │ │ Redis(会话) │ +│ json2ddl 生成 DDL │ └─────────────────┘ +└─────────────────────┘ files/ 目录:附件存储(合同文件、头像、导入导出文件) +``` + +请求处理链路(以花名册列表为例): +1. 浏览器访问 `/hrroster/roster_list.ui`(由 json/roster_employee_list.json 经 xls2ui 生成的 DataViewer 页); +2. DataViewer 按 CRUD JSON 中的 `dataurl`/`new_data_url` 等调用 `/hrroster/api/xxx.dspy`; +3. ahserver 将 GET query + POST body 统一解析为 `params_kw` 注入 dspy 上下文; +4. dspy 调用 `load_hrroster()` 注册的业务函数(内部经 sqlor `sor.R` 查询,叠加 rbac 数据范围过滤与敏感字段脱敏); +5. dspy 显式 `return` JSON(列表必须 `{status:'success', data:{rows:[...], total:N}}`),bricks 渲染。 + +## 3. 技术选型与理由 + +| 层 | 选型 | 选型理由 | +|---|---|---| +| 前端 | bricks 组件体系 + .ui 纯 JSON 页面 | ocai 强制规范;CRUD JSON 自动生成列表/表单/树页面,F01~F15 中 80% 的增删改查页面零 Vue 代码;DataViewer 自带筛选(data_filter)、子表(subtables)、工具栏 bind | +| 声明式页面脚本 | .dspy(受控 Python) | 后端 API 与页面逻辑统一语言栈(Python);ahserver 自动解析参数、自动 JSON 序列化;禁止 import/print,天然受控 | +| 后端框架 | ahserver(aiohttp 异步) | ocai 强制规范;内置会话/RBAC/文件上传/后台任务;wwwroot 自动路由免手写路由注册;100 人规模单实例足够 | +| 数据访问 | apppublic/sqlor | 异步连接池 + 绑定参数防注入;`sor.C/U/D/R/I/sqlExe` 六元 API 覆盖全部数据操作;与 models JSON 配套 | +| 表定义 | models/*.json + json2ddl | database-table-definition-spec 标准;数据库无关的抽象类型,DDL 自动生成,保证 collate utf8mb4_unicode_ci 一致 | +| CRUD 生成 | json/*.json + xls2ui | crud-definition-spec 标准;自动产出列表页 .ui 与 add/update/delete dspy 包装 | +| 字典 | appbase appcodes/appcodes_kv | 性别/员工类型/异动类型/离职原因等枚举统一管理,CRUD 下拉直接引用(codes 段) | +| 权限 | rbac 模块 + 自研数据范围表 | rbac 管"功能权限(路径级)",hr-system 扩展"数据范围(组织维度/花名册字段维度)",满足 SRS §3.1.14 | +| 数据库 | MySQL 8.0 | 产线既有设施(staff-mgr 亦为 MySQL),sqlor DDL 模板成熟 | +| 会话 | Redis + aiohttp_session | web-application-spec 推荐;服务重启不丢登录 | +| 附件 | ahserver files/ 文件存储 | 合同附件、离职证明、导入导出文件;100 人规模本地目录足够 | + +与 v1(Java/Spring Boot/JPA/JWT)口径的差异已全部废弃归档(`docs/_archive/`),不再保留双栈:鉴权由"自研 JWT Filter"改为"ahserver session + rbac",ORM 由 JPA 改为 sqlor,前端由"无"改为 bricks/dspy。 + +## 4. 模块划分与职责边界 + +### 4.1 迭代1模块清单(6 个,均挂载于 hr-web 应用) + +| 模块 | 路由前缀 | 职责 | 数据表前缀 | 迭代1功能 | +|---|---|---|---|---| +| hr-org | /hrorg | 组织架构、职位职级体系、入转调离兼岗异动业务、黑名单、合同公司 | org_ | F01/F02/F04~F08 | +| hr-roster | /hrroster | 花名册(字段定义/字段值 EAV/员工主档/时间轴/工号规则)、导入导出 | roster_ | F03 | +| hr-flow | /hrflow | 表单定义、流程定义、流程实例、审批任务(待办/已办/我发起) | flow_ | F10 | +| hr-contract | /hrcontract | 合同台账、合同模板、到期提醒规则、合同审批 | contract_ | F09 | +| hr-report | /hrreport | 只读聚合报表(花名册分析/入职/转正/调岗/离职分析),无自有表 | — | F13 | +| hr-system | /hrsystem | 角色/管理员/数据范围、操作日志、工作台聚合、提醒规则、公告政策、站内消息 | sys_ | F11/F12/F14/F15 | + +### 4.2 职责边界规则 + +1. **员工主数据唯一入口**:所有模块读写员工信息必须经 hr-roster 的注册函数(ServerEnv 暴露),禁止跨模块直接 SQL 写 roster_ 表。入转调离审批通过后由 hr-flow 回调 hr-org 的业务函数,再调用 hr-roster 回写接口更新员工状态。 +2. **审批引擎与业务解耦**:hr-flow 只管"表单+流程+实例+任务"的流转,不含业务语义;业务回写通过 `biz_type + biz_id` 关联 + 流程完成回调(ServerEnv 注册的 hook 函数)实现。 +3. **权限横切**:功能权限(路径级 RBAC)由 rbac 模块统一拦截(各模块 scripts/load_path.py 注册路径与角色);数据范围由 hr-system 提供 `get_data_scope(user_id)` 公共函数,hr-org/hr-roster/hr-report 在查询时强制叠加。 +4. **操作日志横切**:所有写操作(sor.C/U/D)统一经 hr-system 的 `write_audit_log(...)` 记录前后值(before/after JSON),F12 查询页只读 sys_audit_log。 +5. **字典统一**:任何枚举值不得硬编码在 dspy 中,一律走 appcodes(init/data.json 初始化),CRUD 下拉用 models codes 段引用。 + +### 4.3 hr-system 与 staff-mgr 的职责边界(重点澄清) + +| 对象 | 性质 | 职责 | 状态 | +|---|---|---|---| +| **hr-system**(模块,repos/hr-system) | 迭代1 ocai 规范模块 | 系统支撑层:F11 权限管理、F12 操作日志、F14 工作台、F15 员工服务与提醒;并承载全应用的横切能力(数据范围、审计、站内消息) | 迭代1新建(复用现有空仓 hr-system.git) | +| **staff-mgr**(repos/staff-mgr) | v1 遗留 Java 模块 | 旧员工 CRUD REST 服务(/api/v1/staff/*,Spring Boot + JPA + JWT) | **已归档,冻结不再开发**;仅作迭代1数据迁移来源与参考实现(见 §6) | + +边界结论: +- 迭代1上线后 staff-mgr **不再承担任何线上职责**;其员工数据一次性迁移至 hr-roster(roster_employee + roster_field_value),部门缓存迁移至 hr-org(org_unit),日志迁移/归档至 hr-system(sys_audit_log)。 +- 旧模块的"员工 CRUD"职责由 **hr-roster** 承接(不是 hr-system);hr-system 只承接其"操作日志/权限"类横切职责。详见 §6 衔接方案。 +- v1 应用定义 `apps/hr-system.md`(Java 后端服务)已废弃,与模块 hr-system(ocai 支撑模块)仅重名,无继承关系。 + +## 5. 模块结构与依赖关系 + +### 5.1 标准模块目录(module-development-spec) + +每个业务模块仓库结构一致: + +``` +{module}/ +├── {module}/ # Python 包 +│ ├── __init__.py # 导出全部公共函数(三处注册同步点之一) +│ ├── init.py # load_{module}():ServerEnv 注册 +│ └── *.py # 业务实现(service 层) +├── wwwroot/ # index.ui、menu、业务页 .ui、api/*.dspy、css/js +├── models/ # 表定义 JSON(json2ddl → mysql.ddl.sql) +├── json/ # CRUD 定义 JSON(xls2ui → 列表页 + add/update/delete dspy) +├── init/data.json # 字典与初始化数据(appcodes Format B) +├── scripts/load_path.py # RBAC 路径注册(角色:logined/admin/hr/manager/employee) +├── skill/SKILL.md # 模块 AI 说明(数据模型/端点/坑位) +├── pyproject.toml +└── README.md +``` + +### 5.2 依赖关系图 + +``` + ┌─────────── rbac(功能权限) ◄──── appbase(users/orgs/appcodes) + │ ▲ ▲ + │ │ 路径注册/数据范围 │ 字典/用户 + ┌─────────┴──┐ ┌──────┴─────┐ ┌──────┴─────┐ + │ hr-system │◄─────│ hr-flow │◄──────────│ hr-contract│ + │ F11/12/14/15│ 审批回调/权限 │ 合同审批 │ + └─────▲──────┘ └──────▲─────┘ └──────┬─────┘ + │ 审计/数据范围 │ 入转调离审批 │ 员工/公司引用 + │ │ │ + ┌─────┴──────┐ ┌──────┴─────┐ │ + │ hr-report │─────►│ hr-org │◄─────────────────┘ + │ (只读聚合) │ 异动数据 │ 组织/职位/异动 │ + └─────▲──────┘ └──────┬─────┘ + │ 花名册分析 │ 员工主数据读写(唯一入口) + │ ┌──────▼─────┐ + └─────────────│ hr-roster │ + │ 员工唯一事实源│ + └────────────┘ +依赖方向:箭头指向被依赖方。hr-report 只读,不被任何模块依赖。 +``` + +依赖矩阵(行依赖列): + +| ↓依赖→ | hr-org | hr-roster | hr-flow | hr-contract | hr-report | hr-system | +|---|---|---|---|---|---|---| +| hr-org | — | 回写花名册/黑名单 | 异动审批流转 | — | — | 权限/日志 | +| hr-roster | 组织/职位主数据 | — | 自助修改审核 | — | — | 字段级权限/脱敏/日志 | +| hr-flow | — | 表单引用字段/完成回调 | — | — | — | 审批角色权限/日志 | +| hr-contract | 合同公司主数据 | 员工关联 | 合同审批 | — | — | 提醒通道/日志 | +| hr-report | 异动数据 | 花名册数据 | — | — | — | 数据范围 | +| hr-system | 工作台引用组织 | 工作台引用档案 | 工作台引用待办 | 工作台引用合同 | — | — | + +### 5.3 应用装配与部署 + +- 应用入口 `app/hr_web.py`:`init()` 中依次 `ServerEnv()` → 设置 `get_module_dbname`(返回 `hr`)→ `load_appbase()` → `load_rbac()` → `load_pybricks()` → `load_hrsystem/load_hrorg/load_hrroster/load_hrflow/load_hrcontract/load_hrreport()`。 +- `conf/config.json`:processors 必含 `[".tmpl","tmpl"], [".ui","bui"], [".dspy","dspy"]`;indexes 含 `index.ui`;databases 配置 hr 库;Redis session(session_max_time/session_issue_time)。 +- build.sh 顺序:建 venv → pip install apppublic/sqlor/ahserver/bricks/appbase/rbac → clone 6 个业务模块 pip install → 各模块 models/ 执行 `json2ddl mysql . > mysql.ddl.sql` 并导入 → init/data.json 导入 → json/ 执行 `xls2ui` 生成 CRUD → symlink 各模块 wwwroot 与 bricks dist → systemd 服务。 +- 环境:dev/test 单实例容器(nginx:8080 → ahserver:9080);prod nginx:443 反代,ahserver 不直接暴露,MySQL/Redis 仅内网;数据每日备份。100 人规模单实例即可满足"列表页 ≤500ms"指标(见 §8)。 + +## 6. 与现有 staff-mgr 员工管理模块的衔接方案 + +### 6.1 衔接定位 + +staff-mgr 是 v1 Java 口径下的员工 CRUD 模块(已通过端到端验证,见其 README),与 ocai 规范冲突,不改造、不并行演进,采取**一次性数据迁移 + 接口替代 + 退役**策略。 + +### 6.2 职责与接口替代映射 + +| staff-mgr 旧接口(/api/v1/staff) | 迭代1替代(hr-roster/hr-system dspy) | 说明 | +|---|---|---| +| POST /(创建员工) | /hrroster/api/roster_employee_create.dspy(或手动入职 /hrorg/api/entry_manual.dspy) | 新建一律走入职流程或花名册新增 | +| GET /(分页列表) | /hrroster/roster_list(CRUD 列表 + data_filter) | 筛选能力增强(自定义字段) | +| GET /{id}(详情) | /hrroster/employee_detail.dspy | 档案 Tabs + 时间轴 | +| PUT /{id}(更新) | /hrroster/api/roster_employee_update.dspy | 可配置自助修改 + 审核 | +| DELETE /{id}、POST /batch-delete | 离职流程 /hrorg/api/leave_manual.dspy | 迭代1不做物理/逻辑删除员工,统一走离职 | +| GET /{id}/change-logs | /hrroster/timeline.dspy | 时间轴(含迁移进来的旧变更记录) | +| GET /audit-logs | /hrsystem/audit_log_list(CRUD) | 历史日志迁入 sys_audit_log | +| GET /check/employee-no | /hrroster/api/check_employee_no.dspy | 工号查重保留 | +| GET /departments | /hrorg/api/org_tree.dspy | 部门缓存表废弃,直接查 org_unit | + +脱敏规则延续并按 SRS 加强:身份证号全角色脱敏(前3后3)、手机号(前3后4)、薪资职级类字段仅 admin/hr 可见——由 hr-system 字段级权限表驱动,替代 staff-mgr 硬编码 MaskUtil。 + +### 6.3 数据迁移方案(详见 database-design.md §6) + +- 迁移对象:staff_employee → roster_employee;staff_employee_extra → roster_field_value(学历/专业等映射到预置字段定义)+ contract_info(合同起止);staff_department_cache → org_unit;staff_change_log → roster_timeline;staff_audit_log → sys_audit_log。 +- 迁移工具:hr-system 仓内 `scripts/migrate_staff_mgr.py`(Python + sqlor,幂等、按 employee_no 去重、输出核对报告)。 +- 切换策略:迭代1 UAT 通过后一次性切换;切换后 staff-mgr 服务下线、仓库冻结归档(保留只读访问一个迭代周期)。 + +### 6.4 风险与对策 + +| 风险 | 对策 | +|---|---| +| 旧数据字段语义不一致(如 status 枚举) | 迁移脚本内置映射表 + 人工核对报告;UAT 期间双库比对 | +| 旧 department_id 无组织主数据 | 先迁 staff_department_cache 建 org_unit,再按 department_id 关联 | +| 身份证号加密算法不同(AesCipher) | 迁移时解密后按 hr-web 统一加密方案重新落库 | + +## 7. 安全设计 + +1. **鉴权**:ahserver session(Redis)+ rbac 角色。迭代1角色:`admin`(系统管理员)、`hr`(人事)、`manager`(部门经理)、`employee`(员工自助);所有路径经 scripts/load_path.py 注册,未注册路径默认拒绝。 +2. **数据范围**(F11):sys_role_data_scope 支持两类范围——组织维度(org_id 集合,含子树)、花名册字段维度(field_id 可见集合)。查询层强制拼接范围条件;报表同样受控。 +3. **脱敏**:敏感字段(身份证/手机/薪资级)在 roster_field_def 标记 sensitive,dspy 返回前按角色脱敏。 +4. **审计**(F12):全量写操作记录前后值 JSON、操作人、IP;审批、导入导出同样记录。 +5. **SQL 注入**:全部经 sqlor 绑定参数;dspy 禁止拼接用户输入(sqlExe 使用 `${var}$` 占位)。 + +## 8. 非功能设计响应 + +| SRS 非功能项 | 设计响应 | +|---|---| +| 列表响应 ≤500ms | 100 人规模 + 索引设计(database-design.md §5);列表页分页默认 50;组织树一次性加载(≤200 节点) | +| 批量导入导出 100 人量级 | openpyxl 同步处理(ahserver 已内置),导入走后台任务 + 结果文件下载 | +| 字段/流程/表单自定义 | roster_field_def(EAV)、flow_form_def/flow_def JSON 化配置,无硬编码 | +| PC 为主 + 员工自助移动端兼容 | 员工自助页面(个人档案/发起审批/待办)使用 ResponsableBox 自适应布局 | + +## 9. 配套设计文档 + +- `database-design.md`(v2.0):ER、43 张表结构、索引、字典、models JSON 示例、staff-mgr 迁移策略 +- `api-design.md`(v2.0):dspy 端点清单(约 100 个)、请求/响应、鉴权角色、错误码 +- `ui-design.md`(v2.0):页面结构、组件树、路由表、核心交互流程 +- `iteration1-task-breakdown.md`(v1.0):可行性分析、风险、开发任务拆解(T01~T24) diff --git a/docs/01-design/database-design.md b/docs/01-design/database-design.md new file mode 100644 index 0000000..6559c16 --- /dev/null +++ b/docs/01-design/database-design.md @@ -0,0 +1,355 @@ +# 迭代1总体设计 —— 数据库设计(hr-web,ocai 口径) + +- 版本:v2.0(迭代1-总体设计,取代 v1 Java/JPA 口径,v1 已归档至 `docs/_archive/01-design-v1-old/`) +- 状态:提交审核 +- 需求基线:`docs/00-requirement/requirement-spec.md`(SRS v2)+ `iteration1-function-detail.md`(F01~F15) +- 架构基线:`docs/01-design/architecture.md` +- 规范依据:ocai 技能集 database-table-definition-spec(models/*.json + json2ddl)、crud-definition-spec、sqlor-database-module + +## 1. 设计总则 + +1. **表定义声明式管理**:所有表以 `models/{table}.json`(summary/fields/indexes/codes 四段)定义,build.sh 中 `json2ddl mysql . > mysql.ddl.sql` 生成 DDL 导入 `hr` 库。本文 DDL 为生成物等价示例,开发以 models JSON 为准。 +2. **统一约定**:InnoDB;utf8mb4 / utf8mb4_unicode_ci;主键 `id VARCHAR(32)`(getID() 雪花串,sqlor 惯例);公共审计列 `created_by/updated_by/created_at/updated_at`;`sor.C` 不自动填时间戳,写入时显式 `created_at=curDateString()`。 +3. **逻辑删除策略**:迭代1员工与组织**不做物理删除**,统一走"停用(status=inactive)/离职流程"(对 baseline-decision Q6 的裁决落地)。 +4. **自定义字段(EAV)**:花名册字段(F03)与组织字段(F01)采用"字段定义表 + 字段值表"EAV 方案,支撑字段/分组/类型规则自定义;固定高频查询字段(组织、职位、状态、入离职日期)冗余在员工主表保证列表性能。 +5. **敏感字段**:身份证号密文列 + 哈希列(确定性,供唯一性与黑名单匹配),手机号明文存储、按角色脱敏展示;`roster_field_def.sensitive` 驱动字段级脱敏与可见性。 +6. **库划分**:单库 `hr`,表前缀区分模块:`org_`(hr-org)、`roster_`(hr-roster)、`flow_`(hr-flow)、`contract_`(hr-contract)、`sys_`(hr-system);appbase(users/orgs/appcodes)与 rbac 表沿用基础包自带结构,不在本文重复。 + +## 2. ER 图(实体关系描述) + +``` + ┌──────────────┐ + │ appbase │ + │ users/orgs/ │◄── 登录用户、字典 appcodes + │ appcodes │ + └──────┬───────┘ + │ user_id 引用 +┌─────────────┐ parent_id │ ┌──────────────────┐ +│ org_unit │◄─自引用──────┼──────│ sys_data_scope │ 组织维度数据范围 +│ 组织 │ │ │ sys_audit_log │ 操作日志(F12) +└──┬───┬──────┘ │ │ sys_message │ 站内消息(F15) + │ │org_field_value │ │ sys_remind_rule │ 提醒规则 + │ ▼ │ └────────▲─────────┘ + │ org_field_def │ │ 推送 + │ │ │ + │ ┌─────────────┐ ┌─────▼───────────────┴───┐ + │ │org_job/ │ │ roster_employee │ 员工唯一事实源(F03) + │ │org_position◄─┼──│ org_id/position_id/ │ + │ │org_sequence/ │ │ employee_status/... │ + │ │org_grade_* │ └──┬──────┬──────┬─────────┘ + │ └─────────────┘ │ │ │ + │ │ │ ▼ + │ roster_field_def◄────┘ roster_field_value(EAV) + │ roster_field_group roster_timeline(时间轴) + │ │ + │ 异动业务(hr-org) │ 合同(hr-contract) + │ org_entry ──────────┤ contract_info ── employee_id + │ org_regularization ─┼──► contract_type / contract_template + │ org_transfer(+detail)│ contract_remind_rule + │ org_leave(+handover) │ │审批 + │ org_concurrent_post │ ▼ + │ │审批流转 │ ┌──────────────┐ + └────────┴──────────────┴────►│ flow_def │ 流程定义 + biz_type+biz_id │ flow_form_def│ 表单定义(引用花名册字段) + │ flow_node_def│ 节点(审批人/字段权限) + │ flow_role │ 审批角色 + │ flow_instance│ 实例 ──► flow_task(待办) + │ │ └► flow_op_log + └──────────────┘ +hr-report 无自有表:只读聚合 org_/roster_/flow_ 表,叠加 sys_data_scope 范围过滤。 +``` + +核心关系说明: +- `roster_employee` 为全系统员工数据唯一事实源;`org_entry/regularization/transfer/leave/concurrent_post` 通过 `employee_id`(入职审批阶段可为空)关联,审批通过后经 hr-roster 回写接口更新主档。 +- 所有审批类记录通过 `flow_instance_id` 关联流程实例;`flow_instance.biz_type + biz_id` 反向定位业务单据,流程完成后回调业务模块回写。 +- `roster_field_value`/`org_field_value` 为 EAV 值表,外键指向 `roster_field_def`/`org_field_def`。 +- 所有表与 appbase.users 之间为逻辑外键(operator_id/leader_id/approver_id),不建物理外键(sqlor 惯例,跨模块解耦)。 + +## 3. models JSON 示例(规范格式,json2ddl 输入) + +`hr-roster/models/roster_employee.json`: + +```json +{ + "summary": [ + {"name": "roster_employee", "title": "员工主档", "pk": ["id"], "charset": "utf8mb4", "collate": "utf8mb4_unicode_ci"} + ], + "fields": [ + {"name": "id", "title": "主键", "type": "varchar", "length": 32}, + {"name": "employee_no", "title": "工号", "type": "varchar", "length": 32}, + {"name": "name", "title": "姓名", "type": "varchar", "length": 64}, + {"name": "gender", "title": "性别", "type": "varchar", "length": 16}, + {"name": "id_number_cipher", "title": "证件号密文", "type": "varchar", "length": 256}, + {"name": "id_number_hash", "title": "证件号哈希", "type": "varchar", "length": 64}, + {"name": "birthday", "title": "出生日期", "type": "date"}, + {"name": "phone", "title": "手机号", "type": "varchar", "length": 20}, + {"name": "email", "title": "邮箱", "type": "varchar", "length": 128}, + {"name": "org_id", "title": "组织", "type": "varchar", "length": 32}, + {"name": "position_id", "title": "职位", "type": "varchar", "length": 32}, + {"name": "job_id", "title": "职务", "type": "varchar", "length": 32}, + {"name": "grade_level_id", "title": "职级", "type": "varchar", "length": 32}, + {"name": "grade_rank_id", "title": "职等", "type": "varchar", "length": 32}, + {"name": "sequence_id", "title": "序列", "type": "varchar", "length": 32}, + {"name": "employee_type", "title": "员工类型", "type": "varchar", "length": 16}, + {"name": "employee_status", "title": "员工状态", "type": "varchar", "length": 16}, + {"name": "hire_date", "title": "入职日期", "type": "date"}, + {"name": "regular_date", "title": "转正日期", "type": "date"}, + {"name": "leave_date", "title": "离职日期", "type": "date"}, + {"name": "company_id", "title": "合同公司", "type": "varchar", "length": 32}, + {"name": "work_location", "title": "办公地点", "type": "varchar", "length": 128}, + {"name": "direct_leader_id", "title": "直属主管", "type": "varchar", "length": 32}, + {"name": "remark", "title": "备注", "type": "text"}, + {"name": "created_by", "title": "创建人", "type": "varchar", "length": 32}, + {"name": "updated_by", "title": "更新人", "type": "varchar", "length": 32}, + {"name": "created_at", "title": "创建时间", "type": "timestamp"}, + {"name": "updated_at", "title": "更新时间", "type": "timestamp"} + ], + "indexes": [ + {"name": "uk_employee_no", "unique": true, "fields": ["employee_no"]}, + {"name": "uk_id_number_hash", "unique": true, "fields": ["id_number_hash"]}, + {"name": "idx_org_id", "fields": ["org_id"]}, + {"name": "idx_status", "fields": ["employee_status"]}, + {"name": "idx_hire_date", "fields": ["hire_date"]}, + {"name": "idx_direct_leader", "fields": ["direct_leader_id"]} + ], + "codes": [ + {"name": "gender", "source": "appcodes", "code": "GENDER"}, + {"name": "employee_type", "source": "appcodes", "code": "EMP_TYPE"}, + {"name": "employee_status", "source": "appcodes", "code": "EMP_STATUS"} + ] +} +``` + +CRUD 侧配套 `hr-roster/json/roster_employee_list.json`(crud-definition-spec):`tblname=roster_employee`,`params` 顶层配置 `new_data_url/update_data_url/delete_data_url` 指向 `wwwroot/api/roster_employee_{create,update,delete}.dspy`,`data_filter` 声明姓名/工号/组织/状态筛选项,`browserfields.alters` 引用 GENDER/EMP_TYPE/EMP_STATUS 字典。 + +## 4. 表结构设计(43 张业务表) + +> 公共列约定:凡标【审计】的表均含 `created_by/updated_by/created_at/updated_at`;日志类表仅含 `created_at`。DDL 示例见 §4.6。 + +### 4.1 hr-org 组织人事(18 张,前缀 org_) + +| # | 表 | 用途 | 关键字段 | 关键索引 | +|---|---|---|---|---| +| 1 | org_unit | 组织(F01) | id, org_code, org_name, parent_id(自引用), org_type(字典ORG_TYPE), leader_id, effective_date, expire_date(空=长期), status(active/inactive), sort_no【审计】 | uk_org_code; idx_parent_id; idx_status | +| 2 | org_unit_change | 组织变更时间轴(F01) | id, org_id, change_type(add/edit/disable/move/split/merge/delete), before_json, after_json, effective_date, operator_id, flow_instance_id, created_at | idx_org_id; idx_created_at | +| 3 | org_field_def | 组织自定义字段(F01) | id, field_code, field_name, field_type(text/number/date/select/file), options_json, required, sort_no, status【审计】 | uk_field_code | +| 4 | org_field_value | 组织字段值 EAV | id, org_id, field_id, value_text, value_date, value_file, updated_at | uk(org_id,field_id) | +| 5 | org_job | 职务(F02) | id, job_code, job_name, status, sort_no, remark【审计】 | uk_job_code | +| 6 | org_position | 职位(F02) | id, position_code, position_name, job_id, sequence_id, category(字典POS_CATEGORY), dept_ids(多值,逗号分隔), description, status, sort_no【审计】 | uk_position_code; idx_job_id | +| 7 | org_sequence | 序列(F02) | id, seq_category, seq_name, grade_level_ids(关联职级类别), status【审计】 | — | +| 8 | org_grade_level | 职级(F02) | id, level_code, level_name, level_category, start_rank_id, end_rank_id, sort_no【审计】 | uk_level_code | +| 9 | org_grade_rank | 职等(F02) | id, rank_code, rank_name, rank_level(int), sort_no【审计】 | uk_rank_code | +| 10 | org_blacklist | 黑名单(F04/F07) | id, name, id_number_hash, id_number_cipher, reason, source(leave/manual), source_employee_id, created_by, created_at | idx_id_number_hash | +| 11 | org_contract_company | 合同公司(F01/F09) | id, company_code, company_name, credit_code, legal_person, contact_info, status【审计】 | uk_company_code | +| 12 | org_entry | 入职记录(F04) | id, employee_id(可空,待入职), name, id_number_cipher/hash, employee_type, org_id, position_id, company_id, work_location, hire_date, entry_status(pending_approval/pending_entry/entered/cancelled/blocked), is_rehire, register_status(登记表填写状态), flow_instance_id, remark【审计】 | idx_entry_status; idx_hire_date; idx_flow_instance_id | +| 13 | org_regularization | 转正记录(F05) | id, employee_id, probation_end_date, regular_date, apply_type(self/proxy/manual), status(pending/approved/rejected/cancelled), flow_instance_id, remark【审计】 | idx_employee_id; idx_regular_date | +| 14 | org_transfer | 调动单(F06,支持批量) | id, transfer_type(promotion/demotion/position_change/org_adjust), status(pending/confirmed/cancelled), effective_date, batch_no, flow_instance_id, remark【审计】 | idx_status; idx_effective_date | +| 15 | org_transfer_detail | 调动明细(逐人) | id, transfer_id, employee_id, from_org_id, to_org_id, from_position_id, to_position_id, from_grade_level_id, to_grade_level_id, status | idx_transfer_id; idx_employee_id | +| 16 | org_leave | 离职记录(F07) | id, employee_id, leave_type(辞职/劝退/合同到期/退休), leave_reason(字典LEAVE_REASON), leave_date, apply_type(self/proxy/manual), status(pending_leave/left/cancelled), handover_status, certificate_file, blacklist_flag, flow_instance_id, remark【审计】 | idx_employee_id; idx_status; idx_leave_date | +| 17 | org_leave_handover | 离职交接项 | id, leave_id, item_type(approval/file/subordinate/permission/other), item_content, handover_to_id, status(pending/done), remark | idx_leave_id | +| 18 | org_concurrent_post | 兼岗(F08) | id, employee_id, org_id, position_id, start_date, end_date, status(awaiting/active/expired), flow_instance_id【审计】 | idx_employee_id; idx_status | + +### 4.2 hr-roster 花名册(7 张,前缀 roster_) + +| # | 表 | 用途 | 关键字段 | 关键索引 | +|---|---|---|---|---| +| 19 | roster_field_group | 字段分组(F03) | id, group_code, group_name(工作信息/个人信息/绩效结果/培训记录), sort_no, status【审计】 | uk_group_code | +| 20 | roster_field_def | 字段定义(F03 核心) | id, group_id, field_code, field_name, field_type(text/number/date/select/multiselect/file), options_json(字典code或自定义项), required, sensitive(0/1), editable_self(0/1), need_audit(0/1自助修改审核), apply_types(JSON适用员工类型), sort_no, status【审计】 | uk_field_code; idx_group_id | +| 21 | roster_employee | 员工主档(F03) | 见 §3 models 示例 | 见 §3 | +| 22 | roster_field_value | 字段值 EAV | id, employee_id, field_id, value_text, value_number(decimal(18,4)), value_date, value_file, updated_by, updated_at | uk(employee_id,field_id); idx_field_id | +| 23 | roster_empno_rule | 工号规则(F03) | id, rule_name, prefix, match_field(如company_id), match_value, seq_length, current_seq(int), status【审计】 | — | +| 24 | roster_timeline | 员工时间轴(F03/F12 联动) | id, employee_id, event_type(entry/regular/transfer/leave/concurrent/contract/field_change/migrate), event_date, title, content_json, source_type, source_id, created_at | idx_emp_date(employee_id,event_date) | +| 25 | roster_type_rule | 员工类型字段规则(F03 分类管理) | id, employee_type, field_rules_json(按类型必填/隐藏字段), status【审计】 | uk(employee_type) | + +### 4.3 hr-flow 流程审批(7 张,前缀 flow_) + +| # | 表 | 用途 | 关键字段 | 关键索引 | +|---|---|---|---|---| +| 26 | flow_form_def | 表单定义(F10) | id, form_code, form_name, biz_type(entry/regular/transfer/leave/handover/concurrent/contract_sign/contract_renew/contract_change/contract_stop/roster_self_edit), fields_json(引用roster_field_def或自定义项), status【审计】 | uk_form_code | +| 27 | flow_def | 流程定义(F10) | id, flow_code, flow_name, form_id, biz_type, match_cond_json(员工类型/部门匹配条件), version, status【审计】 | uk_flow_code; idx_biz_type | +| 28 | flow_node_def | 流程节点 | id, flow_id, node_seq, node_name, approver_type(user/role/leader/admin/flow_role), approver_value, pass_rule(any/all), field_perm_json(节点字段可读写), cc_to(抄送) | idx_flow_id | +| 29 | flow_role | 审批角色(F10) | id, role_name, flow_scope_json(可用流程), op_perm_json(操作权限), data_scope_json(数据查看范围), status【审计】 | — | +| 30 | flow_instance | 流程实例 | id, inst_no(审批编号), flow_id, form_id, biz_type, biz_id, title, initiator_id, inst_status(running/approved/rejected/cancelled), submit_data_json, start_time, finish_time | uk_inst_no; idx_biz(biz_type,biz_id); idx_initiator; idx_status | +| 31 | flow_task | 审批任务(待办/已办) | id, instance_id, node_id, node_name, approver_id, task_status(pending/approved/rejected/forwarded/cancelled), comment, handle_time, created_at | idx_approver_status(approver_id,task_status); idx_instance | +| 32 | flow_op_log | 流转日志 | id, instance_id, op_type(submit/approve/reject/forward/cancel/withdraw), operator_id, comment, created_at | idx_instance | + +### 4.4 hr-contract 合同(4 张,前缀 contract_) + +| # | 表 | 用途 | 关键字段 | 关键索引 | +|---|---|---|---|---| +| 33 | contract_type | 合同类型(F09 自定义) | id, type_code, type_name(劳动合同/保密协议/竞业协议…), status【审计】 | uk_type_code | +| 34 | contract_template | 合同模板(F09) | id, template_name, type_id, file_path, field_marks_json(占位符映射), status【审计】 | — | +| 35 | contract_info | 合同台账(F09) | id, contract_no, employee_id, type_id, company_id, template_id, start_date, end_date, sign_date, contract_status(active/expired/stopped/renewing), file_path, flow_instance_id, remind_rule_id, esign_status(预留), remark【审计】 | idx_employee; idx_end_date; idx_status | +| 36 | contract_remind_rule | 到期提醒规则(F09) | id, rule_name, days_before(int), target_role(self/leader/hr), content_template, status【审计】 | — | + +### 4.5 hr-system 权限日志与通用服务(7 张,前缀 sys_) + +| # | 表 | 用途 | 关键字段 | 关键索引 | +|---|---|---|---|---| +| 37 | sys_data_scope | 数据范围(F11) | id, admin_user_id(管理员), scope_type(org/field), org_ids_json(组织维度,含子树), field_ids_json(花名册字段维度), remark【审计】 | idx_admin_user | +| 38 | sys_audit_log | 操作日志(F12,只增不改) | id, module, target_type, target_id, operation(create/update/delete/import/export/approve/login), operator_id, operator_name, before_json, after_json, request_ip, created_at | idx_target(target_type,target_id); idx_operator; idx_created_at; idx_module_op(module,operation) | +| 39 | sys_message | 站内消息(F15) | id, receiver_id, msg_type(todo/approval/remind/care/notice), title, content, biz_type, biz_id, send_channel(site; sms/email预留), is_read, created_at | idx_receiver_read(receiver_id,is_read); idx_created_at | +| 40 | sys_remind_rule | 通用提醒规则(F12 场景) | id, scene_code(entry/regular/leave/retire/contract_expire/health_cert/social_insurance/custom), rule_name, days_before, content_template, target_role(admin/employee/leader), status【审计】 | uk(scene_code,rule_name) | +| 41 | sys_announcement | 企业公告(F15) | id, title, content, publish_scope_json, publish_time, status(draft/published/offline), created_by【审计】 | idx_status | +| 42 | sys_policy | 企业政策(F15) | id, title, file_path, view_scope_json, downloadable(0/1), publish_time, status, created_by【审计】 | idx_status | +| 43 | sys_care_config | 关怀配置(F15 生日/周年) | id, care_type(birthday/anniversary), template, enable(0/1), push_target(employee/leader), updated_by, updated_at | uk_care_type | + +### 4.6 核心表 DDL 示例(json2ddl 生成等价物) + +```sql +-- roster_employee(完整 DDL 见 §3 models JSON) +CREATE TABLE roster_employee ( + id VARCHAR(32) NOT NULL COMMENT '主键', + employee_no VARCHAR(32) NOT NULL COMMENT '工号', + name VARCHAR(64) NOT NULL COMMENT '姓名', + gender VARCHAR(16) DEFAULT NULL COMMENT '性别(字典GENDER)', + id_number_cipher VARCHAR(256) DEFAULT NULL COMMENT '证件号密文', + id_number_hash VARCHAR(64) DEFAULT NULL COMMENT '证件号哈希(唯一)', + birthday DATE DEFAULT NULL, + phone VARCHAR(20) DEFAULT NULL, + email VARCHAR(128) DEFAULT NULL, + org_id VARCHAR(32) DEFAULT NULL COMMENT '组织', + position_id VARCHAR(32) DEFAULT NULL COMMENT '职位', + job_id VARCHAR(32) DEFAULT NULL COMMENT '职务', + grade_level_id VARCHAR(32) DEFAULT NULL COMMENT '职级', + grade_rank_id VARCHAR(32) DEFAULT NULL COMMENT '职等', + sequence_id VARCHAR(32) DEFAULT NULL COMMENT '序列', + employee_type VARCHAR(16) DEFAULT NULL COMMENT '员工类型(字典EMP_TYPE)', + employee_status VARCHAR(16) DEFAULT NULL COMMENT '状态(字典EMP_STATUS)', + hire_date DATE DEFAULT NULL, + regular_date DATE DEFAULT NULL, + leave_date DATE DEFAULT NULL, + company_id VARCHAR(32) DEFAULT NULL COMMENT '合同公司', + work_location VARCHAR(128) DEFAULT NULL, + direct_leader_id VARCHAR(32) DEFAULT NULL COMMENT '直属主管', + remark TEXT DEFAULT NULL, + created_by VARCHAR(32) DEFAULT NULL, + updated_by VARCHAR(32) DEFAULT NULL, + created_at TIMESTAMP NULL DEFAULT NULL, + updated_at TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY uk_employee_no (employee_no), + UNIQUE KEY uk_id_number_hash (id_number_hash), + KEY idx_org_id (org_id), + KEY idx_status (employee_status), + KEY idx_hire_date (hire_date), + KEY idx_direct_leader (direct_leader_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='员工主档'; + +CREATE TABLE org_unit ( + id VARCHAR(32) NOT NULL, + org_code VARCHAR(32) NOT NULL COMMENT '组织编码', + org_name VARCHAR(128) NOT NULL COMMENT '组织名称', + parent_id VARCHAR(32) DEFAULT NULL COMMENT '上级组织', + org_type VARCHAR(16) DEFAULT NULL COMMENT '组织类型(字典ORG_TYPE)', + leader_id VARCHAR(32) DEFAULT NULL COMMENT '负责人', + effective_date DATE DEFAULT NULL COMMENT '生效日期', + expire_date DATE DEFAULT NULL COMMENT '失效日期(空=长期)', + status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', + sort_no INT DEFAULT 0, + remark TEXT DEFAULT NULL, + created_by VARCHAR(32) DEFAULT NULL, updated_by VARCHAR(32) DEFAULT NULL, + created_at TIMESTAMP NULL DEFAULT NULL, updated_at TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY uk_org_code (org_code), + KEY idx_parent_id (parent_id), + KEY idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='组织'; + +CREATE TABLE flow_instance ( + id VARCHAR(32) NOT NULL, + inst_no VARCHAR(32) NOT NULL COMMENT '审批编号', + flow_id VARCHAR(32) NOT NULL, form_id VARCHAR(32) NOT NULL, + biz_type VARCHAR(32) NOT NULL COMMENT '业务类型', biz_id VARCHAR(32) DEFAULT NULL COMMENT '业务单据ID', + title VARCHAR(256) DEFAULT NULL, + initiator_id VARCHAR(32) NOT NULL, + inst_status VARCHAR(16) NOT NULL DEFAULT 'running' COMMENT 'running/approved/rejected/cancelled', + submit_data_json TEXT DEFAULT NULL COMMENT '提交表单数据快照', + start_time TIMESTAMP NULL DEFAULT NULL, finish_time TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY uk_inst_no (inst_no), + KEY idx_biz (biz_type, biz_id), + KEY idx_initiator (initiator_id), + KEY idx_status (inst_status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='流程实例'; + +CREATE TABLE sys_audit_log ( + id VARCHAR(32) NOT NULL, + module VARCHAR(32) NOT NULL COMMENT 'hr-org/hr-roster/...', + target_type VARCHAR(32) NOT NULL COMMENT 'roster_employee/org_unit/...', + target_id VARCHAR(32) NOT NULL, + operation VARCHAR(16) NOT NULL COMMENT 'create/update/delete/import/export/approve/login', + operator_id VARCHAR(32) NOT NULL, operator_name VARCHAR(64) DEFAULT '', + before_json TEXT DEFAULT NULL COMMENT '变更前快照', + after_json TEXT DEFAULT NULL COMMENT '变更后快照', + request_ip VARCHAR(64) DEFAULT NULL, + created_at TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (id), + KEY idx_target (target_type, target_id), + KEY idx_operator (operator_id), + KEY idx_created_at (created_at), + KEY idx_module_op (module, operation) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志(只增)'; +``` + +## 5. 索引与性能策略 + +1. 100 人规模全表扫描亦可满足 ≤500ms,但仍按查询模式建索引:列表筛选列(status/org_id/hire_date/end_date)、EAV 值表 uk(employee_id,field_id)、待办 idx(approver_id,task_status)。 +2. 组织树、职位职级主数据一次性全量加载(≤200/≤500 行),前端缓存,无需分页。 +3. EAV 查询模式:花名册列表先按主表条件分页取员工,再批量 `IN` 查值表拼装(每页 ≤50 人 × 显示字段数),避免 EAV 行转列大 JOIN。 +4. 报表(hr-report)直接 SQL 聚合(sor.sqlExe 只读),100 人规模不建物化视图;sys_audit_log 按月保留,冷数据归档不删除。 +5. 唯一性:工号、组织编码、职位/职务/职级/职等编码、审批编号均唯一索引;证件号经哈希列唯一(加密为非确定性,哈希列承担唯一与黑名单匹配)。 + +## 6. 数据字典(appbase appcodes,init/data.json 初始化) + +| code | 值 | 说明 | +|---|---|---| +| GENDER | male/female/unknown | 性别 | +| ORG_TYPE | group/subsidiary/dept/team | 组织类型 | +| EMP_TYPE | formal/temp/dispatch/intern | 员工类型(正式/临时/派遣/实习) | +| EMP_STATUS | pending_entry/probation/regular/pending_leave/left | 员工状态(待入职/试用/正式/待离职/离职) | +| POS_CATEGORY | management/professional/skill | 职位类别 | +| TRANSFER_TYPE | promotion/demotion/position_change/org_adjust | 调动类型 | +| LEAVE_REASON | personal/company/contract_expire/retire/other | 离职原因 | +| CONTRACT_STATUS | active/expired/stopped/renewing | 合同状态 | +| FLOW_BIZ_TYPE | entry/regular/transfer/leave/handover/concurrent/contract_sign/contract_renew/contract_change/contract_stop/roster_self_edit | 审批业务类型 | +| INST_STATUS | running/approved/rejected/cancelled | 实例状态 | +| REMIND_SCENE | entry/regular/leave/retire/contract_expire/health_cert/social_insurance/custom | 提醒场景 | +| AUDIT_OP | create/update/delete/import/export/approve/login | 操作类型 | + +枚举一律不硬编码于 dspy;CRUD 下拉经 models `codes` 段引用。 + +## 7. staff-mgr 数据迁移策略(v1 → 迭代1) + +迁移工具:`repos/hr-system` 仓内规划 `scripts/migrate_staff_mgr.py`(Python + sqlor,幂等可重跑,输出核对报告)。 + +| v1 源表(staff-mgr) | 目标表 | 映射规则 | +|---|---|---| +| staff_department_cache | org_unit | 按树形重建 parent_id;org_code=DEPT{id};status 映射 active/inactive | +| staff_employee | roster_employee | employee_no/name/gender/phone/email 直映;id_number AES 解密后按新方案重加密(cipher+hash);department_id→org_id;position 文本→预置 org_position(无匹配则建"未定职");status: active→regular、probation→probation、inactive→left;hire_date 直映 | +| staff_employee_extra | roster_field_value + contract_info | education/major/school/graduation_date/previous_company/work_years → 预置 roster_field_def 字段值;technical_level/salary_grade → 预置敏感字段值;contract_type/start/end → contract_info(type_id 映射正式/外包/实习协议) | +| staff_change_log | roster_timeline | change_type→event_type(transfer/field_change),old/new 值入 content_json,event_type 前缀 `migrate:` 标识迁移来源 | +| staff_audit_log | sys_audit_log | 字段直映,module 标记 `staff-mgr-legacy` | + +策略与约束: +1. **顺序**:org_unit → org_position(预置)→ roster_field_def/group(预置)→ roster_employee → roster_field_value → contract_info → timeline/audit。 +2. **幂等**:按 employee_no/org_code 去重,重跑仅补差;证件号哈希冲突时输出冲突报告人工裁决(对 baseline-decision Q6:冲突员工按离职记录保留,不入在职)。 +3. **切换**:迭代1 UAT 通过后一次性迁移+双库比对 → staff-mgr 服务下线、仓库冻结只读(保留一个迭代周期)。 +4. 迁移全程写 sys_audit_log(operation=migrate),迁移数据在时间轴/日志中可辨识。 + +## 8. 与需求验收项的映射(摘选) + +| 验收项(function-detail) | 数据支撑 | +|---|---| +| F01-4 时间轴留痕 | org_unit_change | +| F03-1/2 自定义字段与分组 | roster_field_def/group/value | +| F03-3 多规则工号 | roster_empno_rule | +| F03-4 自助修改审核 | roster_field_def.editable_self/need_audit + flow biz_type=roster_self_edit | +| F03-6 类型差异规则 | roster_type_rule + apply_types | +| F04-4 黑名单拦截 | org_blacklist(id_number_hash 匹配) | +| F07-5 离职证明 | org_leave.certificate_file(files/ 存储) | +| F09-6 电子签预留 | contract_info.esign_status | +| F10-2 字段权限 | flow_node_def.field_perm_json | +| F11-2 双维度数据范围 | sys_data_scope(scope_type=org/field) | +| F12-3 前后对比 | sys_audit_log.before_json/after_json | +| F15-4 多场景提醒 | sys_remind_rule(scene_code) | diff --git a/docs/01-design/feature-list.md b/docs/01-design/feature-list.md new file mode 100644 index 0000000..b51f58f --- /dev/null +++ b/docs/01-design/feature-list.md @@ -0,0 +1,67 @@ +# 迭代1功能清单(F01~F15,ocai 口径) + +- 版本:v2.0(替换原 299B 占位文件;占位文件内容为 v1 Java 口径描述,已废弃) +- 需求基线:`docs/00-requirement/requirement-spec.md`(SRS v2)+ `docs/00-requirement/iteration1-function-detail.md` +- 应用:hr-web(`apps/hr-web.md`);模块定义:`modules/hr-*.md` + +## 0. 范围与角色 + +迭代1 = 组织人事底座,规模 100 人账号。技术口径统一 ocai:前端 bricks + dspy 声明式页面,后端 ahserver(Python),数据层 apppublic/sqlor。 + +| 角色 | 代码 | 主要能力 | +|---|---|---| +| 系统管理员 | admin | 全部数据与配置、角色/管理员/数据范围、操作日志 | +| 人事 | hr | 组织、花名册、入转调离、合同、流程配置、报表 | +| 部门经理 | manager | 数据范围内入转调离审批、团队统计、关怀提醒 | +| 员工(自助) | employee | 个人档案、发起审批、待办、企业政策/公告 | + +脱敏基线:身份证号全角色脱敏(前3后3);手机号前3后4;薪资/职级敏感字段仅 admin/hr 可见(由 roster_field_def.sensitive 驱动)。 + +## 1. 功能清单(F01~F15,共 81 条验收项) + +| # | 功能 | 承载模块 | 表前缀 | 验收项数 | 关键交付 | 范围边界 | +|---|---|---|---|---|---|---| +| F01 | 组织架构 | hr-org | org_ | 6 | 组织树/架构图(含 as_of 历史)/新建变更停用移动/字段自定义/时间轴/Excel 导入 | 编制管理、项目式组织范围外 | +| F02 | 职位职级体系 | hr-org | org_ | 5 | 职位/职务/职级/职等/序列 CRUD + 导入导出 + options | 全量 | +| F03 | 花名册 | hr-roster | roster_ | 8 | 自定义字段(EAV)/分组/工号多规则/自助修改+审核/时间轴/类型规则/搜索/导入导出 | 附件预览依赖 files/ | +| F04 | 入职管理 | hr-org | org_ | 7 | 审批入职/手动批量入职/登记表邀请/黑名单拦截/入职通知/复职 | 扫码入职、身份证读取为降级项 | +| F05 | 转正管理 | hr-org | org_ | 4 | 审批/手动转正、回写花名册、转正提醒 | 全量 | +| F06 | 调动管理 | hr-org | org_ | 4 | 调动查询/审批(晋升/降级/调岗/组织调整)/批量调动 | 全量 | +| F07 | 离职管理 | hr-org | org_ | 7 | 审批/手动离职、交接、离职证明、黑名单、信息存储 | 钉钉资源交接置后 | +| F08 | 兼岗管理 | hr-org | org_ | 3 | 一人多兼岗记录、兼岗审批、通过自动同步 | 全量 | +| F09 | 合同台账 | hr-contract | contract_ | 6 | 台账/类型自定义/模板/审批(新签续签变更终止)/到期提醒 | 电子签置后(esign_stub 预留) | +| F10 | 流程审批 | hr-flow | flow_ | 7 | 表单/流程/节点配置、审批角色、流转引擎、查询导出、打印 | 考勤/薪酬/组合审批置后 | +| F11 | 权限管理 | hr-system | sys_ | 4 | 管理角色、人员范围(组织维度+花名册字段维度)、管理员管理 | 全量 | +| F12 | 操作日志 | hr-system | sys_ | 4 | 全量写操作留痕、前后对比、时间/类型查询 | 全量 | +| F13 | 人事报表 | hr-report | —(只读) | 6 | 花名册/入职/转正/调岗/离职五类分析,数据范围受控 | 全量 | +| F14 | 工作台 | hr-system | sys_ | 5 | 员工/经理/管理员三工作台聚合 | 绩效/考勤统计预留占位 | +| F15 | 员工服务与提醒 | hr-system | sys_ | 5 | 生日周年关怀、政策、公告、多场景到期提醒 | 站内消息优先,短信/邮件预留 | + +合计:**81 条可验收项**(逐项输入/处理/输出见 `iteration1-function-detail.md`)。 + +## 2. 功能 → 模块 → 数据表落点 + +| 模块 | 功能 | 主要数据表 | +|---|---|---| +| hr-org | F01/F02/F04/F05/F06/F07/F08 | org_unit, org_unit_change, org_field_def/value, org_job, org_position, org_sequence, org_grade_level, org_grade_rank, org_blacklist, org_contract_company, org_entry, org_regularization, org_transfer(+detail), org_leave(+handover), org_concurrent_post(18 张) | +| hr-roster | F03 | roster_field_group, roster_field_def, roster_employee, roster_field_value, roster_empno_rule, roster_timeline, roster_type_rule(7 张) | +| hr-flow | F10 | flow_form_def, flow_def, flow_node_def, flow_role, flow_instance, flow_task, flow_op_log(7 张) | +| hr-contract | F09 | contract_type, contract_template, contract_info, contract_remind_rule(4 张) | +| hr-report | F13 | 无自有表,只读聚合 org_/roster_/flow_ | +| hr-system | F11/F12/F14/F15 | sys_data_scope, sys_audit_log, sys_message, sys_remind_rule, sys_announcement, sys_policy, sys_care_config(7 张) | + +共 43 张业务表,详见 `database-design.md`。 + +## 3. 设计文档索引 + +| 文档 | 内容 | +|---|---| +| architecture.md | 系统架构、技术选型、模块划分与依赖、hr-system/staff-mgr 职责边界、部署、安全、非功能 | +| database-design.md | ER、43 表结构、索引、数据字典、models JSON、staff-mgr 迁移 | +| api-design.md | dspy 端点清单、通用约定、鉴权、错误码、典型调用链、v1 接口替代 | +| ui-design.md | 布局、路由表、页面组件树、核心交互流程、设计规范、页面-接口追溯 | +| iteration1-task-breakdown.md | 技术可行性、风险、开发任务拆解(T01~T24,约 84 人日) | + +## 4. 迭代1范围外(既定) + +编制管理、项目式组织、钉钉同步、考勤流程、薪酬流程、组合审批、电子签、短信/邮件通道、浏览器插件——列为后续迭代/集成迭代,本期仅预留字段或桩接口。 diff --git a/docs/01-design/iteration1-task-breakdown.md b/docs/01-design/iteration1-task-breakdown.md new file mode 100644 index 0000000..e5c0efb --- /dev/null +++ b/docs/01-design/iteration1-task-breakdown.md @@ -0,0 +1,99 @@ +# 迭代1总体设计 —— 技术可行性与开发任务拆解(hr-web) + +- 版本:v1.0(迭代1-总体设计配套文档) +- 状态:提交审核 +- 基线:`docs/01-design/architecture.md`(架构)+ `database-design.md`(43 表)+ `api-design.md`(端点清单)+ `ui-design.md`(页面结构) +- 需求基线:`docs/00-requirement/requirement-spec.md`(SRS v2)+ `iteration1-function-detail.md`(F01~F15,81 条验收项) + +## 1. 技术可行性说明 + +### 1.1 技术栈成熟度(ocai 规范) + +| 能力诉求 | ocai 设施 | 成熟度结论 | +|---|---|---| +| 声明式 CRUD 页面 | json/*.json + xls2ui 自动生成 DataViewer/Form/Tree | 成熟(产线既有模式);迭代1约 20 个 CRUD 页面零手写 | +| 组织树/架构图 | Tree widget + org_unit parent_id 自引用 + as_of 历史查询 | 可行;历史架构靠 org_unit_change 时间轴回放/有效期区间过滤 | +| 自定义字段(花名册/组织) | EAV 双表 + field_def 元数据驱动表单渲染 | 可行;列表页采用"主表分页+值表批量拼装"规避 EAV 性能问题 | +| 审批引擎 | flow_def/node_def JSON 配置 + flow_instance/task 状态机 | 可行;迭代1仅串行节点 + any/all 通过规则,不做并行分支(满足 F10 验收) | +| 审批通过自动回写 | biz_type+biz_id 关联 + ServerEnv 注册回调 hook | 可行;模块宿主无关原则下经 load_xxx() 注册函数互调 | +| 批量导入导出 | ahserver 后台任务 + openpyxl + files/ 结果文件 | 可行;100 人量级同步/准同步处理即可 | +| 数据范围权限 | rbac 路径级 + sys_data_scope(组织/字段双维度)查询叠加 | 可行;复用 rbac-permission-initialization-pattern | +| 脱敏/审计 | roster_field_def.sensitive + sys_audit_log 前后 JSON | 可行;替代 staff-mgr 硬编码 MaskUtil | +| 图表报表 | bricks Chart widgets(bricks-chart-widgets 技能) | 可行;聚合 SQL 只读查询 | +| 提醒推送 | cron 扫描 remind_scan + sys_message 站内消息 | 可行;短信/邮件通道预留 send_channel 字段 | + +### 1.2 规模与性能 + +100 人账号、单实例部署(nginx + ahserver + MySQL + Redis)。最大表量级:花名册 100 行、字段值 ≤100×100=1 万行、审计日志年级 ≤10 万行。全部查询在索引覆盖下远低于 500ms 指标;组织树/主数据全量加载无分页压力。导入导出 100 人 × 50 字段 openpyxl 秒级完成。 + +### 1.3 主要风险与对策 + +| 风险 | 等级 | 对策 | +|---|---|---| +| EAV 自定义字段在列表页的筛选/排序复杂度 | 中 | 迭代1筛选支持"主表字段 + 至多 3 个自定义字段等值匹配",排序仅主表字段;超出部分作为已知限制写入 UAT 说明 | +| 审批引擎配置化过度导致返工 | 中 | 迭代1锁定"串行节点、any/all、字段权限、抄送"能力边界;并行/条件分支留 flow_node_def JSON 扩展位 | +| staff-mgr 旧数据语义差异(status/加密算法) | 中 | 迁移脚本内置映射表 + 核对报告 + UAT 双库比对(见 database-design.md §7) | +| 6 模块并行开发契约漂移 | 中 | 本文 T01 先行冻结表定义 models JSON 与 api-design 端点签名,变更走设计评审 | +| 提醒场景字段依赖(健康证/社保等花名册字段未建) | 低 | init/data.json 预置 REMIND_SCENE 对应字段定义,remind_scan 按 field_def 取数 | + +### 1.4 已裁决口径(对 baseline-decision 遗留问题) + +- Q1 双口径:统一 ocai(本设计全套)。 +- Q6 删除语义:迭代1员工/组织不做物理删除与逻辑删除标记,统一走停用/离职流程(database-design.md §1.3、api-design.md §4)。 +- 其余 Q2~Q5/Q7 以本设计为评审结论:自定义字段排序限主表字段(1.3)、审批引擎能力边界(1.3)、迁移幂等策略(db §7)。 + +## 2. 开发任务拆解(T01~T24,契约先行) + +> 依赖关系:T01~T02 为契约冻结阶段,全量先行;其后按模块并行。工作量单位:人日(估算,供 PM 排期)。 + +### 阶段0 契约与脚手架 +| 编号 | 任务 | 内容/产出 | 依赖 | 估时 | +|---|---|---|---|---| +| T01 | 数据契约冻结 | 6 模块仓库建仓(hr_org/hr_roster/hr_flow/hr_contract/hr_report,hr-system 复用既有空仓);43 张 models/*.json 全量提交;json2ddl 生成 DDL 验证 | — | 4 | +| T02 | 应用脚手架 | hr-web 应用仓(app/hr_web.py、conf/config.json 含 processors/indexes/session、build.sh、.env);appbase/rbac 加载验证;登录走通 | T01 | 2 | + +### 阶段1 主数据与底座(可并行) +| 编号 | 任务 | 内容/产出 | 依赖 | 估时 | +|---|---|---|---|---| +| T03 | hr-org 组织管理 | org_unit CRUD/树/停用/移动、org_field_def 自定义字段、org_unit_change 时间轴、org_tree/org_import 端点、org_tree.ui/org_chart.ui(F01) | T01,T02 | 5 | +| T04 | hr-org 职位职级 | org_job/position/sequence/grade_level/grade_rank CRUD + 导入导出 + options 端点(F02) | T03 | 3 | +| T05 | hr-roster 字段体系 | roster_field_group/field_def/type_rule/empno_rule 配置页与端点、工号生成器(F03 搭建类验收 1/2/3/6) | T01,T02 | 4 | +| T06 | hr-roster 花名册主体 | roster_employee CRUD、EAV 值表读写、roster_list/employee_detail/timeline、脱敏与字段可见(F03 验收 4/5/7) | T05,T03,T04 | 6 | +| T07 | hr-roster 导入导出 | roster_import(新增/修改)、模板生成、roster_export(字段/顺序/as_of)(F03 验收 8) | T06 | 3 | +| T08 | hr-system 权限底座 | 角色/管理员/数据范围(sys_data_scope 双维度)、get_data_scope 注册、各模块查询叠加(F11) | T02 | 4 | +| T09 | hr-system 审计底座 | write_audit_log + sys_audit_log 查询/详情对比页(F12) | T02 | 2 | + +### 阶段2 审批引擎(关键路径) +| 编号 | 任务 | 内容/产出 | 依赖 | 估时 | +|---|---|---|---|---| +| T10 | hr-flow 引擎核心 | flow_form_def/flow_def/flow_node_def/flow_role 配置、flow_start 状态机、task 生成与流转、flow_match、回调 hook 机制(F10 验收 1/2/3) | T02,T08 | 6 | +| T11 | hr-flow 审批界面 | todo/done/mine/received 列表、inst_detail 动态表单渲染、approve/reject/forward/withdraw、打印(F10 验收 5/6) | T10 | 4 | +| T12 | hr-flow 查询导出 | inst_query/inst_export、审批角色数据范围生效验证(F10 验收 3/5) | T10,T08 | 2 | + +### 阶段3 入转调离与合同(依赖 T10 回调,可部分并行) +| 编号 | 任务 | 内容/产出 | 依赖 | 估时 | +|---|---|---|---|---| +| T13 | 入职管理 | entry_approval/entry_manual(批量)/登记表邀请与提交/黑名单校验与高亮/入职通知/复职关联(F04 全 7 项) | T10,T06 | 5 | +| T14 | 转正管理 | regular_apply(自助/代发)/regular_manual/回写花名册/转正提醒接入(F05 全 4 项) | T10,T06,T16 | 3 | +| T15 | 调动管理 | transfer_apply(含批量明细)/transfer_cancel/回写档案与花名册/调动查询(F06 全 4 项) | T10,T06 | 4 | +| T16 | 提醒引擎 | sys_remind_rule/care_config/remind_scan(转正/合同/生日/周年等场景)+ sys_message(F15 提醒类验收) | T02 | 3 | +| T17 | 离职管理 | leave_apply/leave_manual/交接项/办理离职/离职证明生成下载/一键黑名单/信息存储(F07 全 7 项,钉钉交接留扩展点) | T10,T06 | 5 | +| T18 | 兼岗管理 | concurrent_apply/兼岗记录维护/审批通过同步花名册(F08 全 3 项) | T10,T06 | 2 | +| T19 | 合同台账 | contract_type/template/info CRUD + 批量导入 + 合同审批(新签/续签/变更/终止)+ 到期提醒规则 + esign_stub 预留(F09 全 6 项) | T10,T06,T16 | 4 | + +### 阶段4 报表、工作台、员工服务与收尾 +| 编号 | 任务 | 内容/产出 | 依赖 | 估时 | +|---|---|---|---|---| +| T20 | 人事报表 | roster/entry/regular/transfer/leave 五类分析端点 + report_board.ui 图表(F13 全 6 项,数据范围受控) | T06,T13~T17 | 4 | +| T21 | 工作台 | workbench_employee/manager/admin 聚合端点与三页面(F14 全 5 项,绩效/考勤占位预留) | T10,T11,T16 | 3 | +| T22 | 员工服务 | 公告/政策发布与查询(查阅范围/下载权限)、关怀文案配置(F15 服务类验收 1~3) | T16 | 2 | +| T23 | staff-mgr 迁移 | migrate_staff_mgr.py(映射/解密重加密/幂等/核对报告)、UAT 双库比对、切换演练 | T06,T09 | 3 | +| T24 | 集成联调与验收 | F01~F15 共 81 条验收项端到端回归;性能验证(列表 ≤500ms);load_path 全路径注册核查;部署脚本验证(dev/test) | 全部 | 4 | + +**合计估算:约 84 人日**(不含 PM 排期缓冲)。关键路径:T01→T02→T10→T11→T13/T15/T17→T20/T21→T24。 + +## 3. 交付与验收定义 + +- 每个 T 任务交付:模块仓代码(models/json/wwwroot/init/scripts/skill/SKILL.md)+ 对应功能验收项自测记录。 +- 契约变更(表结构/端点签名)必须回改 docs/01-design 四份文档并评审。 +- T24 通过标准:81 条验收项全部通过或经 PM 确认降级项(扫码入职、身份证读取、钉钉交接、电子签为既定范围外/降级项)。 diff --git a/docs/01-design/ui-design.md b/docs/01-design/ui-design.md new file mode 100644 index 0000000..35f0286 --- /dev/null +++ b/docs/01-design/ui-design.md @@ -0,0 +1,237 @@ +# 迭代1总体设计 —— UI/页面设计(hr-web,ocai 口径) + +- 版本:v2.0(迭代1-总体设计,取代 v1 Vue3/Element Plus 口径,v1 已归档至 `docs/_archive/01-design-v1-old/ui-design.md`) +- 状态:提交审核 +- 规范依据:ocai 技能集 bricks-framework、bricks-layout-patterns、module-development-spec(index.ui 强制)、crud-definition-spec;交互基线 `docs/01-design/architecture.md` + +## 1. 界面体系与总体布局 + +1. **技术形态**:无 Vue/无手写 HTML。页面 = `wwwroot/*.ui`(纯 JSON bricks 组件树)+ `*.dspy`(数据端点);CRUD 列表/表单页由 json/*.json 经 xls2ui 自动生成 DataViewer/Form/Tree 页面。 +2. **入口**:`/index.ui`(应用门户,菜单聚合 6 模块入口);每模块强制 `/{module}/index.ui`(ResponsableBox 功能卡片导航)。 +3. **权限渲染**:菜单与按钮可见性由 rbac 角色控制(Menu 只注册已授权路径;操作按钮 binds 前按角色渲染)。 +4. **核心 widgets**:VBox/HBox、ResponsableBox(自适应,员工自助移动端兼容)、Menu、DataViewer(列表:data_filter 筛选/toolbar binds/子表 subtables)、Tree(组织树)、Form、PopupWindow、Chart(报表)、Text、FileUpload/FilePreview、UrlWidget。 +5. **binds actiontype 仅 5 种**:urlwidget / script / url / datawidget / event(禁止 script 内 fetch;弹窗走 PopupWindow + urlwidget)。 +6. **URL 规则**:.ui 内全部 url 使用 `{{entire_url('/module/xxx.ui')}}` 绝对路径;json/ 内引用别名用 `{{entire_url('../alias')}}`。 + +### 1.1 应用门户 /index.ui + +``` +index.ui (VBox, height:100%) +├── Header(HBox): Text「Web版人事系统」+ 用户信息 + [消息铃铛(message_list 未读数)] +├── 内容区(HBox, flex:1) +│ ├── Menu(id:app.menu, width:220px) +│ │ ├── 工作台 → /hrsystem/workbench_*.ui(按角色路由) +│ │ ├── 组织管理 → /hrorg/index.ui +│ │ ├── 花名册 → /hrroster/index.ui +│ │ ├── 审批中心 → /hrflow/index.ui +│ │ ├── 合同管理 → /hrcontract/index.ui +│ │ ├── 人事报表 → /hrreport/index.ui +│ │ ├── 员工服务 → /hrsystem/service.ui(公告/政策) +│ │ └── 系统管理 → /hrsystem/index.ui(角色/范围/管理员/日志) +│ └── VBox(id:app.content, flex:1) ← Menu items url 统一加载到此 +└── 说明:Menu 不加 binds(内部处理点击);内容区置于 sidebar 之前(DOM 顺序) +``` + +## 2. 路由表(wwwroot 自动路由) + +| URL | 页面 | 说明 | 角色 | +|---|---|---|---| +| /index.ui | 应用门户 | 全局导航 | L | +| /hrorg/index.ui | 组织模块入口 | 卡片:组织树/架构图/时间轴/职位职级/入转调离工作台/黑名单 | L | +| /hrorg/org_tree.ui | 组织管理 | Tree + 详情表单 + 变更时间轴 | L | +| /hrorg/org_chart.ui | 组织架构图 | 层级展开/as_of 历史/导出 | A,H | +| /hrorg/position_list.ui 等 | 职位/职务/职级/职等/序列 CRUD | xls2ui 生成 DataViewer | A,H | +| /hrorg/entry_workbench.ui | 入职工作台 | 待入职/审批中/黑名单高亮 | A,H | +| /hrorg/transfer_list.ui | 调动查询 | 待确定/已确定/已取消筛选 | A,H,M | +| /hrorg/leave_workbench.ui | 离职工作台 | 待离职名单/交接/证明 | A,H,M | +| /hrroster/index.ui | 花名册入口 | 卡片:花名册/字段配置/工号规则/导入导出 | A,H | +| /hrroster/roster_list.ui | 花名册列表 | DataViewer + data_filter + 自定义列 | A,H,M(团队) | +| /hrroster/employee_detail.ui | 员工档案 | Tabs 分组 + 时间轴 | L(按范围) | +| /hrroster/field_config.ui | 字段/分组/类型规则配置 | 拖拽排序 | A,H | +| /hrflow/index.ui | 审批中心入口 | 待办/已办/我发起/我收到/流程配置 | L | +| /hrflow/todo_list.ui | 待办列表 | DataViewer,行内审批 | L | +| /hrflow/inst_detail.ui | 审批单 | 表单渲染 + 流转记录 + 操作按钮 | 参与者 | +| /hrflow/flow_design.ui | 流程/表单/节点/审批角色配置 | A,H/A | A,H | +| /hrcontract/index.ui | 合同入口 | 台账/类型/模板/提醒规则 | A,H | +| /hrcontract/contract_list.ui | 合同台账 | DataViewer + 到期高亮 | A,H | +| /hrreport/index.ui | 报表看板 | 五类分析卡片 | A,H,M | +| /hrreport/report_board.ui | 看板页 | Chart 组件 | A,H,M | +| /hrsystem/index.ui | 系统管理入口 | 角色/管理员/数据范围/日志/提醒配置 | A | +| /hrsystem/workbench_employee.ui | 员工工作台 | 个人档案/发起审批/待办 | E | +| /hrsystem/workbench_manager.ui | 经理工作台 | 团队统计/入转调离审批/关怀 | M | +| /hrsystem/workbench_admin.ui | 管理员工作台 | 人事统计/合同/提醒 | A,H | +| /hrsystem/audit_log_list.ui | 操作日志 | DataViewer + 详情对比弹窗 | A | +| /hrsystem/service.ui | 员工服务 | 公告/政策查询预览 | L | +| /hrsystem/message_list.ui | 站内消息 | 未读/已读 | L | + +## 3. 关键页面结构与组件树 + +### 3.1 组织管理 /hrorg/org_tree.ui(F01) + +``` +org_tree.ui (HBox) +├── 左侧 VBox(width:320px) +│ ├── 搜索行(HBox): Input(keyword) + Button[搜索](binds script → 触发 Tree 刷新) +│ ├── Tree(id:org_tree, dataurl=/hrorg/api/org_tree.dspy, 点击节点→右侧详情) +│ └── 工具按钮行: [新增子组织][新增同级](PopupWindow → org_unit_form.dspy) [导入](FileUpload→org_import.dspy) +└── 右侧 VBox(flex:1) + ├── 组织详情 Form(id:org_detail, dataurl=/hrorg/api/org_unit_detail.dspy?id=..) + │ 字段: org_code/org_name/org_type(codes:ORG_TYPE)/leader_id(dataurl:employee_options)/effective_date/自定义字段(动态渲染 org_field_def) + ├── 操作按钮行: [编辑][移动(PopupWindow)][停用(二次确认)] ← A/H 角色可见 + └── 变更时间轴 VBox(id:org_timeline, dataurl=/hrorg/api/org_change_timeline.dspy) + 每条: Text(时间+操作人+类型) + before/after 对比展开 +``` +交互:Tree 节点点击 → urlwidget 刷新 org_detail 与 org_timeline(params_mapping 传 id);停用前弹确认 PopupWindow;停用后该组织在入职/调动表单 options 中不可选(服务端过滤 status=active)。 + +### 3.2 组织架构图 /hrorg/org_chart.ui(F01) + +``` +org_chart.ui (VBox) +├── 工具行(HBox): DatePicker(as_of 历史日期) + TreeSelect(根节点) + 显示内容多选(姓名/职位/负责人) + Button[查看][导出PNG][导出XMind] +└── Chart/Tree 容器(id:chart_box, dataurl=/hrorg/api/org_tree.dspy?as_of=..&root_id=..) +``` +交互:as_of 变更后重查;导出经 PopupWindow 提示后浏览器下载(org_chart_export.dspy 返回文件)。 + +### 3.3 花名册列表 /hrroster/roster_list.ui(F03,CRUD 生成) + +``` +roster_list.ui = DataViewer(json/roster_employee_list.json 生成) +├── data_filter: keyword(姓名/工号 LIKE) + org_id(TreeSelect:org_options) + employee_status(codes) + employee_type(codes) + 自定义字段筛选(动态追加) +├── toolbar binds: +│ ├── [新增员工] → PopupWindow → roster_employee_create.dspy +│ ├── [导入] → PopupWindow: 模板下载链接 + FileUpload(roster_import.dspy) + 结果文件下载 +│ ├── [导出] → PopupWindow: 字段多选(拖拽排序) + as_of 日期 → roster_export.dspy +│ └── [字段配置] → url 跳转 field_config.ui(A/H) +├── 列: 工号/姓名(点击→employee_detail.ui?id=)/组织/职位/员工类型/状态/入职日期 + 自定义显示列 +└── 行操作: [详情][发起转正][发起调动][办理离职](按角色与员工状态显隐) +``` + +### 3.4 员工档案 /hrroster/employee_detail.ui(F03) + +``` +employee_detail.ui (VBox) +├── 头部卡片(HBox): 头像 + 姓名/工号/状态标签 + 快捷操作[编辑][发起审批](PopupWindow 选择 biz_type) +├── Tabs(id:profile_tabs) +│ ├── Tab 分组字段(按 roster_field_group 动态生成): Form 只读/可编辑(按 editable_self+角色) +│ ├── Tab 时间轴(id:timeline, dataurl=timeline.dspy, 垂直时间线) + [添加记录](A/H) +│ ├── Tab 兼岗记录(DataViewer subtables: org_concurrent_post by employee_id) +│ ├── Tab 合同(DataViewer subtables: contract_info by employee_id) +│ └── Tab 审批记录(dataurl=inst_mine.dspy?about=..) +└── 附件: 字段类型=file → FileUpload + FilePreview(file_preview_url.dspy) +``` +交互:自助修改——employee 角色仅看到 editable_self=1 字段可编辑;提交时若字段 need_audit=1,服务端走 roster_self_edit 审批流,页面提示"已提交审核";否则直接生效。 + +### 3.5 入转调离工作台(F04~F07) + +``` +entry_workbench.ui (VBox) +├── 状态卡片行(ResponsableBox): 待入职数/审批中数/本月入职数(dataurl=workbench_transfer.dspy) +├── 待入职列表 DataViewer(org_entry by entry_status=pending_entry) +│ ├── 黑名单命中行: 高亮样式(confidential_fields/行样式) + [拦截原因] +│ └── 行操作: [邀请填登记表][发送入职通知][直接入花名册] +└── 工具行: [手动入职(批量 PopupWindow)][发起入职审批] + +transfer_list.ui: DataViewer(org_transfer) + data_filter(status=pending/confirmed/cancelled, transfer_type, effective_date) + 行操作: [查看明细(org_transfer_detail subtable)][取消](pending 状态) + +leave_workbench.ui (VBox) +├── 待离职名单 DataViewer(org_leave by status=pending_leave) +│ 行操作: [交接管理(PopupWindow: org_leave_handover 编辑)][办理离职][开具证明][加入黑名单(确认弹窗)] +└── 已离职列表 DataViewer(status=left) + [离职证明下载] +``` + +### 3.6 审批中心(F10) + +``` +todo_list.ui = DataViewer(dataurl=task_todo.dspy) + 列: 审批编号/标题/发起人/发起时间/当前节点 行操作:[审批]→ inst_detail.ui?instance_id= + +inst_detail.ui (VBox) +├── 表单渲染区(id:form_box, dataurl=inst_detail.dspy) —— 按 flow_form_def 动态渲染,节点字段权限控制可编辑性 +├── 流转记录 VBox: 节点链(提交→各审批人意见/时间) +└── 操作行(binds urlwidget POST): [同意(task_approve.dspy)][驳回(task_reject.dspy)][转交(PopupWindow 选人)][撤回(发起人)][打印(inst_print.dspy)] + 操作完成后 script 刷新页面 → 列表刷新 + +flow_design.ui (A/H): 三区块 +├── 表单定义 DataViewer(flow_form_def) + 字段引用器(勾选 roster_field_def) +├── 流程定义 DataViewer(flow_def) + 节点编辑 PopupWindow(审批人类型/通过规则/字段权限) +└── 审批角色 DataViewer(flow_role, 仅 admin) +``` + +### 3.7 报表看板 /hrreport/report_board.ui(F13) + +``` +report_board.ui (VBox) +├── 顶部 Tab: 花名册分析 | 入职 | 转正 | 调岗 | 离职 +├── 花名册分析 Tab: 维度选择器(codes: type/status/age/edu/location/gender + 自定义字段) + Chart(饼图/柱状, dataurl=roster_analysis.dspy) + 明细 DataViewer +├── 入职 Tab: 维度(部门/地区/岗位) + 周期选择 + Chart(趋势折线 + 分布柱) +├── 转正 Tab: Chart(趋势) + 近期待转正 DataViewer(regular_analysis.dspy) +├── 调岗 Tab: 日期范围 + Chart(按类型柱状) +└── 离职 Tab: 卡片(待离职人数/离职率/同比/环比) + Chart(离职原因饼图) +``` +所有看板查询服务端叠加数据范围;manager 仅见团队。 + +### 3.8 系统管理(F11/F12/F15) + +``` +index.ui(hrsystem): 卡片导航 → role_admin.ui / data_scope.ui / audit_log_list.ui / remind_config.ui / service.ui +role_admin.ui: DataViewer(角色) + 权限树勾选 PopupWindow(rbac paths) +data_scope.ui: 管理员列表 + 范围编辑 PopupWindow(scope_type 切换: 组织 TreeSelect 多选 / 花名册字段多选) +audit_log_list.ui: DataViewer(module/operation/date_range 筛选) + 行[详情] → PopupWindow 前后 JSON 对比(左右双栏 Text) +remind_config.ui: DataViewer(sys_remind_rule) + DataViewer(sys_care_config) +service.ui: Tabs[公告 DataViewer(sys_announcement)][政策 DataViewer(sys_policy, 行内预览/下载按权限)] +message_list.ui: DataViewer(msg_type/is_read 筛选) 行点击标已读 +``` + +### 3.9 工作台(F14) + +``` +workbench_employee.ui (ResponsableBox) +├── 卡片: 个人档案(→employee_detail.ui?id=self) | 发起审批(PopupWindow 选择流程类型→flow_start) +├── 待办/已办/我发起/我收到 四 Tab DataViewer(task_todo/done/inst_mine/received) +workbench_manager.ui (VBox) +├── 统计卡片行(dataurl=team_stats.dspy): 团队人数/本月入离职/待审批数 +├── 待审批 DataViewer(task_todo 范围=团队) | 团队入转调离 DataViewer(workbench_transfer.dspy) +└── 关怀提醒 VBox(生日/周年/合同到期 近期列表) +workbench_admin.ui (VBox) +├── 人事统计卡片(team_stats scope=all) + 合同即将到期 DataViewer(contract_expire_soon.dspy) +└── 待审批 + 关怀提醒(同经理视图,范围=数据权限内全部) +``` + +## 4. 核心交互流程(页面级时序) + +1. **入职(审批)**:entry_workbench [发起入职审批] → PopupWindow 表单 → entry_approval.dspy →(BLACKLIST_HIT 则红色高亮提示)成功 → 待审批列表出现;审批人在 todo_list 处理 → inst_detail 同意 → 花名册新增记录 → message_list 收到入职通知。 +2. **员工自助修改**:employee_detail → 编辑可改字段 → 保存 → 提示"直接生效"或"已提交审核"(need_audit)→ 审核通过后字段更新、时间轴留痕。 +3. **调动批量**:transfer_list [发起调动] → PopupWindow 多人选择 + 目标组织/职位 → transfer_apply.dspy → 生成批量审批单 → 通过后逐人更新,明细可追溯。 +4. **离职全流程**:leave_workbench 发起/手动 → 待离职名单 → [交接管理]逐项勾选 → [办理离职] → 状态 left → [开具证明]下载 → 可选[加入黑名单]。 +5. **合同到期提醒**:remind_scan(后台)→ message_list 消息 → workbench_admin 到期卡片 → contract_list 行内到期高亮。 +6. **历史架构图**:org_chart 选择 as_of 日期 → 查看 → 导出 PNG/XMind。 + +## 5. 设计规范 + +1. **布局**:左侧 Menu 固定 220px;内容区 VBox 滚动;卡片统一圆角 8px、间距 16px;表单 label 右对齐;列表默认每页 50。 +2. **状态色**:active/在职=绿、probation/审批中=橙、inactive/离职/驳回=灰、黑名单/超期=红。 +3. **反馈**:操作成功 message 提示并刷新当前视图;不可逆操作(停用/删除语义/加黑名单)一律 PopupWindow 二次确认;耗时操作(导入导出)返回 task_id 后轮询/消息通知结果。 +4. **空态/加载**:DataViewer 自带 loading 与空数据提示。 +5. **权限感知**:按钮与列按角色渲染(load_path + CRUD confidential_fields);敏感字段服务端脱敏后展示。 +6. **移动端兼容**:员工自助页面(工作台/档案/待办/服务/消息)使用 ResponsableBox 自适应,窄屏卡片化;管理类页面 PC 优先。 +7. **打印**:审批单 inst_print.dspy 输出 A4 打印样式页面。 + +## 6. 页面-接口追溯 + +| 页面 | 主要接口(见 api-design.md) | +|---|---| +| org_tree.ui | org_tree / org_unit_create / org_unit_update / org_unit_move / org_unit_disable / org_change_timeline / org_import | +| org_chart.ui | org_tree(as_of) / org_chart_export | +| roster_list.ui | roster_list / roster_employee_create / roster_import / roster_export / check_employee_no | +| employee_detail.ui | employee_detail / roster_employee_update / timeline / file_preview_url | +| entry_workbench.ui | entry_approval / entry_manual / entry_invite_register / entry_blacklist_check / entry_notify | +| transfer_list.ui | transfer_apply / transfer_cancel | +| leave_workbench.ui | leave_apply / leave_manual / leave_handover_save / leave_certificate / blacklist_add | +| todo_list.ui / inst_detail.ui | task_todo / inst_detail / task_approve / task_reject / task_forward / inst_withdraw / inst_print | +| flow_design.ui | form_def_save / flow_def_save / flow_node_save / flow_role_save | +| contract_list.ui | contract_list / contract_create / contract_import / contract_apply / contract_remind_rule_save | +| report_board.ui | roster_analysis / entry_analysis / regular_analysis / transfer_analysis / leave_analysis | +| workbench_*.ui | workbench_employee / workbench_manager / workbench_admin / team_stats | +| audit_log_list.ui | audit_log_list / audit_log_detail | +| remind_config.ui / service.ui | remind_rule_save / care_config_save / announcement_save / policy_save | diff --git a/modules/hr-contract.md b/modules/hr-contract.md new file mode 100644 index 0000000..0c47597 --- /dev/null +++ b/modules/hr-contract.md @@ -0,0 +1,50 @@ +# 模块名称: 合同模块 (hr-contract) + +状态:**迭代1总体设计完成(提交审核)** +所属应用:hr-web(Web版人事系统) + +## 1. 模块功能 +迭代1合同台账管理模块(不含电子签,对应 SRS v2 §3.1.9): + +| 功能编号 | 功能 | 说明 | +|---|---|---| +| F09 | 合同台账 | 合同在线管理(新增与批量导入);合同类型自定义(劳动合同、保密协议、竞业协议等);合同模板管理;合同审批(新签、续签、变更、终止);到期提醒(自定义提醒规则,提醒员工本人或管理人员) | + +输入/处理/输出/可验收标准见 `docs/00-requirement/iteration1-function-detail.md`(F09 共 6 条验收项)。 +集成类置后:电子签(依赖电子签平台,接口预留 esign_stub.dspy + contract_info.esign_status 字段)。 + +## 2. 仓库(规划地址) +- 仓库 URL:`git@git.opencomputing.cn:yumoqing/hr_contract.git`(规划,建仓时以 PM 确认为准) +- 工作空间目录:`repos/hr-contract` +- 分支:`main` + +## 3. 技术栈(ocai 规范,设计已冻结) +- 前端:bricks 组件体系 + dspy 声明式页面(contract_list.ui 台账含到期高亮、模板/类型/提醒规则配置页) +- 后端:ahserver(Python);load_hrcontract() 注册 ServerEnv;合同审批复用 hr-flow 引擎(biz_type=contract_sign/renew/change/stop);到期提醒经 hr-system remind_scan 扫描 contract_end_date +- 数据层:apppublic/sqlor;本模块 4 张表(前缀 contract_):contract_type、contract_template、contract_info、contract_remind_rule(见 `docs/01-design/database-design.md` §4.4) +- 附件:合同文件存 ahserver files/ +- 模块结构遵循 module-development-spec 标准结构 + +## 4. 模块依赖 +**依赖(本模块 → 其他模块):** + +| 依赖模块 | 依赖内容 | +|---|---| +| hr-roster | 合同与员工花名册关联(employee_id) | +| hr-org | 签约主体引用 org_contract_company 主数据 | +| hr-flow | 合同新签/续签/变更/终止审批 | +| hr-system | 提醒推送通道、权限与操作日志 | + +**被依赖(其他模块 → 本模块):** + +| 调用方 | 依赖内容 | +|---|---| +| hr-report | F13 合同相关统计(如适用) | +| hr-system | F14 管理员工作台查看权限范围内合同 | + +## 5. 设计落点(迭代1) +- 总体设计:`docs/01-design/api-design.md` §2.4(8 个端点)、`ui-design.md` §3(合同入口/台账页)、`database-design.md` §4.4 +- 开发任务:T19(合同台账全量,依赖 T10 审批引擎与 T16 提醒引擎) + +## 6. 负责人 +待定(迭代启动会指定)。 diff --git a/modules/hr-flow.md b/modules/hr-flow.md new file mode 100644 index 0000000..e69a7bc --- /dev/null +++ b/modules/hr-flow.md @@ -0,0 +1,49 @@ +# 模块名称: 流程审批模块 (hr-flow) + +状态:**迭代1总体设计完成(提交审核)** +所属应用:hr-web(Web版人事系统) + +## 1. 模块功能 +迭代1通用审批引擎模块,支撑入转调离等人事流程(对应 SRS v2 §3.1.14 系统-流程): + +| 功能编号 | 功能 | 说明 | +|---|---|---| +| F10 | 流程审批 | 自定义入转调离表单(花名册字段可被审批引用);自定义流程(多条件审批、字段权限设置);审批角色配置(流程范围/操作权限/数据查看范围);人事流程(入职/转正/异动/离职/离职交接审批,通过后自动更新花名册);审批数据查询(按表单/状态/发起人/审批编号/时间搜索与导出);审批在线打印 | + +输入/处理/输出/可验收标准见 `docs/00-requirement/iteration1-function-detail.md`(F10 共 7 条验收项)。 +迭代1范围外(置后):考勤流程联动考勤系统(接口预留)、薪酬流程与组合审批(依赖薪酬模块,迭代2)。 +能力边界(任务拆解 §1.3 裁决):迭代1锁定串行节点 + any/all 通过规则 + 节点字段权限 + 抄送;并行分支/条件分支留 flow_node_def JSON 扩展位。 + +## 2. 仓库(规划地址) +- 仓库 URL:`git@git.opencomputing.cn:yumoqing/hr_flow.git`(规划,建仓时以 PM 确认为准) +- 工作空间目录:`repos/hr-flow` +- 分支:`main` + +## 3. 技术栈(ocai 规范,设计已冻结) +- 前端:bricks 组件体系 + dspy 声明式页面(todo_list.ui 待办、inst_detail.ui 动态表单审批单、flow_design.ui 流程配置) +- 后端:ahserver(Python);load_hrflow() 注册 ServerEnv;状态机 running→approved/rejected/cancelled;业务回写经 biz_type+biz_id 关联 + 完成回调 hook(调 hr-roster roster_writeback) +- 数据层:apppublic/sqlor;表单/流程/节点全部 JSON 化配置(fields_json/match_cond_json/field_perm_json),无硬编码;本模块 7 张表(前缀 flow_) +- 模块结构遵循 module-development-spec 标准结构 + +## 4. 模块依赖 +**依赖(本模块 → 其他模块):** + +| 依赖模块 | 依赖内容 | +|---|---| +| hr-roster | 审批表单引用花名册字段;审批通过后调用花名册回写能力 | +| hr-org | 审批表单引用组织、职位职级主数据 | +| hr-system | 审批角色的权限基础、操作日志 | + +**被依赖(其他模块 → 本模块):** + +| 调用方 | 依赖内容 | +|---|---| +| hr-org | F04~F08 全部审批流转(入职/转正/调动/离职/兼岗) | +| hr-contract | F09 合同新签/续签/变更/终止审批 | + +## 5. 设计落点(迭代1) +- 总体设计:`docs/01-design/architecture.md` §4.2(引擎与业务解耦规则)、`database-design.md` §4.3、`api-design.md` §2.3(18 个端点)、§3.1 转正调用链、`ui-design.md` §3.6 +- 开发任务:T10(引擎核心,关键路径)、T11(审批界面)、T12(查询导出) + +## 6. 负责人 +待定(迭代启动会指定)。 diff --git a/modules/hr-org.md b/modules/hr-org.md new file mode 100644 index 0000000..8ae5df1 --- /dev/null +++ b/modules/hr-org.md @@ -0,0 +1,55 @@ +# 模块名称: 组织人事模块 (hr-org) + +状态:**迭代1总体设计完成(提交审核)** +所属应用:hr-web(Web版人事系统) + +## 1. 模块功能 +迭代1组织人事底座核心模块,承担组织与人员异动主线业务: + +| 功能编号 | 功能 | 说明(对应 SRS v2 章节) | +|---|---|---| +| F01 | 组织架构 | 组织树查看/编辑(新建、变更、停用、移动)、字段自定义、组织架构图、时间轴管理、Excel 批量导入(SRS §3.1.2) | +| F02 | 职位职级体系 | 职位/职务/职级/职等/序列管理,新增/编辑/停启用、批量导入导出(SRS §3.1.2) | +| F04 | 入职管理 | 审批入职、手动入职(批量)、完善个人信息、黑名单校验、入职通知;扫码入职/身份证读取为集成类降级项(SRS §3.1.5) | +| F05 | 转正管理 | 审批转正、手动转正、转正提醒,通过后自动更新花名册(SRS §3.1.6) | +| F06 | 调动管理 | 调动查询/审批(晋升、降级、调岗、组织调整)、批量调动,通过后关联员工档案(SRS §3.1.7) | +| F07 | 离职管理 | 审批离职、手动离职、离职交接、离职员工信息存储、离职证明、黑名单(SRS §3.1.8;钉钉资源交接为集成类置后) | +| F08 | 兼岗管理 | 一人多条兼岗记录(起止日期、兼岗职位),兼岗审批通过后自动同步(SRS §3.1.4) | + +各功能输入/处理/输出/可验收标准见 `docs/00-requirement/iteration1-function-detail.md`。 +范围外:编制管理、项目式组织架构、钉钉同步(集成类,后续迭代/集成迭代)。 + +## 2. 仓库(规划地址) +- 仓库 URL:`git@git.opencomputing.cn:yumoqing/hr_org.git`(规划,建仓时以 PM 确认为准) +- 工作空间目录:`repos/hr-org` +- 分支:`main` + +## 3. 技术栈(ocai 规范,设计已冻结) +- 前端:bricks 组件体系 + dspy 声明式页面(org_tree.ui 组织树、org_chart.ui 架构图、entry_workbench/transfer_list/leave_workbench 异动工作台) +- 后端:ahserver(Python);load_hrorg() 注册 ServerEnv;审批回写经 hr-flow 完成回调 hook +- 数据层:apppublic/sqlor;本模块 18 张表(前缀 org_):org_unit(+change/field_def/field_value)、org_job/position/sequence/grade_level/grade_rank、org_blacklist、org_contract_company、org_entry、org_regularization、org_transfer(+detail)、org_leave(+handover)、org_concurrent_post(见 `docs/01-design/database-design.md` §4.1) +- 模块结构遵循 module-development-spec 标准结构 + +## 4. 模块依赖 +**依赖(本模块 → 其他模块):** + +| 依赖模块 | 依赖内容 | +|---|---| +| hr-roster | 入转调离审批通过后写入/更新花名册(roster_writeback 唯一入口);黑名单数据 | +| hr-flow | 入职/转正/调动/离职/兼岗审批流程定义与流转引擎 | +| hr-system | 权限校验(数据范围 get_data_scope)、操作日志记录(write_audit_log) | + +**被依赖(其他模块 → 本模块):** + +| 调用方 | 依赖内容 | +|---|---| +| hr-report | F13 报表的入转调离异动数据源 | +| hr-flow | 审批表单引用组织、职位职级主数据 | +| hr-system | F14 工作台展示入转调离数据 | + +## 5. 设计落点(迭代1) +- 总体设计:`docs/01-design/architecture.md` §4、`api-design.md` §2.1(约 30 个端点)、`ui-design.md` §3.1/§3.2/§3.5 +- 开发任务:T03(组织管理)、T04(职位职级)、T13(入职)、T14(转正)、T15(调动)、T17(离职)、T18(兼岗) + +## 6. 负责人 +待定(迭代启动会指定)。 diff --git a/modules/hr-report.md b/modules/hr-report.md new file mode 100644 index 0000000..52d84b3 --- /dev/null +++ b/modules/hr-report.md @@ -0,0 +1,46 @@ +# 模块名称: 报表模块 (hr-report) + +状态:**迭代1总体设计完成(提交审核)** +所属应用:hr-web(Web版人事系统) + +## 1. 模块功能 +迭代1人事报表模块,提供人事数据多维分析(对应 SRS v2 §3.1.13): + +| 功能编号 | 功能 | 说明 | +|---|---|---| +| F13 | 人事报表 | 花名册信息分析(员工类型/状态/年龄/学历/办公地点/性别等多维分布,维度可自定义);入职分析(按部门/地区/岗位分析入职数量及趋势);转正分析(多维度转正数量及趋势、近期待转正数据);调岗分析(近期人员调动数据);离职员工分析(待离职人数、离职原因、离职率、同环比) | + +输入/处理/输出/可验收标准见 `docs/00-requirement/iteration1-function-detail.md`(F13 共 6 条验收项)。 + +## 2. 仓库(规划地址) +- 仓库 URL:`git@git.opencomputing.cn:yumoqing/hr_report.git`(规划,建仓时以 PM 确认为准) +- 工作空间目录:`repos/hr-report` +- 分支:`main` + +## 3. 技术栈(ocai 规范,设计已冻结) +- 前端:bricks 组件体系 + dspy 声明式页面(report_board.ui 看板:Tab 切换五类分析,Chart 图表组件 + 明细 DataViewer) +- 后端:ahserver(Python);只读聚合查询(sor.sqlExe 只读 SQL),全部接口强制叠加 sys_data_scope 数据范围;100 人规模不建物化视图 +- 数据层:apppublic/sqlor;本模块无自有表,只读 org_/roster_/flow_ 表 +- 模块结构遵循 module-development-spec 标准结构 + +## 4. 模块依赖 +**依赖(本模块 → 其他模块):** + +| 依赖模块 | 依赖内容 | +|---|---| +| hr-roster | 花名册信息分析数据源(含 EAV 自定义维度) | +| hr-org | 入转调离异动记录数据源 | +| hr-system | 数据范围权限控制(报表只能看权限范围内数据)、操作日志 | + +**被依赖(其他模块 → 本模块):** + +| 调用方 | 依赖内容 | +|---|---| +| hr-system | F14 工作台团队人事统计卡片数据(team_stats.dspy) | + +## 5. 设计落点(迭代1) +- 总体设计:`docs/01-design/api-design.md` §2.5(6 个只读端点)、`ui-design.md` §3.7 报表看板 +- 开发任务:T20(人事报表,依赖 T06 与 T13~T17) + +## 6. 负责人 +待定(迭代启动会指定)。 diff --git a/modules/hr-roster.md b/modules/hr-roster.md new file mode 100644 index 0000000..00b06f0 --- /dev/null +++ b/modules/hr-roster.md @@ -0,0 +1,51 @@ +# 模块名称: 花名册模块 (hr-roster) + +状态:**迭代1总体设计完成(提交审核)** +所属应用:hr-web(Web版人事系统) + +## 1. 模块功能 +迭代1人员主数据模块,是全系统员工数据的唯一事实来源(对应 SRS v2 §3.1.3): + +| 功能编号 | 功能 | 说明 | +|---|---|---| +| F03 | 花名册 | 花名册搭建(自定义字段:文本/数字/附件)、分组管理(工作信息/个人信息等)、在线查看(附件预览、拖拽排序)、自动生成工号(多规则)、员工自助修改(可配置范围与审核)、时间轴信息管理(全周期成长记录)、分类管理(不同员工类型字段规则)、个性化搜索筛选、自定义批量导入、自定义导出(指定数据日期/字段/顺序) | + +输入/处理/输出/可验收标准见 `docs/00-requirement/iteration1-function-detail.md`(F03 共 8 条验收项)。 + +## 2. 仓库(规划地址) +- 仓库 URL:`git@git.opencomputing.cn:yumoqing/hr_roster.git`(规划,建仓时以 PM 确认为准) +- 工作空间目录:`repos/hr-roster` +- 分支:`main` + +## 3. 技术栈(ocai 规范,设计已冻结) +- 前端:bricks 组件体系 + dspy 声明式页面(roster_list.ui DataViewer 列表、employee_detail.ui 档案 Tabs+时间轴、field_config.ui 字段配置拖拽) +- 后端:ahserver(Python);load_hrroster() 注册 ServerEnv,暴露 roster_writeback 供 hr-org/hr-flow 服务内回调(不注册 HTTP 路径) +- 数据层:apppublic/sqlor;自定义字段采用 EAV 双表(roster_field_def + roster_field_value),高频字段冗余 roster_employee 主表;附件走 ahserver files/ 存储;本模块 7 张表(前缀 roster_) +- 列表性能模式:主表条件分页 + 值表批量 IN 拼装 + 敏感字段按角色脱敏(roster_field_def.sensitive 驱动) +- 模块结构遵循 module-development-spec 标准结构 + +## 4. 模块依赖 +**依赖(本模块 → 其他模块):** + +| 依赖模块 | 依赖内容 | +|---|---| +| hr-org | 员工任职信息引用组织、职位职级主数据(options 端点) | +| hr-flow | 员工自助修改可配置审核环节(biz_type=roster_self_edit) | +| hr-system | 字段级数据权限、敏感信息脱敏角色矩阵、操作日志 | + +**被依赖(其他模块 → 本模块):** + +| 调用方 | 依赖内容 | +|---|---| +| hr-org | 入转调离审批通过后回写花名册(本模块提供回写能力,唯一写入入口) | +| hr-flow | 审批表单引用花名册字段 | +| hr-contract | 合同与员工花名册关联 | +| hr-report | F13 花名册信息分析数据源 | +| hr-system | F14 个人档案、F15 提醒规则字段 | + +## 5. 设计落点(迭代1) +- 总体设计:`docs/01-design/architecture.md` §4、`database-design.md` §4.2(EAV 方案)、`api-design.md` §2.2(16 个端点)、`ui-design.md` §3.3/§3.4 +- 开发任务:T05(字段体系)、T06(花名册主体)、T07(导入导出) + +## 6. 负责人 +待定(迭代启动会指定)。 diff --git a/modules/hr-system.md b/modules/hr-system.md new file mode 100644 index 0000000..3360ee7 --- /dev/null +++ b/modules/hr-system.md @@ -0,0 +1,55 @@ +# 模块名称: 权限日志与通用服务模块 (hr-system) + +状态:**迭代1总体设计完成(提交审核)** +所属应用:hr-web(Web版人事系统) + +> 说明:本模块为迭代1规划的系统支撑模块(ocai 口径),取代 v1 同名应用 `apps/hr-system.md`(Java 口径,已废弃)。 + +## 1. 模块功能 +迭代1系统支撑能力模块,承载权限、日志、工作台与员工服务提醒(对应 SRS v2 §3.1.1/§3.1.11/§3.1.12/§3.1.14): + +| 功能编号 | 功能 | 说明 | +|---|---|---| +| F11 | 权限管理 | 管理角色(创建角色并设置权限);人员范围管理(按组织部门维度或花名册字段设置可管理人员范围);管理员管理(创建管理员并调整权限) | +| F12 | 操作日志 | 按操作时间/类型查看操作记录,详情含操作前后对比、操作人、时间;全量记录增删改操作 | +| F14 | 工作台 | 员工工作台(个人档案/发起审批/待办管理)、经理工作台(权限范围内入转调离管理与审批、团队人事统计、员工关怀提醒)、管理员工作台(权限范围内入转调离与合同、人事统计、员工关怀提醒) | +| F15 | 员工服务与提醒 | 生日/周年关怀(个性化文案、到期自动推送);企业政策查询;企业公告查询;通用场景到期提醒(入职、转正、离职、退休、合同到期、健康证到期、社保缴纳等,自定义提醒内容与时间,推送管理员或员工) | + +输入/处理/输出/可验收标准见 `docs/00-requirement/iteration1-function-detail.md`(F11/F12/F14/F15 合计 18 条验收项)。 + +## 2. 仓库 +- 仓库 URL:`git@git.opencomputing.cn:yumoqing/hr-system.git`(复用现有仓,迭代1总体设计文档已提交至该仓 `docs/01-design/`) +- 工作空间目录:`repos/hr-system` +- 分支:`main` + +## 3. 技术栈(ocai 规范,设计已冻结) +- 前端:bricks 组件体系 + dspy 声明式页面(工作台门户 workbench_employee/manager/admin.ui、角色权限配置 role_admin.ui/data_scope.ui、日志查询 audit_log_list.ui、员工服务 service.ui) +- 后端:ahserver(Python);ServerEnv 注册横切公共函数 `get_data_scope(user_id)`、`write_audit_log(...)`、`remind_scan()` +- 数据层:apppublic/sqlor;本模块 7 张表(前缀 sys_):sys_data_scope、sys_audit_log、sys_message、sys_remind_rule、sys_announcement、sys_policy、sys_care_config(见 `docs/01-design/database-design.md` §4.5) +- 权限:复用 rbac 基础包做路径级功能权限,本模块扩展双维度数据范围(组织/花名册字段) +- 消息推送:站内消息优先(sys_message),短信/邮件为集成类预留(send_channel 字段) +- 模块结构遵循 module-development-spec 标准结构(包/wwwroot/models/json/init/scripts/skill) + +## 4. 模块依赖 +**依赖(本模块 → 其他模块):** + +| 依赖模块 | 依赖内容 | +|---|---| +| hr-org | F14 工作台展示入转调离数据引用组织与异动主数据;F11 人员范围按组织部门维度配置 | +| hr-roster | F14 个人档案、F15 提醒规则字段、花名册字段权限基础 | +| hr-contract | F14 管理员工作台查看权限范围内合同 | + +**被依赖(其他模块 → 本模块):** + +| 调用方 | 依赖内容 | +|---|---| +| hr-org / hr-roster / hr-flow / hr-contract / hr-report | F11 权限校验(数据范围)与 F12 操作日志为横切能力,全模块依赖 | +| hr-contract / hr-org | F15 提醒推送通道(入职通知、转正提醒、合同到期提醒等) | + +## 5. 设计落点(迭代1) +- 总体设计:`docs/01-design/architecture.md` §4.1/§4.3(职责边界)、`api-design.md` §2.6、`ui-design.md` §3.8/§3.9 +- 数据迁移:staff-mgr 迁移脚本规划于本仓 `scripts/migrate_staff_mgr.py`(见 `database-design.md` §7、任务拆解 T23) +- 开发任务:T08(权限底座)、T09(审计底座)、T16(提醒引擎)、T21(工作台)、T22(员工服务)、T23(staff-mgr 迁移) + +## 6. 负责人 +待定(迭代启动会指定)。