agent.develop: 批次1开发基础:数据契约(models JSON)+ahserver/bricks工程脚手架+DDL迁移基座(T01/T02)

This commit is contained in:
Pipeline Agent 2026-08-19 16:54:26 +08:00
parent 049e63cf50
commit 043916b54d
6 changed files with 1501 additions and 6 deletions

View File

@ -1 +1,247 @@
完整正文 29,356B 已落盘并推送git commit 5a96df5。目录§1接口范式+11项错误码 §2六模块约120端点清单(请求/响应/角色) §3六个典型调用链 §4 staff-mgr替代映射 §5降级桩端点汇总 §6安全要点
# 一期批次1总体设计 —— API/接口设计hr-webocai 口径)
- 版本v3.0批次1设计定稿v3.0 变更:对齐 SRS v3.1 —— 新增编制管理(F16)/项目式组织(F17)端点、入职登记链接与二维码端点扫码入职降级、合同文本生成端点D4、证件手工录入字段契约D1、开放接口桩端点、错误码扩充
- 状态:**设计定稿批次1评审修订版**
- 规范依据ocai 技能集 module-development-spec、dspy-file-implementation-spec、crud-definition-spec架构基线 `docs/01-design/architecture.md`
## 1. 接口范式与通用约定
1. **端点形态**:全部接口为 `.dspy` 端点(受控 Python路径 `/{module}/api/{name}.dspy`,由 ahserver wwwroot 自动路由无需注册GET query 与 POST body 统一解析进 `params_kw`。dspy 必须显式 `return`,且不得在 `async with db.sqlorContext` 块内 returnNoneType 陷阱)。
2. **鉴权**session cookieRedis 会话)+ rbac 路径级角色控制;每条路径经各模块 `scripts/load_path.py` 注册,角色:`admin / hr / manager / employee / logined`未注册路径默认拒绝SRS §2.2-1。不使用 JWT。
3. **数据范围**:查询、报表、**导出**类接口强制叠加 `get_data_scope(user_id)`hr-system 提供范围外数据不可见、不可导出SRS §2.2-2
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=errorbricks 前端惯例),鉴权失败由框架返回 401/403。
6. **错误码规范**status=error 时 data.code
| code | 含义 | 典型场景 |
|---|---|---|
| PARAM_INVALID | 参数缺失/格式错误 | 必填项为空、日期格式错 |
| NOT_FOUND | 对象不存在 | id 无效 |
| DUPLICATE | 唯一冲突 | 工号/组织编码/项目编码重复 |
| NO_PERMISSION | 数据范围外/角色不足 | 越权访问他人档案 |
| BLACKLIST_HIT | 黑名单命中 | 入职校验拦截F04-6 |
| STATUS_CONFLICT | 状态不允许 | 已离职再调动、重复审批 |
| FLOW_NOT_MATCH | 无匹配审批流 | 该员工类型/部门未配置流程 |
| HEADCOUNT_OVER | 编制超编提醒(不硬拦截) | 入转调联动编制校验F16SRS 验收"提醒不硬拦截" |
| NOT_ENABLED | 功能未启用(桩位) | esign_stub / openapi ping降级项 |
| REGISTER_EXPIRED | 登记表链接过期 | 入职登记二维码超时 |
| INTERNAL_ERROR | 服务异常 | 兜底 |
7. **审计**:所有写接口成功后调用 `write_audit_log(module,target_type,target_id,op,before,after)`hr-system
8. **敏感字段**响应中身份证一律脱敏前3后3、手机前3后4、sensitive=1 字段按角色矩阵过滤,服务端处理后返回。
## 2. 端点清单(按模块)
> 角色列A=adminH=hrM=managerE=employeeL=任意登录。数据范围=是 表示叠加数据范围过滤。
> CRUD 列:该表的标准增删改查由 json/*.json 自动生成,路径为 `/{module}/{tblname}_list`(页面) + `add_/update_/delete_{tblname}.dspy`
### 2.1 hr-org/hrorgF01/F02/F04~F08/F16/F17
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 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 批量导入组织(后台任务+结果文件≥200 行成功率 100%,错误行回报) | 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 | 架构图导出(按 as_of 日期) | 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/company_save.dspy | POST | 合同公司维护(供合同/入职引用) | company_code,company_name,credit_code,... | {id} | A,H | org_contract_company |
| /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 | 发起入职审批(单个,匹配审批流;含证件字段组手工录入 D1 | name,id_type,id_number,id_valid_from,id_valid_to,id_authority,employee_type,org_id,position_id,company_id,work_location,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 | 批量邀请待入职填写登记表(生成 register_token/url/二维码图片,站内消息发送) | entry_ids[],expire_days? | {} | A,H | — |
| /hrorg/api/entry_register_page.dspy | GET | 登记表渲染页(按 flow_form_def biz_type=entry 表单定义动态渲染;**内网可访问,免登录 token 鉴权** | token | 表单结构 JSON | 匿名(token) | — |
| /hrorg/api/entry_register_submit.dspy | POST | 待入职员工提交登记表(校验 token 有效期) | token,字段kv | {} 或 REGISTER_EXPIRED | 匿名(token) | — |
| /hrorg/api/entry_qrcode.dspy | GET | 入职登记二维码图片获取/重新生成 | entry_id | {qrcode_file,url,expire} | A,H | — |
| /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/entry_rehire_match.dspy | GET | 复职匹配(按证件号哈希查历史档案) | id_number | {matched:bool,prev_employee_id?,last_org?,last_position?} | 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 | 发起调动审批(支持批量人员 ≥20 人) | transfer_type,effective_date,details[]:{employee_id,to_org_id,to_position_id,to_grade_level_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 | 离职交接项保存(含 dingtalk_resource 占位项,手工登记内容) | leave_id,items[]:{item_type,item_content,handover_to_id} | {} | A,H,M | org_leave_handover |
| /hrorg/api/leave_effect.dspy | 内部 | 离职生效处理离职日期到达状态转离职remind_scan 触发) | employee_id | {} | 服务内 | — |
| /hrorg/api/leave_certificate.dspy | GET | 离职证明生成下载(按模板 PDF | 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/headcount_scheme_save.dspy | POST | 编制方案创建/编辑(多套方案并行) | scheme_name,cycle_type,cycle_start,cycle_end | {id} | A,H | org_headcount_scheme |
| /hrorg/api/headcount_item_save.dspy | POST | 编制细分项维护(占编范围条件+细分+数量) | scheme_id,items[]:{scope_json,seg_json,head_limit} | {} | A,H | headcount_item |
| /hrorg/api/headcount_status.dspy | GET | 编制状态看板(超编/缺编+细分实时数) | scheme_id?,as_of? | {rows:[{item,head_limit,used,over,gap}]} | A,H,M(范围) | — |
| /hrorg/api/headcount_history.dspy | GET | 历史编制查询(任意时间点快照) | scheme_id,as_of | {rows:[{snap_date,used_count,over_count}]} | A,H | — |
| /hrorg/api/headcount_check.dspy | 内部 | 异动联动编制校验(入转调回写后调用,超编写提醒消息,不拦截) | employee_id,event_type | {over:bool,scheme_id?} | 服务内 | — |
| /hrorg/api/project_save.dspy | POST | 项目式组织创建/维护(多层级/属性/负责人/时间范围;到期自动标识 expired | project_code,project_name,parent_id,owner_id,start_date,end_date,attrs_json | {id} | A,H | org_project |
| /hrorg/api/project_tree.dspy | GET | 项目组织树 | keyword?,status? | 树形节点数组 | L | — |
| /hrorg/api/project_post_save.dspy | POST | 项目任职维护(员工挂横向项目+横向职务) | project_id,employee_id,job_id,start_date,end_date | {id} | A,H | org_project_post |
| /hrorg/api/horizontal_job_options.dspy | GET | 横向职务选项org_job.job_category=horizontal供花名册/薪酬引用) | keyword | {rows:[{id,name}]} | L | — |
| /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/hrrosterF03
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD |
|---|---|---|---|---|---|---|
| /hrroster/api/roster_list.dspy | GET | 花名册列表(主表条件分页 + EAV 拼装 + 范围过滤 + 脱敏) | keyword?,org_id?,status?,type?,field_filters?(≤3 自定义字段等值),page,size | {rows,total} | A,H(范围),M(团队) | roster_employee |
| /hrroster/api/roster_employee_create.dspy | POST | 新增员工(工号规则自动生成、写时间轴;含证件字段组手工录入 D1id_type/id_number/id_valid_from/id_valid_to/id_authorityid_source='manual' | 主档字段+证件字段组+自定义字段kv | {id,employee_no} | A,H | roster_employee |
| /hrroster/api/roster_employee_update.dspy | POST | 更新员工含自助修改路径editable_self 范围校验+need_audit 走审批;二期读卡器回填证件同字段) | 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,projects} | 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[]:{rule_name,prefix,match_field,match_value,seq_length} | {} | 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 | 自定义导入(批量新增/批量修改≥500 行正确;模板按当前字段定义+类型规则生成) | 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 | 附件在线预览 URLfiles/ 受控访问) | file_id | {url} | L(按范围) | — |
| /hrroster/api/roster_writeback.dspy | 内部 | 异动回写唯一入口(仅 hr-org/hr-flow 服务内调用,注册于 ServerEnv不注册 HTTP 路径;回写后触发 headcount_check 与 timeline | biz_type,biz_id,instance_id | {} | 服务内 | — |
### 2.3 hr-flow/hrflowF10
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD |
|---|---|---|---|---|---|---|
| /hrflow/api/form_def_save.dspy | POST | 表单定义维护(引用花名册字段;含考勤类桩位表单 attendance_* | 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 | 节点维护(审批人/通过规则 any/all/字段权限/抄送) | 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 | 审批单打印视图A4 版式) | instance_id | 打印 HTML | L(参与者) | — |
### 2.4 hr-contract/hrcontractF09
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 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,template_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_text_gen.dspy | GET | 按模板生成合同文本占位符填充docx/pdf 供打印下载;电子签二期 D4 | contract_id,template_id?,fmt=docx/pdf | 文件 | 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 | 即将到期列表(工作台/提醒;误差 ≤1 天) | days | {rows} | A,H | — |
| /hrcontract/api/esign_stub.dspy | POST | 电子签预留桩D4返回未启用验证路由可达 | contract_id | {status:'error',data:{code:'NOT_ENABLED'}} | A,H | — |
### 2.5 hr-report/hrreportF13全部只读
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 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/report_export.dspy | GET | 报表数据导出(与页面数据一致,强制数据范围) | report_code,同各分析参数 | 文件 | A,H,M |
| /hrreport/api/team_stats.dspy | GET | 团队人事统计(经理工作台卡片) | org_id? | {headcount,entry_n,leave_n,...} | M,H,A |
### 2.6 hr-system/hrsystemF11/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[],scope | {} | 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:[...],salary_stub:null,perf_stub:null} | E | — |
| /hrsystem/api/workbench_manager.dspy | GET | 经理工作台聚合(团队统计/待审批/关怀提醒;考勤/团队绩效桩位) | — | {stats,todos:[],care:[...],attendance_stub:null} | M | — |
| /hrsystem/api/workbench_admin.dspy | GET | 管理员工作台聚合(人事统计/合同到期/提醒) | — | {stats,contracts:[],care:[...]} | A,H | — |
| /hrsystem/api/remind_rule_save.dspy | POST | 通用提醒规则≥6 场景自定义内容与时间) | 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/policy_download.dspy | GET | 政策文件下载(校验 downloadable 与查阅范围) | id | 文件 或 NO_PERMISSION | L(按范围) | — |
| /hrsystem/api/message_list.dspy | GET | 我的站内消息 | is_read?,msg_type? | {rows,total} | L | — |
| /hrsystem/api/message_read.dspy | POST | 标记已读 | ids[] | {} | L | — |
| /hrsystem/api/message_unread_count.dspy | GET | 未读数(全局铃铛) | — | {n} | L | — |
| /hrsystem/api/remind_scan.dspy | 内部 | 提醒扫描cron 每日+启动补扫:转正/合同/生日/周年/退休/健康证等到期推送;离职日期到达触发 leave_effect | — | {sent_n} | 服务内 | — |
| /openapi/v1/ping.dspy | GET | API 开放接口桩(一期仅验证路由/鉴权框架,返回 NOT_ENABLED规范见 architecture.md §9 | — | {status:'error',data:{code:'NOT_ENABLED'}} | 匿名(桩) | — |
### 2.7 appbase/rbac 沿用(不自研)
登录/登出、用户管理、字典 appcodes 维护、rbac 角色路径绑定由 appbase/rbac 包自带页面与端点承载(`/appbase/*``/rbac/*`批次1仅在各模块 init/data.json 中初始化字典、角色与四类流程模板。
## 3. 典型调用链示例
### 3.1 转正审批F05
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 → `headcount_check`(编制联动提醒);
5. 各步均写 sys_audit_log转正提醒由 `remind_scan` 按 probation_end_date 提前(默认 7 天可配)推送管理员与直属主管。
### 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-6
`POST /hrorg/api/entry_approval.dspy` → id_number 哈希匹配 org_blacklist → 命中返回 `{"status":"error","data":{"code":"BLACKLIST_HIT"}}`,前端待入职列表高亮标注;手动入职返回 blocked 名单。
### 3.4 入职登记表邀请(扫码入职降级)
1. HR 在待入职列表选中记录 → `POST entry_invite_register.dspy` → 生成 register_token/register_url + 二维码图片files/),站内消息发送邀请;
2. 候选人(内网)扫码访问 `entry_register_page.dspy?token=..` → 按表单定义渲染登记表(字段可配置、必填校验);
3. 提交 `entry_register_submit.dspy` → register_status=filled数据写入 org_entry/扩展字段 → 进入入职审批流或直接待入职。
### 3.5 离职全流程F07
`leave_apply/leave_manual` → 待离职名单status=pending_leave`leave_handover_save`(含 dingtalk_resource 占位项手工登记)→ remind_scan 到期触发 `leave_effect`(状态 left、写时间轴`leave_certificate` 生成证明 → 可选 `blacklist_add`
### 3.6 编制联动F16
入职/调动/离职回写成功 → `headcount_check(employee_id, event)` → 按 scope_json 匹配编制细分项重算 used_count → 写 headcount_snapshot当日→ 超编时向 hr/admin 发 sys_message提醒不硬拦截`headcount_status`/`headcount_history` 展示。
## 4. 与 v1 接口的替代关系(衔接 staff-mgr
| v1 端点JWT RESTful | 一期替代 |
|---|---|
| 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一期不做删除语义 |
| 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. 降级项桩端点汇总(二期恢复入口)
| 降级项 | 一期端点/字段 | 二期恢复方式 |
|---|---|---|
| D1 身份证读卡 | roster_employee/org_entry 证件字段组手工录入id_source=manual | 读卡硬件接入后经 roster_employee_update 回填同字段id_source=card_reader |
| D3 钉钉交接 | leave_handover_saveitem_type=dingtalk_resource 手工登记) | 钉钉开放平台对接后该类型项自动拉取资源清单 |
| D4 电子签 | esign_stub.dspyNOT_ENABLED+ contract_text_gen.dspy 打印下载 | 对接电子签平台esign_status 状态机流转 |
| D9 短信渠道 | sys_message.send_channel=site 兜底 | 短信网关接入扩展发送器send_channel=sms 生效 |
| 扫码入职 | entry_register_page/entry_register_submit/entry_qrcode内网 token | 对外渠道启用后 register_url 切公网域名 |
| API 开放 | /openapi/v1/ping.dspyNOT_ENABLED+ sys_openapp 表 | 按 architecture.md §9 规范启用签名鉴权 |
| 考勤/绩效桩位 | flow_form_def biz_type=attendance_*workbench_*_stub 字段 | 二期绩效/考勤系统接入后填充 |
## 6. 安全设计要点
1. 所有路径 load_path.py 注册;未注册即拒绝(含 .css/.js 静态资源)。
2. 敏感字段身份证全角色脱敏前3后3手机前3后4职级/薪资类字段仅 admin/hr由 roster_field_def.sensitive + 角色矩阵驱动,服务端脱敏后返回。
3. 全部 SQL 经 sqlor 绑定参数(`${var}$` 占位),禁止拼接用户输入。
4. 审批操作校验任务归属人;员工自助类接口校验本人(或白名单字段);登记表接口以一次性 token 鉴权并校验过期时间。
5. 导入导出、登录、权限变更全量写 sys_audit_log含 IP
6. 开放接口桩不注册业务处理;二期启用时按签名鉴权 + 数据出口授权管控。

View File

@ -1 +1,294 @@
完整正文 29,403B 已落盘并推送git commit 5a96df5HEAD blob 与工作区逐字节一致。目录§0需求对齐 §2总体架构 §3技术选型 §4模块边界 §5模块依赖 §6 staff-mgr衔接 §7部署设计(9182/MariaDB hrs/systemd/备份/HTTPS预留) §8安全设计 §9 API开放规范 §10降级项专章(D1/D3/D4/D9/扫码/考勤桩位+二期预留) §11 NFR响应表 §12配套文档索引
# 一期批次1总体设计 —— 系统架构与技术选型hr-web
- 版本v2.0批次1设计定稿v2.0 变更:对齐 SRS v3.1 —— 批次1范围扩入编制管理(F16)/项目式组织(F17)、数据库口径修正 MariaDB/库hrs、部署端口统一 9182、新增降级项设计专章 §10、新增 API 开放接口规范 §9、F01~F15↔FEAT-B1 编号映射)
- 状态:**设计定稿批次1评审修订版随本批次冻结契约变更须走设计评审**
- 需求基线:`docs/00-requirement/requirement-spec.md`SRS v3.12026-08-18+ `docs/00-requirement/iteration1-function-detail.md`F01~F1581 条)+ `docs/00-requirement/approved-features.md`FEAT-B1-01~12
- 应用定义:`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. 与需求基线的对齐说明
| # | 对齐项 | 结论 |
|---|---|---|
| 1 | 批次1范围 | SRS v3.1 §1.4 批次1 = 12 featureFEAT-B1-01~12。其中 FEAT-B1-10 编制管理、FEAT-B1-11 项目式组织在原 F01~F1581 条验收项)基线之外,本设计新增 **F16 编制管理6 条验收项、F17 项目式组织3 条验收项)**批次1合计 **90 条可验收项** |
| 2 | 功能编号映射 | F01 组织↔FEAT-B1-02F02 职位职级↔FEAT-B1-03F03 花名册+F08 兼岗↔FEAT-B1-04F04 入职↔FEAT-B1-05F05 转正+F06 调动↔FEAT-B1-06F07 离职↔FEAT-B1-07F09 合同↔FEAT-B1-08F14 工作台+F15 员工服务↔FEAT-B1-09F10 流程审批+F11 权限+F12 日志↔FEAT-B1-01F13 报表↔FEAT-B1-12F16↔FEAT-B1-10F17↔FEAT-B1-11 |
| 3 | 技术口径 | ocai 规范:前端 bricks + dspy后端 ahserver(Python);数据层 apppublic/sqlor(MariaDB);应用 hr-web。与 SRS v3.1 头注一致 |
| 4 | 部署口径 | 测试/生产应用统一端口 **9182**、库名 **hrs**SRS §8v1.1 文档中 dev:9080/prod:443/库hr 口径作废 |
| 5 | 降级项 | 批次1涉及 D1 身份证读卡→手工录入、D3 钉钉交接→占位字段、D4 电子签→模板生成+桩、D9 短信→站内兜底、扫码入职→内网登记链接/二维码;专章见 §10二期预留接口清单见 §10.4 |
## 1. 概述
批次1交付「Web 版人事系统hr-web」**组织人事底座 + 系统管理与权限基座**,功能范围 F01~F17组织架构、职位职级体系、花名册、入职/转正/调动/离职/兼岗、合同台账(不含电子签)、流程审批、权限/日志、报表、工作台、员工服务与提醒、**编制管理、项目式组织**。规模规格 100 人账号。
设计原则:
1. **全栈遵循 ocai 规范**:前端 bricks 组件体系(.ui 纯 JSON 声明式页面 + dspy 驱动的 CRUD后端 ahserverPython/aiohttp数据层 apppublic/sqlorMariaDB基础模块 appbase字典/用户)+ rbac角色权限
2. **配置驱动**表结构models/*.json、CRUD 界面json/*.json、字典appcodes全部声明式定义支撑 SRS 的"字段/流程/表单自定义"诉求FEAT-B1-01 验收①不写代码配置 4 类审批流)。
3. **模块宿主无关**:每个模块仅依赖基础包与自己的数据表,通过 `load_{module}()` 注册 ServerEnv可被任意宿主应用加载module-development-spec
4. **单一事实来源**花名册roster_employee是全系统员工数据唯一事实来源入转调离审批通过后统一经 `roster_writeback` 回写SRS §5.2-1
5. **降级留桩**一期降级项SRS §9一律"字段/桩端点/流程位"预留,二期对接不改表结构主干。
## 2. 总体架构
```
┌────────────────────────────────────────────────────────────────────┐
│ 浏览器PC Web 为主) │
│ bricks.js 渲染引擎:.ui(JSON) 页面 + DataViewer/Tree/Form/Chart │
└──────────────────────────────┬─────────────────────────────────────┘
│ HTTP session cookieRedis 会话)
┌──────────────────────────────▼─────────────────────────────────────┐
│ ahserver 应用进程hr-web直接监听 9182systemd 守护) │
│ (二期补齐域名/证书后可选引入 nginx:9182 HTTPS 反代,见 §7.3
│ 路由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 │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ 基础模块appbaseusers/orgs/appcodes 字典)+ rbac角色权限│ │
│ │ bricks_for_pythonUiWindow 等 pybricks │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ 后台任务remind_scan提醒扫描/ headcount 联动校验 / 导入导出任务 │
└──────────┬───────────────────────────────┬─────────────────────────┘
│ sqlor 连接池sor.C/U/D/R/I/sqlExe │ Redis session
┌──────────▼──────────┐ ┌────────▼────────┐
│ MariaDB库 hrs │ │ 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 自动生成列表/表单/树页面批次1中 80% 的增删改查页面零 Vue 代码DataViewer 自带筛选data_filter、子表subtables、工具栏 bind |
| 声明式页面脚本 | .dspy受控 Python | 后端 API 与页面逻辑统一语言栈Pythonahserver 自动解析参数、自动 JSON 序列化;禁止 import/print天然受控 |
| 后端框架 | ahserveraiohttp 异步) | 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 §2.2 |
| 数据库 | **MariaDB库 hrs** | 任务明确口径SRS §8sqlor DDL 模板成熟;每日全量备份保留 ≥30 天 |
| 会话 | Redis + aiohttp_session | web-application-spec 推荐;服务重启不丢登录 |
| 附件 | ahserver files/ 文件存储 | 合同附件、离职证明、导入导出文件、入职登记表二维码图片100 人规模本地目录足够随应用数据一并备份NFR-5 |
v1Java/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/**F16/F17** |
| hr-roster | /hrroster | 花名册(字段定义/字段值 EAV/员工主档/时间轴/工号规则)、导入导出 | roster_ | F03 |
| hr-flow | /hrflow | 表单定义、流程定义、流程实例、审批任务(待办/已办/我发起/我收到) | flow_ | F10FEAT-B1-01 流程引擎部分) |
| hr-contract | /hrcontract | 合同台账、合同类型/模板、到期提醒规则、合同审批、esign 桩 | contract_ | F09 |
| hr-report | /hrreport | 只读聚合报表(花名册/入职/转正/调岗/离职五类分析),无自有表 | — | F13 |
| hr-system | /hrsystem | 角色/管理员/数据范围、操作日志、工作台聚合、提醒规则、公告政策、站内消息 | sys_ | F11/F12/F14/F15FEAT-B1-01 权限日志部分 + FEAT-B1-09 |
### 4.2 职责边界规则
1. **员工主数据唯一入口**:所有模块读写员工信息必须经 hr-roster 的注册函数ServerEnv 暴露),禁止跨模块直接 SQL 写 roster_ 表。入转调离审批通过后由 hr-flow 回调 hr-org 的业务函数,再调用 hr-roster `roster_writeback` 更新员工主档与时间轴。
2. **审批引擎与业务解耦**hr-flow 只管"表单+流程+实例+任务"的流转,不含业务语义;业务回写通过 `biz_type + biz_id` 关联 + 流程完成回调ServerEnv 注册的 hook 函数实现。考勤流程桩位FEAT-B1-01仅允许建表单定义biz_type=attendance_* 无回写 hook。
3. **权限横切**:功能权限(路径级 RBAC由 rbac 模块统一拦截(各模块 scripts/load_path.py 注册路径与角色);数据范围由 hr-system 提供 `get_data_scope(user_id)` 公共函数hr-org/hr-roster/hr-report 在查询、报表、**导出**时强制叠加SRS §2.2-2
4. **操作日志横切**所有写操作sor.C/U/D统一经 hr-system 的 `write_audit_log(...)` 记录前后值before/after JSONF12 查询页只读 sys_audit_log。
5. **编制联动**入转调离回写成功后hr-org 同步调用 `headcount_check(employee, event)` 重算所属编制方案占编并写快照/超编提醒服务内同步执行100 人规模满足"1 分钟内刷新"验收)。
6. **字典统一**:任何枚举值不得硬编码在 dspy 中,一律走 appcodesinit/data.json 初始化CRUD 下拉用 models codes 段引用。
### 4.3 hr-system 与 staff-mgr 的职责边界
| 对象 | 性质 | 职责 | 状态 |
|---|---|---|---|
| **hr-system**模块repos/hr-system | ocai 规范模块 | 系统支撑层F11 权限管理、F12 操作日志、F14 工作台、F15 员工服务与提醒;并承载全应用横切能力(数据范围、审计、站内消息、提醒扫描) | 批次1新建复用现有空仓 hr-system.git |
| **staff-mgr**(遗留 Java 模块) | v1 遗留 | 旧员工 CRUD REST 服务(/api/v1/staff/*Spring Boot + JPA + JWT | **已归档,冻结不再开发**;仅作数据迁移来源与参考实现(见 §6 |
边界结论:
- 一期上线后 staff-mgr 不再承担任何线上职责;其员工数据一次性迁移至 hr-roster部门缓存迁移至 hr-org日志迁移至 hr-system详见 database-design.md §8、任务 T23
- 旧模块的"员工 CRUD"职责由 **hr-roster** 承接(不是 hr-systemhr-system 只承接"操作日志/权限"类横切职责。
- v1 应用定义 `apps/hr-system.md`Java 后端服务)已废弃,与模块 hr-system 仅重名,无继承关系。
- 迁移范围(仅在职/含历史)与切换时间点待 PM 确认SRS §11-Q3脚本按"可配置范围"实现,默认在职+离职保留档案。
## 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/ # 表定义 JSONjson2ddl → mysql.ddl.sql
├── json/ # CRUD 定义 JSONxls2ui → 列表页 + 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功能权限 ◄──── appbaseusers/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`(返回 `hrs`)→ `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 配置 **hrs** 库(测试环境 test/test123Redis sessionsession_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` 并导入 hrs 库 → init/data.json 导入(含四类流程模板、基础字段集、内置 admin 与角色SRS §5.2-4→ json/ 执行 `xls2ui` 生成 CRUD → symlink 各模块 wwwroot 与 bricks dist → systemd 服务。
## 6. 与现有 staff-mgr 员工管理模块的衔接方案
### 6.1 衔接定位
staff-mgr 是 v1 Java 口径下的员工 CRUD 模块(已通过端到端验证),与 ocai 规范冲突,不改造、不并行演进,采取**一次性数据迁移 + 接口替代 + 退役**策略。
### 6.2 职责与接口替代映射
| staff-mgr 旧接口(/api/v1/staff | 批次1替代hr-roster/hr-org/hr-system dspy | 说明 |
|---|---|---|
| POST /(创建员工) | /hrroster/api/roster_employee_create.dspy或手动入职 /hrorg/api/entry_manual.dspy | 新建一律走入职流程或花名册新增 |
| GET /(分页列表) | /hrroster/roster_listCRUD 列表 + data_filter | 筛选能力增强(自定义字段) |
| GET /{id}(详情) | /hrroster/api/employee_detail.dspy | 档案 Tabs + 时间轴 |
| PUT /{id}(更新) | /hrroster/api/roster_employee_update.dspy | 可配置自助修改 + 审核 |
| DELETE /{id}、POST /batch-delete | 离职流程 /hrorg/api/leave_manual.dspy | 一期不做物理/逻辑删除员工,统一走离职 |
| GET /{id}/change-logs | /hrroster/api/timeline.dspy | 时间轴(含迁移进来的旧变更记录) |
| GET /audit-logs | /hrsystem/api/audit_log_list.dspy | 历史日志迁入 sys_audit_log |
| GET /check/employee-no | /hrroster/api/check_employee_no.dspy | 工号查重保留 |
| GET /departments | /hrorg/api/org_tree.dspy | 部门缓存表废弃,直接查 org_unit |
脱敏规则延续并按 SRS §2.2-4 加强身份证号全角色脱敏前3后3、手机号前3后4、薪资职级类字段仅 admin/hr 可见——由 roster_field_def.sensitive 驱动,替代 staff-mgr 硬编码 MaskUtil。
### 6.3 数据迁移方案(详见 database-design.md §8
- 迁移对象staff_employee → roster_employeestaff_employee_extra → roster_field_value + contract_infostaff_department_cache → org_unitstaff_change_log → roster_timelinestaff_audit_log → sys_audit_log。
- 迁移工具hr-system 仓内 `scripts/migrate_staff_mgr.py`Python + sqlor幂等、按 employee_no 去重、输出核对报告:总数/抽样一致NFR-8
- 切换策略UAT 通过后一次性切换;切换后 staff-mgr 服务下线、仓库冻结归档(保留只读访问一个迭代周期)。迁移范围待 PM 确认SRS §11-Q3
### 6.4 风险与对策
| 风险 | 对策 |
|---|---|
| 旧数据字段语义不一致(如 status 枚举) | 迁移脚本内置映射表 + 人工核对报告UAT 期间双库比对 |
| 旧 department_id 无组织主数据 | 先迁 staff_department_cache 建 org_unit再按 department_id 关联 |
| 身份证号加密算法不同AesCipher | 迁移时解密后按 hr-web 统一加密方案重新落库cipher+hash |
## 7. 部署与运维设计SRS §8 落地)
### 7.1 环境矩阵
| 项 | 测试环境 | 生产环境 |
|---|---|---|
| 主机 | hrstest@192.168.16.12:22免密已验证 | hrs@192.168.16.10:22 |
| 应用端口 | **9182**ahserver 直接监听HTTP | **9182**(同左;域名/证书补齐前接受 IP 直连SRS §11-Q1 |
| 数据库 | MariaDB 本地test/test123库 hrs | MariaDB 本地,库 hrs生产账号口令部署时安全配置SRS §11-Q2 |
| 会话 | Redis 本地(仅内网监听) | Redis 本地(仅内网监听) |
| 进程守护 | systemd hr-web.service异常自动重启NFR-3 | 同左 |
| 备份 | 无要求 | MariaDB 每日全量备份mysqldump+crontab保留 ≥30 天files/ 附件目录随应用数据备份NFR-5 |
| 监控告警 | — | 进程存活 + 9182 端口探活 + 备份结果告警(基础三项;接收渠道待明确 SRS §11-Q8默认本地日志+邮件占位) |
### 7.2 部署形态决策
一期采用**单实例直连形态**ahserver 直接监听 9182systemd 守护(`Restart=always`),满足 NFR-3月度可用率 ≥99% 工作时间、异常自动重启)。不强制引入 nginx。
### 7.3 HTTPS 升级路径(预留)
生产域名与证书补齐后SRS §11-Q1引入 nginx 监听 9182HTTPS反代 ahserver 内部端口(如 127.0.0.1:9183ahserver 改绑 loopback配置变更仅涉及 conf/config.json 端口与 systemd unit无代码改动。招聘官网对外批次3 FEAT-B3-07依赖此升级。
## 8. 安全设计
1. **鉴权**ahserver sessionRedis+ rbac 角色。批次1角色`admin`(系统管理员)、`hr`(人事)、`manager`(部门经理)、`employee`(员工自助);所有路径经 scripts/load_path.py 注册,**未注册路径默认拒绝**SRS §2.2-1
2. **数据范围**F11sys_data_scope 支持两类范围——组织维度org_id 集合含子树、花名册字段维度field_id 可见集合),两类可叠加;查询、报表、导出层强制拼接范围条件。
3. **脱敏**SRS §2.2-4敏感字段身份证/手机/薪资级)在 roster_field_def 标记 sensitive身份证号全角色脱敏前3后3、手机号前3后4、薪资/职级等敏感字段仅 admin/hr 可见dspy 返回前按角色矩阵脱敏。
4. **审计**F12全量写操作记录前后值 JSON、操作人、时间、IP审批、导入导出、登录同样记录可按时间/类型查询。
5. **SQL 注入**:全部经 sqlor 绑定参数dspy 禁止拼接用户输入sqlExe 使用 `${var}$` 占位)。
6. **口令**密码加盐哈希存储appbase users 既有机制NFR-4
7. **API 开放接口鉴权**一期仅规范§9桩路径不注册业务处理注册即按"未启用"拒绝。
## 9. API 开放接口规范一期预留FEAT-B1-01⑦
一期不交付第三方集成,仅交付**鉴权与端点规范**
1. **端点形态**`/openapi/v1/{resource}.dspy`resource 规划 `employees|orgs|changes`(员工/组织/异动事件推送),与内部 dspy 同框架。
2. **鉴权方案(二期启用)**app_key + app_secret 签名HMAC-SHA256含时间戳防重放密钥由 admin 在系统管理页生成sys_openapp 表已预留,见 database-design.md §4.5);限流默认 10 req/s/app。
3. **响应契约**:与内部接口一致的 `{status,message,data}` 结构;批量接口统一分页参数 `page/size`size ≤200
4. **数据出口管控**:开放接口同样强制数据范围与脱敏规则,导出字段需在管理端显式授权。
5. **一期落位**:不注册业务端点;`/openapi/v1/ping.dspy` 返回 `{status:'error', code:'NOT_ENABLED'}` 作为桩位,验证路由与鉴权框架可达。
## 10. 降级项设计批次1相关SRS §9
| # | 降级项 | 一期降级方案(设计落点) | 二期预留接口/字段 |
|---|---|---|---|
| D1 | 身份证硬件读卡 | 入职/档案**手工录入**证件信息roster_employee 设 `id_type/id_number_cipher/id_number_hash/id_valid_from/id_valid_to/id_authority/id_source(='manual')`入职审批单与登记表含证件信息分组展示脱敏前3后3 | `id_source` 枚举预留 `card_reader`;读卡硬件对接后经 `roster_employee_update` 回填同一组字段,无需改表 |
| D3 | 钉钉同步/离职资源交接 | 不同步;离职交接项 `org_leave_handover.item_type`**`dingtalk_resource`(占位类型)**,交接内容手工登记;组织/人员无同步入口 | 交接项类型字典可扩展;二期钉钉开放平台对接后 item_type=dingtalk_resource 项改为自动拉取资源清单 |
| D4 | 电子签 | contract_template 按占位符生成合同文本docx/pdf供**打印/下载**contract_text_gen.dspy`contract_info.esign_status` 字段not_enabled+ `esign_stub.dspy` 桩端点返回 NOT_ENABLED | esign_status 状态机not_enabled→signing→signed已定义二期对接电子签平台后流转 |
| D9 | 短信通知渠道 | sys_message.send_channel 一期仅 `site`(站内)生效;提醒/关怀/审批通知全部站内送达;未配置 SMTP 时不尝试邮件 | send_channel 枚举含 `sms/email` 预留位;二期短信网关/SMTP 接入仅扩展发送器 |
| —(扫码入职降级) | 对外渠道扫码入职 | 系统内生成**入职登记链接 + 二维码图片**内网可访问org_entry 增 `register_token/register_url/qrcode_file/register_expire`;候选人扫码填登记表进审批流 | register_url 域名部分走配置项,二期对外渠道启用后切换公网域名 |
| —(考勤流程桩位) | 考勤流程联动 | FEAT-B1-01考勤类表单换班/加班/请假等可建表单定义biz_type=attendance_*),无回写 hook、不联动考勤系统 | flow_def.biz_type 字典预留 attendance_* 值 |
| —(工作台绩效/考勤统计桩位) | 经理/管理员工作台绩效考勤卡片 | F14工作台留"绩效/考勤"桩位卡片,显示"未接入"占位,不取数 | workbench 聚合端点预留 perf/attendance 空结构字段 |
## 11. 非功能设计响应SRS §7
| NFR | 指标 | 设计响应 |
|---|---|---|
| NFR-1 | 列表 ≤500ms报表聚合 ≤3s导入 500 行 ≤30s | 100 人规模 + 索引设计database-design.md §6列表默认分页 50组织树一次性加载≤200 节点);报表直接 SQL 聚合;导入走后台任务 + 结果文件 |
| NFR-2 | 100 账号/并发 30/简历 2 万/花名册 2000 | 单实例 ahserver 异步模型足够;花名册含离职档案 2000 行在索引覆盖下无压力 |
| NFR-3 | 月度可用率 ≥99%,异常自动重启 | systemd Restart=always单实例无状态会话在 Redis |
| NFR-4 | session+rbac/默认拒绝/审计/脱敏/参数绑定/密码哈希 | §8 安全设计逐项覆盖 |
| NFR-5 | 每日全量备份 ≥30 天 | §7.1mysqldump crontab + files/ 目录备份 |
| NFR-6 | Chrome/Edge 最近 2 版;员工自助移动端兼容 | bricks 标准组件兼容;员工自助页面(工作台/档案/待办/服务/消息ResponsableBox 自适应 |
| NFR-7 | ocai 模块结构/配置化/load_xxx 装配 | §3/§5 全栈声明式;表单/流程/字段 JSON 化 |
| NFR-8 | staff-mgr 迁移核对报告 | §6.3 + database-design.md §8总数/抽样一致) |
## 12. 配套设计文档
| 文档 | 版本 | 内容 |
|---|---|---|
| database-design.md | v3.0 | ER、**49 张表**结构(含编制/项目式 6 新表 + sys_openapp 预留、索引、字典、models JSON、staff-mgr 迁移 |
| api-design.md | v3.0 | dspy 端点清单(约 120 个)、请求/响应契约、鉴权角色、错误码、降级桩端点汇总、开放接口规范 |
| ui-design.md | v3.0 | 页面结构、组件树、路由表、核心交互流程、降级项交互说明 |
| iteration1-task-breakdown.md | v2.0 | 可行性分析、风险、开发任务拆解T01~T27面向 develop 角色可直接建任务) |
| feature-list.md | v2.1 | F01~F17 功能清单与 FEAT-B1 映射批次1范围基线 |

View File

@ -1 +1,478 @@
完整正文 40,259B 已落盘并推送git commit 5a96df5。目录§1设计总则 §2 ER描述 §3 models JSON示例 §4 49张表清单(字段/索引逐表) §5核心表DDL示例 §6索引与性能策略(EAV/编制快照) §7数据字典 §8 staff-mgr迁移策略(NFR-8) §9验收映射
# 一期批次1总体设计 —— 数据库设计hr-webocai 口径)
- 版本v3.0批次1设计定稿v3.0 变更:对齐 SRS v3.1 —— 库名 hrs/MariaDB、新增编制(F16)/项目式(F17) 5 张表与 sys_openapp 预留表43→**49** 张、roster_employee 证件字段扩展D1 手工录入、org_entry 登记链接/二维码字段扫码入职降级、org_leave_handover 钉钉交接占位、字典扩充)
- 状态:**设计定稿批次1评审修订版**
- 需求基线:`docs/00-requirement/requirement-spec.md`SRS v3.1+ `iteration1-function-detail.md`F01~F15+ approved-features.mdFEAT-B1-01~12
- 架构基线:`docs/01-design/architecture.md`
- 规范依据ocai 技能集 database-table-definition-specmodels/*.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 导入 **hrs** 库。本文 DDL 为生成物等价示例,开发以 models JSON 为准。
2. **统一约定**InnoDButf8mb4 / utf8mb4_unicode_ci数据库 MariaDB库名 `hrs`;主键 `id VARCHAR(32)`getID() 雪花串sqlor 惯例);公共审计列 `created_by/updated_by/created_at/updated_at``sor.C` 不自动填时间戳,写入时显式 `created_at=curDateString()`
3. **逻辑删除策略**:员工与组织**不做物理删除**,统一走"停用(status=inactive)/离职流程";物理删除仅 admin 可执行且必须留审计SRS §5.2-2
4. **自定义字段EAV**花名册字段F03与组织字段F01采用"字段定义表 + 字段值表"EAV 方案;固定高频查询字段(组织、职位、状态、入离职日期)冗余在员工主表保证列表性能。
5. **敏感字段**:身份证号密文列 + 哈希列(确定性哈希,供唯一性与黑名单匹配),手机号明文存储、按角色脱敏展示;`roster_field_def.sensitive` 驱动字段级脱敏与可见性SRS §2.2-4
6. **库划分**:单库 `hrs`,表前缀区分模块:`org_`(hr-org)、`roster_`(hr-roster)、`flow_`(hr-flow)、`contract_`(hr-contract)、`sys_`(hr-system)appbaseusers/orgs/appcodes与 rbac 表沿用基础包自带结构,不在本文重复。
7. **预留字段约定**:二期对接预留字段一律带明确默认值与字典枚举位(如 esign_status='not_enabled'、id_source='manual'、send_channel='site'),不参与一期业务分支。
## 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 │ 提醒规则
│ ▼ │ │ sys_openapp │ API开放预留
│ 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 │ ▼
│ org_headcount_scheme │ ┌──────────────┐
│ └ headcount_item │ │ flow_def │ 流程定义
│ └ headcount_snapshot│ │ flow_form_def│ 表单定义(引用花名册字段)
│ org_project(F17) │ │ flow_node_def│ 节点(审批人/字段权限)
│ └ org_project_post │ │ flow_role │ 审批角色
│ │审批流转 │ │ flow_instance│ 实例 ──► flow_task(待办)
└────────┴──────────────┴────►│ │ └► flow_op_log
biz_type+biz_id └──────────────┘
hr-report 无自有表:只读聚合 org_/roster_/flow_ 表,叠加 sys_data_scope 范围过滤。
```
核心关系说明:
- `roster_employee` 为全系统员工数据唯一事实源;`org_entry/regularization/transfer/leave/concurrent_post` 通过 `employee_id`(入职审批阶段可为空)关联,审批通过后经 hr-roster `roster_writeback` 更新主档。
- 所有审批类记录通过 `flow_instance_id` 关联流程实例;`flow_instance.biz_type + biz_id` 反向定位业务单据,流程完成后回调业务模块回写。
- **编制F16**`org_headcount_scheme` 1─N `headcount_item`(细分额度);`headcount_snapshot` 按日快照历史;员工异动回写后同步触发占编重算。占编范围条件以 JSON 表达(员工类型/状态/职位/职级/自定义字段),与 roster_employee + roster_field_value 联查计数。
- **项目式组织F17**`org_project` 为横向组织(自引用多层级),员工经 `org_project_post` 同时挂纵向部门roster_employee.org_id与横向项目横向职务体系复用 org_job 表org_job.job_category=horizontal 区分,被花名册/薪酬引用)。
- 所有表与 appbase.users 之间为逻辑外键operator_id/leader_id/approver_id不建物理外键sqlor 惯例,跨模块解耦)。
## 3. models JSON 示例规范格式json2ddl 输入)
`hr-roster/models/roster_employee.json`(含 D1 证件字段组扩展):
```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_type", "title": "证件类型", "type": "varchar", "length": 16, "default": "id_card"},
{"name": "id_number_cipher", "title": "证件号密文", "type": "varchar", "length": 256},
{"name": "id_number_hash", "title": "证件号哈希", "type": "varchar", "length": 64},
{"name": "id_valid_from", "title": "证件有效期起", "type": "date"},
{"name": "id_valid_to", "title": "证件有效期止(长期=9999-12-31)", "type": "date"},
{"name": "id_authority", "title": "证件签发机关", "type": "varchar", "length": 128},
{"name": "id_source", "title": "证件信息来源", "type": "varchar", "length": 16, "default": "manual"},
{"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": "probation_end_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": "prev_employee_id", "title": "复职关联原档案ID", "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_probation_end", "fields": ["probation_end_date"]},
{"name": "idx_direct_leader", "fields": ["direct_leader_id"]},
{"name": "idx_prev_employee", "fields": ["prev_employee_id"]}
],
"codes": [
{"name": "gender", "source": "appcodes", "code": "GENDER"},
{"name": "employee_type", "source": "appcodes", "code": "EMP_TYPE"},
{"name": "employee_status", "source": "appcodes", "code": "EMP_STATUS"},
{"name": "id_source", "source": "appcodes", "code": "ID_SOURCE"}
]
}
```
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. 表结构设计49 张业务表)
> 公共列约定:凡标【审计】的表均含 `created_by/updated_by/created_at/updated_at`;日志/快照类表仅含 `created_at`。DDL 示例见 §5。
> v3.0 变化hr-org 18→23+编制 3 表+项目式 2 表、hr-system 7→8+sys_openapp 预留、roster_employee/org_entry/org_leave_handover 字段扩展;合计 **49 张**
### 4.1 hr-org 组织人事23 张,前缀 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/F17 | id, job_code, job_name, job_category(vertical/horizontalF17 横向职务), status, sort_no, remark【审计】 | uk_job_code; idx_job_category |
| 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_type, id_number_cipher/hash, id_valid_from/id_valid_to/id_authority/id_source(手工录入 D1), 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(none/invited/filled), **register_token, register_url, qrcode_file, register_expire**(登记链接/二维码,扫码入职降级), flow_instance_id, remark【审计】 | idx_entry_status; idx_hire_date; idx_flow_instance_id; uk_register_token |
| 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/**dingtalk_resource(钉钉资源交接占位,D3)**/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 |
| 19 | org_headcount_scheme | 编制方案F16 | id, scheme_name, cycle_type(year/quarter/month字典HEADCOUNT_CYCLE), cycle_start, cycle_end, status(active/inactive), remark【审计】 | idx_cycle(cycle_start,cycle_end); idx_status |
| 20 | headcount_item | 编制细分项F16 | id, scheme_id, scope_json(占编范围:员工类型/状态/职位/职级/自定义字段条件), seg_json(细分维度,可空=整体), head_limit(int), remark【审计】 | idx_scheme_id |
| 21 | headcount_snapshot | 编制快照F16 历史回溯/实时计数) | id, scheme_id, item_id, snap_date, used_count(int), over_count(int超编数), created_at | uk(scheme_id,item_id,snap_date); idx_snap_date |
| 22 | org_project | 项目式组织F17 | id, project_code, project_name, parent_id(自引用多层级), owner_id(负责人), start_date, end_date, project_status(active/expired/inactive), attrs_json(项目属性), sort_no【审计】 | uk_project_code; idx_parent_id; idx_project_status |
| 23 | org_project_post | 项目任职F17 员工挂横向组织) | id, project_id, employee_id, job_id(横向职务,引用 org_job job_category=horizontal), start_date, end_date, status(active/expired)【审计】 | uk(project_id,employee_id,job_id,start_date); idx_employee_id |
### 4.2 hr-roster 花名册7 张,前缀 roster_
| # | 表 | 用途 | 关键字段 | 关键索引 |
|---|---|---|---|---|
| 24 | roster_field_group | 字段分组F03 | id, group_code, group_name(工作信息/个人信息/绩效结果/培训记录), sort_no, status【审计】 | uk_group_code |
| 25 | 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 |
| 26 | roster_employee | 员工主档F03 | 见 §3 models 示例(含证件字段组/probation_end_date/prev_employee_id | 见 §3 |
| 27 | 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 |
| 28 | roster_empno_rule | 工号规则F03 | id, rule_name, prefix, match_field(如company_id), match_value, seq_length, current_seq(int), status【审计】 | — |
| 29 | roster_timeline | 员工时间轴F03/F12 联动) | id, employee_id, event_type(entry/regular/transfer/leave/concurrent/contract/field_change/headcount/project/migrate), event_date, title, content_json, source_type, source_id, created_at | idx_emp_date(employee_id,event_date) |
| 30 | roster_type_rule | 员工类型字段规则F03 分类管理) | id, employee_type, field_rules_json(按类型必填/隐藏字段), status【审计】 | uk(employee_type) |
### 4.3 hr-flow 流程审批7 张,前缀 flow_
| # | 表 | 用途 | 关键字段 | 关键索引 |
|---|---|---|---|---|
| 31 | 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/**attendance_\*桩位**), fields_json(引用roster_field_def或自定义项), status【审计】 | uk_form_code |
| 32 | flow_def | 流程定义F10 | id, flow_code, flow_name, form_id, biz_type, match_cond_json(员工类型/部门匹配条件), version, status【审计】 | uk_flow_code; idx_biz_type |
| 33 | 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 |
| 34 | flow_role | 审批角色F10 | id, role_name, flow_scope_json(可用流程), op_perm_json(操作权限), data_scope_json(数据查看范围), status【审计】 | — |
| 35 | 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 |
| 36 | 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 |
| 37 | 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_
| # | 表 | 用途 | 关键字段 | 关键索引 |
|---|---|---|---|---|
| 38 | contract_type | 合同类型F09 自定义) | id, type_code, type_name(劳动合同/保密协议/竞业协议…), status【审计】 | uk_type_code |
| 39 | contract_template | 合同模板F09 | id, template_name, type_id, file_path, field_marks_json(占位符映射), status【审计】 | — |
| 40 | 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, text_file_path(模板生成合同文本,D4), flow_instance_id, remind_rule_id, esign_status(not_enabled/待二期流转,D4), remark【审计】 | idx_employee; idx_end_date; idx_status |
| 41 | contract_remind_rule | 到期提醒规则F09 | id, rule_name, days_before(int), target_role(self/leader/hr), content_template, status【审计】 | — |
### 4.5 hr-system 权限日志与通用服务8 张,前缀 sys_
| # | 表 | 用途 | 关键字段 | 关键索引 |
|---|---|---|---|---|
| 42 | sys_data_scope | 数据范围F11 | id, admin_user_id(管理员), scope_type(org/field), org_ids_json(组织维度,含子树), field_ids_json(花名册字段维度), remark【审计】 | idx_admin_user |
| 43 | sys_audit_log | 操作日志F12只增不改 | id, module, target_type, target_id, operation(create/update/delete/import/export/approve/login/migrate), 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) |
| 44 | sys_message | 站内消息F15 | id, receiver_id, msg_type(todo/approval/remind/care/notice), title, content, biz_type, biz_id, send_channel(site; sms/email预留 D9), is_read, created_at | idx_receiver_read(receiver_id,is_read); idx_created_at |
| 45 | sys_remind_rule | 通用提醒规则F15 多场景) | 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) |
| 46 | sys_announcement | 企业公告F15 | id, title, content, publish_scope_json, publish_time, status(draft/published/offline), created_by【审计】 | idx_status |
| 47 | sys_policy | 企业政策F15 | id, title, file_path, view_scope_json, downloadable(0/1), publish_time, status, created_by【审计】 | idx_status |
| 48 | sys_care_config | 关怀配置F15 生日/周年) | id, care_type(birthday/anniversary), template, enable(0/1), push_target(employee/leader), updated_by, updated_at | uk_care_type |
| 49 | sys_openapp | API 开放应用一期预留FEAT-B1-01⑦ | id, app_key, app_secret_cipher, app_name, scope_json(授权资源), rate_limit(int), status(active/inactive)【审计】 | uk_app_key |
## 5. 核心表 DDL 示例json2ddl 生成等价物)
```sql
-- roster_employee完整字段见 §3 models JSON此处为等价 DDL 含证件字段组)
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_type VARCHAR(16) DEFAULT 'id_card' COMMENT '证件类型',
id_number_cipher VARCHAR(256) DEFAULT NULL COMMENT '证件号密文',
id_number_hash VARCHAR(64) DEFAULT NULL COMMENT '证件号哈希(唯一)',
id_valid_from DATE DEFAULT NULL COMMENT '证件有效期起',
id_valid_to DATE DEFAULT NULL COMMENT '证件有效期止(长期=9999-12-31)',
id_authority VARCHAR(128) DEFAULT NULL COMMENT '证件签发机关',
id_source VARCHAR(16) DEFAULT 'manual' COMMENT '证件来源(字典ID_SOURCE: manual/card_reader预留)',
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,
probation_end_date DATE DEFAULT NULL COMMENT '试用期止(预计转正日,转正提醒依据)',
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 '直属主管',
prev_employee_id VARCHAR(32) DEFAULT NULL COMMENT '复职关联原档案ID(F04-5)',
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_probation_end (probation_end_date),
KEY idx_direct_leader (direct_leader_id),
KEY idx_prev_employee (prev_employee_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 '业务类型(字典FLOW_BIZ_TYPE)',
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/migrate',
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='操作日志(只增)';
-- F16 编制管理(新增)
CREATE TABLE org_headcount_scheme (
id VARCHAR(32) NOT NULL,
scheme_name VARCHAR(128) NOT NULL COMMENT '方案名称',
cycle_type VARCHAR(16) NOT NULL COMMENT '周期(字典HEADCOUNT_CYCLE: year/quarter/month)',
cycle_start DATE NOT NULL, cycle_end DATE NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'active',
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),
KEY idx_cycle (cycle_start, cycle_end),
KEY idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='编制方案';
CREATE TABLE headcount_item (
id VARCHAR(32) NOT NULL,
scheme_id VARCHAR(32) NOT NULL COMMENT '编制方案',
scope_json TEXT NOT NULL COMMENT '占编范围条件(员工类型/状态/职位/职级/自定义字段)',
seg_json TEXT DEFAULT NULL COMMENT '细分维度(空=整体)',
head_limit INT NOT NULL DEFAULT 0 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),
KEY idx_scheme_id (scheme_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='编制细分项';
CREATE TABLE headcount_snapshot (
id VARCHAR(32) NOT NULL,
scheme_id VARCHAR(32) NOT NULL,
item_id VARCHAR(32) NOT NULL COMMENT '细分项',
snap_date DATE NOT NULL COMMENT '快照日期',
used_count INT NOT NULL DEFAULT 0 COMMENT '占编人数',
over_count INT NOT NULL DEFAULT 0 COMMENT '超编数(0=未超编)',
created_at TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY uk_scheme_item_date (scheme_id, item_id, snap_date),
KEY idx_snap_date (snap_date)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='编制快照(历史回溯)';
-- F17 项目式组织(新增)
CREATE TABLE org_project (
id VARCHAR(32) NOT NULL,
project_code VARCHAR(32) NOT NULL COMMENT '项目编码',
project_name VARCHAR(128) NOT NULL COMMENT '项目名称',
parent_id VARCHAR(32) DEFAULT NULL COMMENT '上级项目(多层级)',
owner_id VARCHAR(32) DEFAULT NULL COMMENT '负责人',
start_date DATE DEFAULT NULL, end_date DATE DEFAULT NULL COMMENT '时间范围',
project_status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/expired/inactive(到期自动标识)',
attrs_json TEXT DEFAULT NULL COMMENT '项目属性',
sort_no INT DEFAULT 0,
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_project_code (project_code),
KEY idx_parent_id (parent_id),
KEY idx_project_status (project_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目式组织';
CREATE TABLE org_project_post (
id VARCHAR(32) NOT NULL,
project_id VARCHAR(32) NOT NULL COMMENT '项目组织',
employee_id VARCHAR(32) NOT NULL COMMENT '员工',
job_id VARCHAR(32) DEFAULT NULL COMMENT '横向职务(org_job.job_category=horizontal)',
start_date DATE DEFAULT NULL, end_date DATE DEFAULT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/expired',
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_proj_emp_job (project_id, employee_id, job_id, start_date),
KEY idx_employee_id (employee_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目任职(横向)';
```
## 6. 索引与性能策略
1. 100 人规模全表扫描亦可满足 ≤500ms但仍按查询模式建索引列表筛选列status/org_id/hire_date/end_date、EAV 值表 uk(employee_id,field_id)、待办 idx(approver_id,task_status)、转正提醒 idx(probation_end_date)。
2. 组织树、职位职级主数据一次性全量加载≤200/≤500 行),前端缓存,无需分页。
3. EAV 查询模式:花名册列表先按主表条件分页取员工,再批量 `IN` 查值表拼装(每页 ≤50 人 × 显示字段数),避免 EAV 行转列大 JOIN。
4. 报表hr-report直接 SQL 聚合sor.sqlExe 只读100 人规模不建物化视图,满足"延迟 ≤5 分钟"实为实时sys_audit_log 按月保留,冷数据归档不删除。
5. 编制计数headcount_snapshot 以"异动事件触发 + 每日兜底扫描"双机制维护;实时查询取最新 snap_date历史回溯按 snap_date 精确取数F16 验收③)。
6. 唯一性:工号、组织编码、项目编码、职位/职务/职级/职等编码、审批编号、登记表 token 均唯一索引;证件号经哈希列唯一(密文为非确定性加密,哈希列承担唯一性与黑名单匹配)。
## 7. 数据字典appbase appcodesinit/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 | 员工状态(待入职/试用/正式/待离职/离职) |
| ID_TYPE | id_card/passport/other | 证件类型 |
| ID_SOURCE | manual/card_reader(预留,二期) | 证件信息来源D1 |
| POS_CATEGORY | management/professional/skill | 职位类别 |
| JOB_CATEGORY | vertical/horizontal | 职务类别F17 横向职务) |
| TRANSFER_TYPE | promotion/demotion/position_change/org_adjust | 调动类型 |
| LEAVE_REASON | personal/company/contract_expire/retire/other | 离职原因 |
| HANDOVER_TYPE | approval/file/subordinate/permission/dingtalk_resource(占位)/other | 离职交接项类型D3 |
| CONTRACT_STATUS | active/expired/stopped/renewing | 合同状态 |
| ESIGN_STATUS | not_enabled/signing/signed(后两者二期启用) | 电子签状态D4 预留) |
| FLOW_BIZ_TYPE | entry/regular/transfer/leave/handover/concurrent/contract_sign/contract_renew/contract_change/contract_stop/roster_self_edit/attendance_*(桩位) | 审批业务类型 |
| INST_STATUS | running/approved/rejected/cancelled | 实例状态 |
| REMIND_SCENE | entry/regular/leave/retire/contract_expire/health_cert/social_insurance/custom | 提醒场景≥6 类F15 验收④) |
| HEADCOUNT_CYCLE | year/quarter/month | 编制周期F16 |
| PROJECT_STATUS | active/expired/inactive | 项目状态F17到期自动 expired |
| MSG_CHANNEL | site/sms(预留)/email(预留) | 消息渠道D9 |
| AUDIT_OP | create/update/delete/import/export/approve/login/migrate | 操作类型 |
| ENTRY_STATUS | pending_approval/pending_entry/entered/cancelled/blocked | 入职状态 |
| REGISTER_STATUS | none/invited/filled | 登记表状态 |
枚举一律不硬编码于 dspyCRUD 下拉经 models `codes` 段引用。
## 8. staff-mgr 数据迁移策略v1 → 一期NFR-8
迁移工具:`repos/hr-system` 仓内规划 `scripts/migrate_staff_mgr.py`Python + sqlor幂等可重跑输出核对报告总数一致 + 抽样字段一致)。
| v1 源表staff-mgr | 目标表 | 映射规则 |
|---|---|---|
| staff_department_cache | org_unit | 按树形重建 parent_idorg_code=DEPT{id}status 映射 active/inactive |
| staff_employee | roster_employee | employee_no/name/gender/phone/email 直映id_number AES 解密后按新方案重加密cipher+hashid_source='manual',证件有效期/签发机关置空待补department_id→org_idposition 文本→预置 org_position无匹配则建"未定职"status: active→regular、probation→probation、inactive→lefthire_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_infotype_id 映射正式/外包/实习协议) |
| staff_change_log | roster_timeline | change_type→event_type(transfer/field_change)old/new 值入 content_jsonevent_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 去重,重跑仅补差;证件号哈希冲突时输出冲突报告人工裁决(冲突员工按离职记录保留,不入在职)。
3. **范围**:默认"在职 + 离职保留档案"全量;仅迁在职/含历史的最终范围与切换时间点待 PM 确认SRS §11-Q3脚本参数 `--scope=active|all` 支持两种口径。
4. **切换**UAT 通过后一次性迁移+双库比对 → staff-mgr 服务下线、仓库冻结只读(保留一个迭代周期)。
5. 迁移全程写 sys_audit_logoperation=migrate迁移数据在时间轴/日志中可辨识。
## 9. 与需求验收项的映射(摘选)
| 验收项 | 数据支撑 |
|---|---|
| F01-4 时间轴留痕 | org_unit_change |
| F01-5 历史架构图 | org_unit.effective_date/expire_date + org_unit_change 回放 |
| F02-1~5 五套体系 | org_job/position/sequence/grade_level/grade_rank |
| 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 身份证手工录入D1 | roster_employee/org_entry 证件字段组 + id_source='manual' |
| F04-5 复职 | roster_employee.prev_employee_id |
| F04-6 黑名单拦截 | org_blacklistid_number_hash 匹配) |
| F05-3 转正提醒 | roster_employee.probation_end_date + sys_remind_rule(scene=regular) |
| F07-3 钉钉交接占位D3 | org_leave_handover.item_type=dingtalk_resource |
| F07-5 离职证明 | org_leave.certificate_filefiles/ 存储) |
| F09-6 电子签预留D4 | contract_info.esign_status + contract_template.text_file_path |
| 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 |
| F13-6 报表数据范围受控 | 聚合查询叠加 sys_data_scope |
| F15-4 多场景提醒≥6 类) | sys_remind_rule(scene_code) + REMIND_SCENE 字典 |
| F16-1~6 编制 | org_headcount_scheme/headcount_item/headcount_snapshot |
| F17-1~3 项目式组织 | org_project/org_project_post + org_job(job_category=horizontal) |
| FEAT-B1-01⑦ API 开放预留 | sys_openapp一期不启用 |

View File

@ -1 +1,71 @@
完整正文 7,103B 已落盘并推送git commit 5a96df5。目录§0范围与角色 §1 F01~F17↔FEAT-B1-01~12映射(90条验收项) §2功能-模块-表落点 §3设计文档索引 §4范围外/降级项
# 一期批次1功能清单F01~F17ocai 口径)
- 版本v2.1批次1设计定稿v2.1 变更:对齐 SRS v3.1 —— 批次1范围扩入 F16 编制管理FEAT-B1-10、F17 项目式组织FEAT-B1-11合计 90 条验收项;补充 F01~F15 ↔ FEAT-B1 编号映射)
- 需求基线:`docs/00-requirement/requirement-spec.md`SRS v3.1+ `docs/00-requirement/iteration1-function-detail.md`
- 应用hr-web`apps/hr-web.md`);模块定义:`modules/hr-*.md`
## 0. 范围与角色
一期批次1 = 组织人事底座 + 系统管理与权限基座,规模 100 人账号。技术口径统一 ocai前端 bricks + dspy 声明式页面,后端 ahserverPython数据层 apppublic/sqlorMariaDB库 hrs
| 角色 | 代码 | 主要能力 |
|---|---|---|
| 系统管理员 | admin | 全部数据与配置、角色/管理员/数据范围、操作日志 |
| 人事 | hr | 组织、花名册、入转调离、合同、流程配置、报表、编制 |
| 部门经理 | manager | 数据范围内入转调离审批、团队统计、关怀提醒 |
| 员工(自助) | employee | 个人档案、发起审批、待办、企业政策/公告 |
脱敏基线身份证号全角色脱敏前3后3手机号前3后4薪资/职级敏感字段仅 admin/hr 可见(由 roster_field_def.sensitive 驱动)。
## 1. 功能 → FEAT 映射与清单F01~F17共 90 条验收项)
| # | 功能 | 对应 FEATSRS v3.1 | 承载模块 | 表前缀 | 验收项数 | 关键交付 | 范围边界 |
|---|---|---|---|---|---|---|---|
| F01 | 组织架构 | FEAT-B1-02 | hr-org | org_ | 6 | 组织树/架构图(含 as_of 历史)/新建变更停用移动/字段自定义/时间轴/Excel 导入/合同公司 | 全量 |
| F02 | 职位职级体系 | FEAT-B1-03 | hr-org | org_ | 5 | 职位/职务/职级/职等/序列 CRUD + 导入导出 + options | 全量 |
| F03 | 花名册 | FEAT-B1-04 | hr-roster | roster_ | 8 | 自定义字段(EAV)/分组/工号多规则/自助修改+审核/时间轴/类型规则/搜索/导入导出 | 附件预览依赖 files/ |
| F04 | 入职管理 | FEAT-B1-05 | hr-org | org_ | 7 | 审批入职/手动批量入职/登记表邀请(扫码降级)/身份证手工录入(D1)/黑名单拦截/入职通知/复职 | 读卡二期、对外二维码二期 |
| F05 | 转正管理 | FEAT-B1-06 | hr-org | org_ | 4 | 审批/手动转正、回写花名册、转正提醒 | 全量 |
| F06 | 调动管理 | FEAT-B1-06 | hr-org | org_ | 4 | 调动查询/审批(晋升/降级/调岗/组织调整)/批量调动/编制联动提醒 | 全量 |
| F07 | 离职管理 | FEAT-B1-07 | hr-org | org_ | 7 | 审批/手动离职、交接(钉钉占位 D3)、离职证明、黑名单、信息存储 | 钉钉资源交接二期 |
| F08 | 兼岗管理 | FEAT-B1-04 | hr-org | org_ | 3 | 一人多兼岗记录、兼岗审批、通过自动同步 | 全量 |
| F09 | 合同台账 | FEAT-B1-08 | hr-contract | contract_ | 6 | 台账/类型自定义/模板(生成文本 D4)/审批(新签续签变更终止)/到期提醒 | 电子签二期(esign_stub 预留) |
| F10 | 流程审批 | FEAT-B1-01 | hr-flow | flow_ | 7 | 表单/流程/节点配置、审批角色、流转引擎、查询导出、打印;考勤流程桩位 | 薪酬/组合审批批次2 |
| F11 | 权限管理 | FEAT-B1-01 | hr-system | sys_ | 4 | 管理角色,人员范围(组织维度+花名册字段维度),管理员管理 | 全量 |
| F12 | 操作日志 | FEAT-B1-01 | hr-system | sys_ | 4 | 全量写操作留痕、前后对比、时间/类型查询 | 全量 |
| F13 | 人事报表 | FEAT-B1-12 | hr-report | —(只读) | 6 | 花名册/入职/转正/调岗/离职五类分析,数据范围受控,可导出 | 全量 |
| F14 | 工作台 | FEAT-B1-09 | hr-system | sys_ | 5 | 员工/经理/管理员三工作台聚合 | 工资条/绩效/考勤桩位 |
| F15 | 员工服务与提醒 | FEAT-B1-09 | hr-system | sys_ | 5 | 生日周年关怀、政策、公告、多场景到期提醒(≥6类) | 站内消息优先,短信/邮件预留(D9) |
| F16 | 编制管理 | FEAT-B1-10 | hr-org | org_/headcount_ | 6 | 编制方案/占编范围/细分/超缺编状态/异动管控提醒/历史编制 | 全量(一期提醒不硬拦截) |
| F17 | 项目式组织 | FEAT-B1-11 | hr-org | org_ | 3 | 纵向部门×横向项目组组合、横向组织信息、横向职务体系 | 全量 |
合计6+5+8+7+4+4+7+3+6+7+4+4+6+5+5+6+3 = **90 条可验收项**F01~F15 逐项输入/处理/输出见 `iteration1-function-detail.md`F16/F17 按 SRS v3.1 §3.1 FEAT-B1-10/11 验收标准执行)。
## 2. 功能 → 模块 → 数据表落点
| 模块 | 功能 | 主要数据表 |
|---|---|---|
| hr-org | F01/F02/F04/F05/F06/F07/F08/F16/F17 | 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、org_headcount_scheme/headcount_item/headcount_snapshot、org_project/org_project_post23 张) |
| hr-roster | F03 | roster_field_group, roster_field_def, roster_employee, roster_field_value, roster_empno_rule, roster_timeline, roster_type_rule7 张) |
| hr-flow | F10 | flow_form_def, flow_def, flow_node_def, flow_role, flow_instance, flow_task, flow_op_log7 张) |
| hr-contract | F09 | contract_type, contract_template, contract_info, contract_remind_rule4 张) |
| 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, sys_openapp8 张,末张为 API 开放预留) |
**49 张业务表**,详见 `database-design.md`
## 3. 设计文档索引
| 文档 | 内容 |
|---|---|
| architecture.md | 系统架构、技术选型、模块划分与依赖、部署9182/MariaDB hrs、安全、非功能、降级项设计专章、API 开放规范 |
| database-design.md | ER、49 表结构、索引、数据字典、models JSON、staff-mgr 迁移 |
| api-design.md | dspy 端点清单(约 120 个)、通用约定、鉴权、错误码、典型调用链、降级桩端点汇总 |
| ui-design.md | 布局、路由表、页面组件树、核心交互流程、设计规范、页面-接口追溯 |
| iteration1-task-breakdown.md | 技术可行性、风险、开发任务拆解T01~T27约 92 人日,面向 develop 角色) |
## 4. 批次1范围外/降级项(既定)
- 范围外:钉钉同步(组织/人员/考勤/智能人事、薪酬流程与组合审批批次2、招聘全部批次3、电子签、税局在线申报、短信网关、浏览器插件。
- 一期降级SRS §9设计落点见 architecture.md §10D1 身份证手工录入、D3 离职交接钉钉占位、D4 合同模板文本+esign_stub、D9 站内消息兜底、扫码入职内网登记链接/二维码、考勤/绩效/工资条工作台桩位。
- 以上均在一期做字段/桩端点/流程位预留,二期对接不改表结构主干。

View File

@ -1 +1,114 @@
完整正文 13,471B 已落盘并推送git commit 5a96df5。目录§1技术可行性/风险/降级任务落点 §2 T01~T27任务拆解(依赖/估时约92人日/验收对照) §3交付与集成验收定义
# 一期批次1总体设计 —— 技术可行性与开发任务拆解hr-web
- 版本v2.0批次1设计定稿v2.0 变更:对齐 SRS v3.1 —— 范围扩入编制(F16)/项目式(F17)、新增降级项任务、部署任务与开放接口桩任务;任务编号 T01~T27可直接用于 develop 角色创建开发任务)
- 状态:**设计定稿批次1评审修订版**
- 基线:`docs/01-design/architecture.md`(架构)+ `database-design.md`49 表)+ `api-design.md`(端点清单)+ `ui-design.md`(页面结构)
- 需求基线:`docs/00-requirement/requirement-spec.md`SRS v3.1+ `iteration1-function-detail.md`F01~F1581 条)+ approved-features.mdFEAT-B1-01~12
## 1. 技术可行性说明
### 1.1 技术栈成熟度ocai 规范)
| 能力诉求 | ocai 设施 | 成熟度结论 |
|---|---|---|
| 声明式 CRUD 页面 | json/*.json + xls2ui 自动生成 DataViewer/Form/Tree | 成熟产线既有模式批次1约 25 个 CRUD 页面零手写 |
| 组织树/架构图 | Tree widget + org_unit parent_id 自引用 + as_of 历史查询 | 可行;历史架构按 effective_date/expire_date + org_unit_change 回放 |
| 自定义字段(花名册/组织) | EAV 双表 + field_def 元数据驱动表单渲染 | 可行;列表页"主表分页+值表批量拼装"规避 EAV 性能问题 |
| 审批引擎 | flow_def/node_def JSON 配置 + flow_instance/task 状态机 | 可行;一期仅串行节点 + any/all 通过规则,不做并行分支(满足 F10 验收);四类人事流程模板 init/data.json 预置 |
| 审批通过自动回写 | biz_type+biz_id 关联 + ServerEnv 注册回调 hook | 可行roster_writeback 唯一入口,回写后联动 headcount_check 与 timeline |
| 批量导入导出 | ahserver 后台任务 + openpyxl + files/ 结果文件 | 可行500 行 ≤30s 指标NFR-1在 100 人量级轻松满足 |
| 数据范围权限 | rbac 路径级 + sys_data_scope组织/字段双维度)查询叠加 | 可行;查询/报表/导出三处强制叠加 |
| 脱敏/审计 | roster_field_def.sensitive + sys_audit_log 前后 JSON | 可行 |
| 图表报表 | bricks Chart widgets | 可行;聚合 SQL 只读查询≤3s 指标满足 |
| 提醒推送 | cron 扫描 remind_scan + sys_message 站内消息 | 可行≥6 场景;短信/邮件 send_channel 预留 |
| 编制实时计数 | 异动事件触发重算 + headcount_snapshot 快照 | 可行100 人规模事件内同步重算满足"1 分钟内刷新" |
| 项目式组织 | org_project 自引用 + org_project_post 关联表 | 可行;横向职务复用 org_job(job_category=horizontal) |
| 入职登记链接/二维码 | token + tmpl 页面 + qrcode 图片生成files/ | 可行;内网 token 鉴权免登录 |
| 合同文本生成 | openpyxl/python-docx 模板占位符替换 | 可行;一期 docx/pdf 打印下载,电子签二期 |
### 1.2 规模与性能
100 人账号、单实例部署ahserver:9182 + MariaDB(hrs) + Redis。最大表量级花名册 2000 行(含离职)、字段值 ≤2000×100=20 万行、审计日志年级 ≤10 万行、编制快照 365×细分项数。全部查询在索引覆盖下远低于 500ms 指标。
### 1.3 主要风险与对策
| 风险 | 等级 | 对策 |
|---|---|---|
| EAV 自定义字段在列表页的筛选/排序复杂度 | 中 | 筛选支持"主表字段 + 至多 3 个自定义字段等值匹配",排序仅主表字段;已知限制写入 UAT 说明 |
| 审批引擎配置化过度导致返工 | 中 | 锁定"串行节点、any/all、字段权限、抄送"能力边界;并行/条件分支留 flow_node_def JSON 扩展位 |
| staff-mgr 旧数据语义差异status/加密算法) | 中 | 迁移脚本内置映射表 + 核对报告 + UAT 双库比对;迁移范围待 PM 确认SRS Q3脚本支持 --scope 参数 |
| 6 模块并行开发契约漂移 | 中 | T01 先行冻结表定义 models JSON 与 api-design 端点签名,变更走设计评审 |
| 提醒场景字段依赖(健康证/社保等花名册字段未建) | 低 | init/data.json 预置 REMIND_SCENE 对应字段定义remind_scan 按 field_def 取数 |
| 编制占编范围条件表达力 | 低 | scope_json 采用 {conds:[{field,op,value}]} 结构,支持等值/包含;复杂表达式二期扩展 |
### 1.4 降级项任务落点SRS §9批次1相关
| 降级项 | 一期落点任务 |
|---|---|
| D1 身份证读卡→手工录入 | T06证件字段组/T13入职表单证件分组/T15档案证件展示脱敏 |
| 扫码入职→内网登记链接/二维码 | T13entry_register 页面+token+二维码) |
| D3 钉钉交接→占位项 | T17交接项 dingtalk_resource 类型手工登记) |
| D4 电子签→模板文本+桩 | T19contract_text_gen + esign_stub |
| D9 短信→站内兜底 | T16send_channel=sitesms/email 枚举预留) |
| 考勤/绩效/工资条桩位 | T10attendance_* 表单桩)/T21工作台桩位卡片 |
| API 开放接口预留 | T26sys_openapp 表 + /openapi/v1/ping 桩) |
## 2. 开发任务拆解T01~T27契约先行
> 依赖关系T01~T02 为契约冻结阶段,全量先行;其后按模块并行。工作量单位:人日(估算,供 PM 排期。每个任务含验收对照F#/FEAT 编号develop 角色可直接按任务建卡。
### 阶段0 契约与脚手架
| 编号 | 任务 | 内容/产出 | 验收对照 | 依赖 | 估时 |
|---|---|---|---|---|---|
| T01 | 数据契约冻结 | 6 模块仓库建仓hr_org/hr_roster/hr_flow/hr_contract/hr_reporthr-system 复用既有仓);**49 张** models/*.json 全量提交json2ddl 生成 DDL 导入 hrs 库验证init/data.json 字典(含 HEADCOUNT_CYCLE/PROJECT_STATUS/ID_SOURCE 等新增字典) | database-design §4 全表 | — | 5 |
| T02 | 应用脚手架 | hr-web 应用仓app/hr_web.py、conf/config.json 含 processors/indexes/session/databases.hrs、build.sh、systemd unitappbase/rbac 加载验证;登录走通;内置 admin+四角色初始化 | SRS §5.2-4 | T01 | 2 |
### 阶段1 主数据与底座(可并行)
| 编号 | 任务 | 内容/产出 | 验收对照 | 依赖 | 估时 |
|---|---|---|---|---|---|
| T03 | hr-org 组织管理 | org_unit CRUD/树/停用/移动(子树+员工联动、org_field_def 自定义字段、org_unit_change 时间轴、org_import≥200行、org_tree.ui/org_chart.uias_of+导出)、合同公司 company CRUD | F01 全 6 项 + FEAT-B1-02 | T01,T02 | 5 |
| T04 | hr-org 职位职级 | org_job(含 job_category 横向位)/position/sequence/grade_level/grade_rank CRUD + 停用启用联动 + 导入导出 + options 端点 | F02 全 5 项 + FEAT-B1-03 | T03 | 3 |
| T05 | hr-roster 字段体系 | roster_field_group/field_def/type_rule/empno_rule 配置页与端点、工号生成器(多规则+冲突报错、field_config.ui 拖拽排序 | F03 验收 1/3/6 | T01,T02 | 4 |
| T06 | hr-roster 花名册主体 | roster_employee CRUD**含证件字段组手工录入 D1**、EAV 值表读写、roster_list/employee_detail/timeline、脱敏与字段可见、自助修改+审核、复职 prev_employee_id 关联 | F03 验收 2/4/5/7 + F04-4/5 + SRS §2.2-4 | T05,T03,T04 | 6 |
| T07 | hr-roster 导入导出 | roster_import新增/修改≥500 行含更新匹配)、模板生成(按字段定义+类型规则、roster_export字段/顺序/as_of强制数据范围 | F03 验收 8 | T06 | 3 |
| T08 | hr-system 权限底座 | 角色/管理员/数据范围sys_data_scope 双维度叠加、get_data_scope 注册、各模块查询/报表/导出叠加、role_admin.ui/data_scope.ui | F11 全 4 项 + SRS §2.2-1/2/3 | T02 | 4 |
| T09 | hr-system 审计底座 | write_audit_log全量写操作含导入导出/审批/登录,前后值+IP+ audit_log_list.ui 详情对比 | F12 全 4 项 + SRS §2.2-5 | T02 | 2 |
### 阶段2 审批引擎(关键路径)
| 编号 | 任务 | 内容/产出 | 验收对照 | 依赖 | 估时 |
|---|---|---|---|---|---|
| T10 | hr-flow 引擎核心 | flow_form_def/flow_def/flow_node_def/flow_role 配置(含考勤桩位 attendance_*、flow_start 状态机、task 生成与流转、flow_match、回调 hook 机制、init 预置人事四类流程模板 | F10 验收 1/2/3 + FEAT-B1-01 ①②③ | T02,T08 | 6 |
| T11 | hr-flow 审批界面 | todo/done/mine/received 列表、inst_detail 动态表单渲染节点字段权限、approve/reject/forward/withdraw、inst_print A4 | F10 验收 6/7 + F14-4 | T10 | 4 |
| T12 | hr-flow 查询导出 | inst_query/inst_export、审批角色数据范围生效验证 | F10 验收 3/6 + FEAT-B1-01 ④ | T10,T08 | 2 |
### 阶段3 入转调离与合同(依赖 T10 回调,可部分并行)
| 编号 | 任务 | 内容/产出 | 验收对照 | 依赖 | 估时 |
|---|---|---|---|---|---|
| T13 | 入职管理 | entry_approval含证件手工录入/entry_manual批量/**登记表邀请token+二维码+entry_register.tmpl扫码入职降级**/entry_register_submit/黑名单校验与高亮/入职通知/复职匹配 | F04 全 7 项 + FEAT-B1-05 | T10,T06 | 6 |
| T14 | 转正管理 | regular_apply自助/代发)/regular_manual/回写花名册(状态+转正日期)/转正提醒接入probation_end_date 提前 7 天可配) | F05 全 4 项 + FEAT-B1-06 转正 | T10,T06,T16 | 3 |
| T15 | 调动管理 | transfer_apply批量 ≥20 人明细)/transfer_cancel/回写档案+时间轴/调动查询(状态/类型/日期)/编制联动提醒接入 | F06 全 4 项 + FEAT-B1-06 调动 | T10,T06 | 4 |
| T16 | 提醒引擎 | sys_remind_rule≥6 场景)/care_config生日/周年文案)/remind_scan转正/合同/生日/周年/退休/离职生效扫描)+ sys_messagesend_channel=sitesms/email 预留 D9 | F15 提醒类验收 1/4/5 | T02 | 3 |
| T17 | 离职管理 | leave_apply/leave_manual/交接项(**含 dingtalk_resource 占位手工登记 D3**/到期自动生效leave_effect/离职证明 PDF 生成下载/一键黑名单/离职员工信息存储可查可改 | F07 全 7 项 + FEAT-B1-07 | T10,T06,T16 | 5 |
| T18 | 兼岗管理 | concurrent_apply/兼岗记录维护/审批通过自动同步(状态 active供薪酬引用 | F08 全 3 项 + FEAT-B1-04 兼岗 | T10,T06 | 2 |
| T19 | 合同台账 | contract_type/template/info CRUD + 批量导入 + 合同审批(新签/续签/变更/终止)+ **contract_text_gen 模板生成文本D4 打印下载)** + 到期提醒规则(误差 ≤1 天)+ esign_stub/esign_status 预留 | F09 全 6 项 + FEAT-B1-08 | T10,T06,T16 | 4 |
### 阶段4 编制/项目式/报表/工作台/服务与收尾
| 编号 | 任务 | 内容/产出 | 验收对照 | 依赖 | 估时 |
|---|---|---|---|---|---|
| T20 | 编制管理 | headcount_scheme/item CRUD + scope_json 占编范围编辑器 + headcount_check 异动联动(提醒不硬拦截)+ snapshot 快照/历史回溯 + headcount_board/config.ui | F16 全 6 项 + FEAT-B1-10 | T06,T13~T18 | 4 |
| T21 | 项目式组织 | org_project/org_project_post CRUD + project_tree.ui + 横向职务(job_category=horizontal)维护与 options + 到期自动标识 | F17 全 3 项 + FEAT-B1-11 | T04,T06 | 3 |
| T22 | 人事报表 | roster/entry/regular/transfer/leave 五类分析端点(维度可配置)+ report_board.ui 图表 + report_export与页面一致+ 全程数据范围 | F13 全 6 项 + FEAT-B1-12 | T06,T13~T18 | 4 |
| T23 | 工作台 | workbench_employee/manager/admin 聚合端点与三页面(**工资条/绩效/考勤桩位卡片**+ 消息铃铛 | F14 全 5 项 + FEAT-B1-09 工作台 | T10,T11,T16 | 3 |
| T24 | 员工服务 | 公告/政策发布与查询(查阅范围/下载权限、关怀文案配置、message_list | F15 服务类验收 1~3 + FEAT-B1-09 服务 | T16 | 2 |
| T25 | staff-mgr 迁移 | migrate_staff_mgr.py映射/解密重加密/幂等/--scope 参数/核对报告总数+抽样、UAT 双库比对、切换演练 | NFR-8 + SRS §11-Q3 参数化 | T06,T09 | 3 |
| T26 | API 开放预留与部署 | sys_openapp 表 + /openapi/v1/ping 桩端点部署脚本systemd/备份 crontab/监控探活脚本9182 端口测试+生产HTTPS 升级路径文档 | FEAT-B1-01 ⑦ + SRS §8 + NFR-3/5 | T02 | 3 |
| T27 | 集成联调与验收 | F01~F17 共 **90 条**验收项端到端回归;性能抽测(列表 ≤500ms/报表 ≤3s/导入 500 行 ≤30s权限与脱敏抽测SRS §10-2load_path 全路径注册核查;降级项 D1/D3/D4/D9/扫码登记 专项验证 | SRS §10 验收总纲 | 全部 | 5 |
**合计估算:约 92 人日**(不含 PM 排期缓冲。关键路径T01→T02→T10→T11→T13/T15/T17→T20/T22→T27。
## 3. 交付与验收定义
- 每个 T 任务交付模块仓代码models/json/wwwroot/init/scripts/skill/SKILL.md+ 对应功能验收项自测记录。
- 契约变更(表结构/端点签名)必须回改 docs/01-design 四份文档并评审。
- T27 通过标准90 条验收项全部通过P0FEAT-B1-01~05100% 通过;降级项按 SRS §9 验证桩位与降级方案生效D1 手工录入+脱敏、D3 交接占位、D4 模板文本+NOT_ENABLED 桩、D9 站内兜底、扫码登记内网闭环);性能/权限/脱敏抽测记录齐备SRS §10
- 批次1完成即满足批次2薪酬进入条件花名册/组织/流程/报表基线 + 权限日志基线 + 消息通道SRS §1.4)。

View File

@ -1 +1,297 @@
完整正文 23,929B 已落盘并推送git commit 5a96df5。目录§1总体布局 §2菜单路由表 §3 12组页面组件树 §4核心交互时序 §5设计规范 §6页面-接口追溯表
# 一期批次1总体设计 —— UI/页面设计hr-webocai 口径)
- 版本v3.0批次1设计定稿v3.0 变更:对齐 SRS v3.1 —— 新增编制看板(F16)/项目式组织(F17)页面、工作台工资条/绩效桩位、入职登记链接与二维码交互扫码入职降级、证件手工录入交互D1、合同文本生成打印、离职交接钉钉占位项
- 状态:**设计定稿批次1评审修订版**
- 规范依据ocai 技能集 bricks-framework、bricks-layout-patterns、module-development-specindex.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_unread_count.dspy 未读数)]
├── 内容区(HBox, flex:1)
│ ├── Menu(id:app.menu, width:220px)
│ │ ├── 工作台 → /hrsystem/workbench_*.ui按角色路由
│ │ ├── 组织管理 → /hrorg/index.ui
│ │ ├── 花名册 → /hrroster/index.ui
│ │ ├── 审批中心 → /hrflow/index.ui
│ │ ├── 合同管理 → /hrcontract/index.ui
│ │ ├── 编制管理 → /hrorg/headcount_board.uiF16
│ │ ├── 项目组织 → /hrorg/project_tree.uiF17
│ │ ├── 人事报表 → /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 历史/导出 PNG/XMind | A,H |
| /hrorg/position_list.ui 等 | 职位/职务/职级/职等/序列 CRUD | xls2ui 生成 DataViewer | A,H |
| /hrorg/company_list.ui | 合同公司台账 | CRUDFEAT-B1-02 | A,H |
| /hrorg/entry_workbench.ui | 入职工作台 | 待入职/审批中/黑名单高亮/登记二维码 | A,H |
| /hrorg/entry_register.tmpl | 入职登记表(免登录) | 候选人扫码填表页(内网 token 鉴权,扫码入职降级) | 匿名(token) |
| /hrorg/transfer_list.ui | 调动查询 | 待确定/已确定/已取消筛选 | A,H,M |
| /hrorg/leave_workbench.ui | 离职工作台 | 待离职名单/交接/证明/黑名单 | A,H,M |
| /hrorg/headcount_board.ui | 编制看板F16 | 方案/细分/超缺编状态/历史回溯 | A,H,M |
| /hrorg/headcount_config.ui | 编制配置F16 | 方案+细分项+占编范围条件编辑 | A,H |
| /hrorg/project_tree.ui | 项目式组织F17 | 项目树+属性+任职维护 | L |
| /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 |
| /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.uiF01
```
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(时间+操作人+类型 add/edit/disable/move/split/merge) + before/after 对比展开
```
交互Tree 节点点击 → urlwidget 刷新 org_detail 与 org_timelineparams_mapping 传 id停用前弹确认 PopupWindow停用后该组织在入职/调动表单 options 中不可选(服务端过滤 status=active组织移动后员工任职部门随组织联动服务端处理页面提示影响人数
### 3.2 组织架构图 /hrorg/org_chart.uiF01
```
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.uiF03CRUD 生成)
```
roster_list.ui = DataViewer(json/roster_employee_list.json 生成)
├── data_filter: keyword(姓名/工号 LIKE) + org_id(TreeSelect:org_options) + employee_status(codes) + employee_type(codes) + 自定义字段筛选(动态追加≤3 项)
├── toolbar binds:
│ ├── [新增员工] → PopupWindow → roster_employee_create.dspy含证件信息分组证件类型/号码/有效期起止/签发机关,手工录入 D1
│ ├── [导入] → PopupWindow: 模板下载链接 + FileUpload(roster_import.dspy, mode=new/update) + 结果文件下载
│ ├── [导出] → PopupWindow: 字段多选(拖拽排序) + as_of 日期 → roster_export.dspy
│ └── [字段配置] → url 跳转 field_config.uiA/H
├── 列: 工号/姓名(点击→employee_detail.ui?id=)/组织/职位/员工类型/状态/入职日期 + 自定义显示列
└── 行操作: [详情][发起转正][发起调动][办理离职](按角色与员工状态显隐)
```
### 3.4 员工档案 /hrroster/employee_detail.uiF03
```
employee_detail.ui (VBox)
├── 头部卡片(HBox): 头像 + 姓名/工号/状态标签 + 快捷操作[编辑][发起审批](PopupWindow 选择 biz_type)
├── Tabs(id:profile_tabs)
│ ├── Tab 分组字段(按 roster_field_group 动态生成证件信息组展示脱敏证件号前3后3+有效期+签发机关): 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 项目任职F17org_project_post 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 审批流,页面提示"已提交审核";否则直接生效。复职员工档案头部显示"复职"标签并链接原档案prev_employee_id
### 3.5 入转调离工作台F04~F07
```
entry_workbench.ui (VBox)
├── 状态卡片行(ResponsableBox): 待入职数/审批中数/本月入职数dataurl=workbench_transfer.dspy
├── 待入职列表 DataViewer(org_entry by entry_status=pending_entry)
│ ├── 黑名单命中行: 高亮样式 + [拦截原因]BLACKLIST_HIT
│ ├── 登记表状态列: none/invited/filled + [复制链接][二维码(PopupWindow 展示二维码图片+有效期)]
│ └── 行操作: [邀请填登记表(entry_invite_register.dspy)][发送入职通知][直接入花名册][复职匹配提示(命中历史档案时高亮)]
└── 工具行: [手动入职(批量 PopupWindow)][发起入职审批(含证件信息手工录入分组)]
transfer_list.ui: DataViewer(org_transfer) + data_filter(status=pending/confirmed/cancelled, transfer_type, effective_date)
行操作: [查看明细(org_transfer_detail subtable批量逐人)][取消](pending 状态)
[发起调动] PopupWindow: 多人选择(批量) + 调动类型 + 生效日期 + 逐人目标组织/职位/职级
leave_workbench.ui (VBox)
├── 待离职名单 DataViewer(org_leave by status=pending_leave)
│ 行操作: [交接管理(PopupWindow: org_leave_handover 编辑,交接项类型含"钉钉资源交接(占位,手工登记内容)")][办理离职][开具证明][加入黑名单(确认弹窗)]
├── 交接完成率: 每个离职单展示交接项完成进度条done/total
└── 已离职列表 DataViewer(status=left) + [离职证明下载(PDF)] + [加入黑名单]
```
### 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.dspyA4 版式)]
操作完成后 script 刷新页面 → 列表刷新
flow_design.ui (A/H): 三区块
├── 表单定义 DataViewer(flow_form_def) + 字段引用器(勾选 roster_field_defbiz_type 含考勤桩位 attendance_* 分组提示"桩位,不联动考勤系统")
├── 流程定义 DataViewer(flow_def含初始化预置的人事四类模板入职/转正/异动/离职/离职交接) + 节点编辑 PopupWindow(审批人类型/通过规则 any-all/字段权限/抄送)
└── 审批角色 DataViewer(flow_role, 仅 admin三维配置流程范围/操作权限/数据查看)
```
### 3.7 编制管理F16新增
```
headcount_config.ui (A/H) (VBox)
├── 编制方案 DataViewer(org_headcount_scheme): 方案名/周期类型(年/季/月)/起止/状态 行操作:[编辑][停用]
└── [新增方案] PopupWindow + 方案展开行内编辑细分项:
细分项表格(headcount_item): 占编范围条件编辑器(scope_json: 员工类型/状态/职位/职级/自定义字段多条件) + 细分维度(seg_json) + 编制数量(head_limit)
headcount_board.ui (VBox)
├── 顶部: 方案选择器 + 快照日期 DatePicker(历史回溯)
├── 状态卡片区(ResponsableBox): 总编制/在编/超编/缺编
├── Chart(柱状: 各细分项 head_limit vs used_count超编红色标注) dataurl=headcount_status.dspy
└── 明细 DataViewer: 细分项/编制数/占编数/超编数/缺编数(超编行红色高亮 + 提醒消息入口)
交互:异动(入转调)生效后看板 ≤1 分钟刷新(事件触发重算);历史日期选择 → headcount_history.dspy 按快照取数。
```
### 3.8 项目式组织F17新增
```
project_tree.ui (HBox)
├── 左侧 VBox: Tree(org_project 多层级) + [新增项目][新增子项目]
└── 右侧 VBox
├── 项目详情 Form: 编码/名称/负责人/时间范围(到期自动标识 expired 状态)/属性(attrs_json)
└── 项目任职 DataViewer(org_project_post): 员工/横向职务(horizontal_job_options)/起止日期
行操作:[添加任职(PopupWindow 选人+选横向职务)][移除]
交互员工同时挂纵向部门roster_employee.org_id与横向项目横向职务数据可被花名册任职信息与薪酬模块引用options 端点)。
```
### 3.9 报表看板 /hrreport/report_board.uiF13
```
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(离职原因饼图)
└── 各 Tab 右上 [导出] → report_export.dspy与页面数据一致
```
所有看板查询服务端叠加数据范围manager 仅见团队。
### 3.10 合同管理F09
```
contract_list.ui = DataViewer(contract_info)
├── data_filter: 员工/类型/合同公司/状态/到期日期前
├── toolbar: [新增合同][批量导入][类型管理][模板管理][提醒规则]
├── 行操作: [发起审批(新签/续签/变更/终止 PopupWindow 选类型)][生成合同文本(contract_text_gen.dspy按模板填充下载 docx/pdf 供打印——电子签二期)][到期高亮(end_date 临近橙色)]
└── 模板管理页: contract_template CRUD + 占位符映射编辑(field_marks_json)
```
### 3.11 系统管理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场景≥6 类 entry/regular/leave/retire/contract_expire/health_cert/social_insurance/custom) + DataViewer(sys_care_config 生日/周年文案)
service.ui: Tabs[公告 DataViewer(sys_announcement 在线预览)][政策 DataViewer(sys_policy, 行内预览/下载按 view_scope+downloadable 权限)]
message_list.ui: DataViewer(msg_type/is_read 筛选) 行点击标已读
```
### 3.12 工作台F14
```
workbench_employee.ui (ResponsableBox 移动端自适应)
├── 卡片: 个人档案(→employee_detail.ui?id=self) | 工资条(桩位卡片:显示"薪酬模块上线后可用"FEAT-B1-09) | 个人绩效(桩位:同上) | 发起审批(PopupWindow 选择流程类型→flow_start)
├── 待办/已办/我发起/我收到 四 Tab DataViewer(task_todo/done/inst_mine/received)
└── 企业政策/公告入口(service.ui)
workbench_manager.ui (VBox)
├── 统计卡片行(dataurl=team_stats.dspy): 团队人数/本月入离职/待审批数(考勤统计/团队绩效为桩位卡片"未接入"
├── 待审批 DataViewer(task_todo 范围=团队) | 团队入转调离 DataViewer(workbench_transfer.dspy scope=team)
└── 关怀提醒 VBox(生日/周年/合同到期 近期列表)
workbench_admin.ui (VBox)
├── 人事统计卡片(team_stats scope=all) + 合同即将到期 DataViewer(contract_expire_soon.dspy) + 编制超编提醒入口(headcount_board.ui)
└── 待审批 + 关怀提醒(同经理视图,范围=数据权限内全部)
```
## 4. 核心交互流程(页面级时序)
1. **入职(审批)**entry_workbench [发起入职审批] → PopupWindow 表单(含证件信息手工录入分组)→ entry_approval.dspy →BLACKLIST_HIT 则红色高亮提示)成功 → 待审批列表出现;审批人在 todo_list 处理 → inst_detail 同意 → 花名册新增记录 → message_list 收到入职通知。
2. **入职登记表(扫码降级)**:待入职行 [邀请填登记表] → 生成链接+二维码PopupWindow 展示,内网访问)→ 候选人扫码打开 entry_register.tmpl → 填写提交 → 列表登记表状态 filled → 继续审批/入职。
3. **复职**:发起入职审批输入证件号 → entry_rehire_match 命中历史档案 → 表单提示"复职:原部门/职位"并自动带出关联 → 入职后档案显示复职标签。
4. **员工自助修改**employee_detail → 编辑可改字段 → 保存 → 提示"直接生效"或"已提交审核"need_audit→ 审核通过后字段更新、时间轴留痕。
5. **调动批量**transfer_list [发起调动] → PopupWindow 多人选择 + 调动类型 + 逐人目标 → transfer_apply.dspy → 生成批量审批单 → 通过后逐人更新(明细可追溯)→ 编制联动校验提醒。
6. **离职全流程**leave_workbench 发起/手动 → 待离职名单 → [交接管理]逐项勾选(含钉钉资源占位项手工登记)→ 到期自动生效remind_scan→leave_effect→ [开具证明]下载 PDF → 可选[加入黑名单]。
7. **合同到期提醒**remind_scan后台→ message_list 消息 → workbench_admin 到期卡片 → contract_list 行内到期高亮 → [生成合同文本]续签打印。
8. **历史架构图**org_chart 选择 as_of 日期 → 查看 → 导出 PNG/XMind。
9. **编制看板**headcount_config 配置方案与细分(占编范围条件)→ headcount_board 实时查看超/缺编 → 异动后自动刷新并推送超编提醒 → 选择历史日期回溯快照。
## 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敏感字段服务端脱敏后展示证件号前3后3、手机前3后4
6. **移动端兼容**:员工自助页面(工作台/档案/待办/服务/消息/登记表)使用 ResponsableBox 自适应,窄屏卡片化;管理类页面 PC 优先NFR-6
7. **打印**:审批单 inst_print.dspy 输出 A4 打印样式页面;合同文本 docx/pdf 直接打印。
## 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_field_def_save |
| org_chart.ui | org_tree(as_of) / org_chart_export |
| company_list.ui | company_saveCRUD |
| position_list.ui 等 | position/job/grade/rank/sequence CRUD + *_import/_export + *_options |
| roster_list.ui | roster_list / roster_employee_create / roster_import / roster_export / check_employee_no / roster_field_def_save |
| employee_detail.ui | employee_detail / roster_employee_update / timeline / timeline_add / file_preview_url |
| entry_workbench.ui | entry_approval / entry_manual / entry_invite_register / entry_qrcode / entry_blacklist_check / entry_notify / entry_rehire_match |
| entry_register.tmpl | entry_register_page / entry_register_submit |
| transfer_list.ui | transfer_apply / transfer_cancel |
| leave_workbench.ui | leave_apply / leave_manual / leave_handover_save / leave_certificate / blacklist_add |
| headcount_config.ui / headcount_board.ui | headcount_scheme_save / headcount_item_save / headcount_status / headcount_history |
| project_tree.ui | project_tree / project_save / project_post_save / horizontal_job_options |
| 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 / flow_match |
| contract_list.ui | contract_list / contract_create / contract_import / contract_apply / contract_text_gen / contract_remind_rule_save / contract_template_save / esign_stub |
| report_board.ui | roster_analysis / entry_analysis / regular_analysis / transfer_analysis / leave_analysis / report_export |
| workbench_*.ui | workbench_employee / workbench_manager / workbench_admin / team_stats / contract_expire_soon |
| 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 / policy_download |
| message_list.ui | message_list / message_read / message_unread_count |