hr-system/docs/01-design/api-design.md

202 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 迭代1总体设计 —— API/接口设计hr-webocai 口径)
- 版本v2.0迭代1-总体设计,取代 v1 Spring Boot/JWT RESTful 口径v1 已归档至 `docs/_archive/01-design-v1-old/api-design.md`
- 状态:提交审核
- 规范依据ocai 技能集 module-development-spec、dspy-file-implementation-spec、crud-definition-spec架构基线 `docs/01-design/architecture.md`
## 1. 接口范式与通用约定(取代 v1 RESTful/JWT
1. **端点形态**:全部接口为 `.dspy` 端点(受控 Python路径 `/{module}/api/{name}.dspy`,由 ahserver wwwroot 自动路由无需注册GET query 与 POST body 统一解析进 `params_kw`。dspy 必须显式 `return`,且不得在 `async with db.sqlorContext` 块内 returnNoneType 陷阱)。
2. **鉴权**session cookieRedis 会话)+ rbac 路径级角色控制;每条路径经各模块 `scripts/load_path.py` 注册,角色:`admin / hr / manager / employee / logined`;未注册路径默认拒绝。不使用 JWT。
3. **数据范围**:查询类接口强制叠加 `get_data_scope(user_id)`hr-system 提供),范围外数据不可见。
4. **CRUD 列表/表单接口**:由 json/*.json 经 xls2ui 自动生成列表查询、add/update/delete 包装 dspy不在本文逐一列出本文列出业务自定义端点。CRUD 自动生成部分约定 `new_data_url/update_data_url/delete_data_url` 位于 params 顶层。
5. **统一响应结构**
- 列表:`{"status":"success","data":{"rows":[...],"total":N}}`DataViewer 强制格式)
- 业务:`{"status":"success"|"error","message":"...","data":{...}}`
- 错误返回 HTTP 200 + status=errorbricks 前端惯例),鉴权失败由框架返回 401/403。
6. **错误码规范**status=error 时 data.code
| code | 含义 | 典型场景 |
|---|---|---|
| PARAM_INVALID | 参数缺失/格式错误 | 必填项为空、日期格式错 |
| NOT_FOUND | 对象不存在 | id 无效 |
| DUPLICATE | 唯一冲突 | 工号/编码重复 |
| NO_PERMISSION | 数据范围外/角色不足 | 越权访问他人档案 |
| BLACKLIST_HIT | 黑名单命中 | 入职校验拦截 |
| STATUS_CONFLICT | 状态不允许 | 已离职再调动、重复审批 |
| FLOW_NOT_MATCH | 无匹配审批流 | 该员工类型/部门未配置流程 |
| SCOPE_OVERDRAFT | 编制/范围超限 | 预留(编制管理范围外) |
| INTERNAL_ERROR | 服务异常 | 兜底 |
7. **审计**:所有写接口成功后调用 `write_audit_log(module,target_type,target_id,op,before,after)`hr-system
## 2. 端点清单(按模块)
> 角色列A=adminH=hrM=managerE=employeeL=任意登录。数据范围=是 表示叠加数据范围过滤。
> CRUD 列:该表的标准增删改查由 json/*.json 自动生成,路径为 `/{module}/{tblname}_list`(页面) + `add_/update_/delete_{tblname}.dspy`。
### 2.1 hr-org/hrorgF01/F02/F04~F08
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD |
|---|---|---|---|---|---|---|
| /hrorg/api/org_tree.dspy | GET | 组织树(支持 as_of 历史日期、status 过滤) | as_of?, status?, keyword? | 树形节点数组(id,name,parent_id,children,status,leader_name) | L | — |
| /hrorg/api/org_unit_create.dspy | POST | 新建组织(编码唯一校验、写 org_unit_change | org_code,org_name,parent_id,org_type,leader_id,effective_date,自定义字段kv | {id} | A,H | org_unit |
| /hrorg/api/org_unit_update.dspy | POST | 编辑组织(留痕) | id,... | {} | A,H | org_unit |
| /hrorg/api/org_unit_move.dspy | POST | 移动组织(变更上级) | id,new_parent_id,effective_date | {} | A,H | — |
| /hrorg/api/org_unit_disable.dspy | POST | 停用组织(校验无在职员工引用) | id | {} | A,H | — |
| /hrorg/api/org_change_timeline.dspy | GET | 组织时间轴 | org_id | {rows:[{change_type,before_json,after_json,operator,created_at}]} | L | — |
| /hrorg/api/org_import.dspy | POST | Excel 批量导入组织(后台任务+结果文件) | file(上传) | {task_id} | A,H | — |
| /hrorg/api/org_import_result.dspy | GET | 导入结果(成功/失败行下载) | task_id | {rows,total,error_file} | A,H | — |
| /hrorg/api/org_chart_export.dspy | GET | 架构图导出(图片/XMind | as_of?, root_id?, fmt=png/xmind | 文件下载 | A,H | — |
| /hrorg/api/org_field_def_save.dspy | POST | 组织字段自定义 | fields[] | {} | A,H | org_field_def |
| /hrorg/api/job_import.dspy / job_export.dspy | POST/GET | 职务批量导入导出 | file / 筛选条件 | {task_id} / 文件 | A,H | org_job |
| /hrorg/api/position_import.dspy / position_export.dspy | POST/GET | 职位批量导入导出 | file / dept_id?,status? | {task_id} / 文件 | A,H | org_position |
| /hrorg/api/job_options.dspy / position_options.dspy / grade_options.dspy / rank_options.dspy / sequence_options.dspy / org_options.dspy / company_options.dspy | GET | 主数据下拉选项(状态=active供花名册/异动表单引用) | 无/keyword | {rows:[{id,name}]} | L | org_job 等 |
| /hrorg/api/entry_approval.dspy | POST | 发起入职审批(单个,匹配审批流) | name,id_number,employee_type,org_id,position_id,hire_date,... | {instance_id} 或 BLACKLIST_HIT/FLOW_NOT_MATCH | A,H | org_entry |
| /hrorg/api/entry_manual.dspy | POST | 手动入职(批量,直接入花名册或待入职) | entries[]:{...}, to=pending/roster | {entered:[],pending:[],blocked:[]} | A,H | — |
| /hrorg/api/entry_invite_register.dspy | POST | 邀请待入职填写登记表(站内消息) | entry_ids[] | {} | A,H | — |
| /hrorg/api/entry_register_submit.dspy | POST | 待入职员工提交登记表 | entry_id,字段kv | {} | E(本人) | — |
| /hrorg/api/entry_blacklist_check.dspy | GET | 黑名单校验 | id_number 或 name | {hit:bool,blacklist_id?} | A,H | — |
| /hrorg/api/entry_notify.dspy | POST | 入职通知/欢迎(模板填充发送) | entry_ids[],template_id | {} | A,H | — |
| /hrorg/api/regular_apply.dspy | POST | 发起转正审批(自助/代发) | employee_id,regular_date | {instance_id} | E(自助),H,M | org_regularization |
| /hrorg/api/regular_manual.dspy | POST | 手动转正(直接更新花名册) | employee_id,regular_date | {} | A,H | — |
| /hrorg/api/transfer_apply.dspy | POST | 发起调动审批(支持批量人员) | transfer_type,effective_date,details[]:{employee_id,to_org_id,to_position_id,...} | {instance_id} | A,H,M | org_transfer |
| /hrorg/api/transfer_cancel.dspy | POST | 取消调动(保留历史不改现职) | transfer_id | {} | A,H | — |
| /hrorg/api/leave_apply.dspy | POST | 发起离职审批(自助/代发) | employee_id,leave_type,leave_reason,leave_date | {instance_id} | E(自助),H,M | org_leave |
| /hrorg/api/leave_manual.dspy | POST | 手动离职(直接入待离职/已离职) | employee_id,leave_date,leave_reason | {} | A,H | — |
| /hrorg/api/leave_handover_save.dspy | POST | 离职交接项保存 | leave_id,items[] | {} | A,H,M | org_leave_handover |
| /hrorg/api/leave_certificate.dspy | GET | 离职证明生成下载 | employee_id | 文件 | E(本人),A,H | — |
| /hrorg/api/blacklist_add.dspy | POST | 一键加入黑名单 | leave_id 或 id_number_hash,reason | {} | A,H | org_blacklist |
| /hrorg/api/concurrent_apply.dspy | POST | 发起兼岗审批 | employee_id,org_id,position_id,start_date,end_date | {instance_id} | A,H,M | org_concurrent_post |
| /hrorg/api/workbench_transfer.dspy | GET | 工作台入转调离汇总(经理/管理员视图) | scope=team/all | {entry_n,regular_n,transfer_n,leave_n,rows} | M,H,A | — |
### 2.2 hr-roster/hrrosterF03
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD |
|---|---|---|---|---|---|---|
| /hrroster/api/roster_list.dspy | GET | 花名册列表(主表条件分页 + EAV 拼装 + 范围过滤 + 脱敏) | keyword?,org_id?,status?,type?,field_filters?,page,size | {rows,total} | A,H(范围),M(团队) | roster_employee |
| /hrroster/api/roster_employee_create.dspy | POST | 新增员工(自动生成工号、写时间轴) | 主档字段+自定义字段kv | {id,employee_no} | A,H | roster_employee |
| /hrroster/api/roster_employee_update.dspy | POST | 更新员工(含自助修改路径:可改范围+可选审核) | id,字段kv | {} 或 {need_audit:true,instance_id} | A,H,E(本人受限) | roster_employee |
| /hrroster/api/employee_detail.dspy | GET | 员工档案详情(主档+分组字段+兼岗+合同摘要,按角色脱敏/字段可见) | id | {main,groups:[{group_name,fields:[...]}],concurrent,contracts} | L(按范围) | — |
| /hrroster/api/roster_field_def_save.dspy | POST | 字段定义维护(类型/必填/敏感/自助/审核/适用类型/排序) | fields[] | {} | A,H | roster_field_def |
| /hrroster/api/roster_field_group_save.dspy | POST | 分组维护(含拖拽排序持久化) | groups[] | {} | A,H | roster_field_group |
| /hrroster/api/roster_type_rule_save.dspy | POST | 员工类型字段规则 | employee_type,field_rules_json | {} | A,H | roster_type_rule |
| /hrroster/api/empno_rule_save.dspy | POST | 工号规则维护 | rules[] | {} | A,H | roster_empno_rule |
| /hrroster/api/check_employee_no.dspy | GET | 工号查重 | employee_no,exclude_id? | {exists} | A,H | — |
| /hrroster/api/roster_import.dspy | POST | 自定义导入(批量新增/批量修改,模板按当前字段定义生成) | file,mode=new/update | {task_id} | A,H | — |
| /hrroster/api/roster_import_template.dspy | GET | 导入模板下载(按字段定义+类型规则) | employee_type? | 文件 | A,H | — |
| /hrroster/api/roster_export.dspy | GET | 自定义导出(指定数据日期/字段/顺序) | as_of?,field_ids[],filters | {task_id}→文件 | A,H | — |
| /hrroster/api/timeline.dspy | GET | 员工时间轴(全周期记录) | employee_id,event_type? | {rows:[{event_type,event_date,title,content_json}]} | L(按范围) | — |
| /hrroster/api/timeline_add.dspy | POST | 时间轴记录编辑 | employee_id,event_type,event_date,title,content | {} | A,H | — |
| /hrroster/api/file_preview_url.dspy | GET | 附件在线预览 URLfiles/ 受控访问) | file_id | {url} | L(按范围) | — |
| /hrroster/api/roster_writeback.dspy | 内部 | 异动回写入口(仅 hr-org/hr-flow 服务内调用,注册于 ServerEnv不注册 HTTP 路径) | biz_type,biz_id,instance_id | {} | 服务内 | — |
### 2.3 hr-flow/hrflowF10
| 端点 | 方法 | 功能 | 关键请求参数 | 响应 data | 角色 | CRUD |
|---|---|---|---|---|---|---|
| /hrflow/api/form_def_save.dspy | POST | 表单定义维护(引用花名册字段) | form_code,form_name,biz_type,fields_json | {id} | A,H | flow_form_def |
| /hrflow/api/flow_def_save.dspy | POST | 流程定义(匹配条件、版本) | flow_code,form_id,biz_type,match_cond_json | {id} | A,H | flow_def |
| /hrflow/api/flow_node_save.dspy | POST | 节点维护(审批人/通过规则/字段权限/抄送) | flow_id,nodes[] | {} | A,H | flow_node_def |
| /hrflow/api/flow_role_save.dspy | POST | 审批角色(流程范围/操作权限/数据范围) | role_name,flow_scope_json,op_perm_json,data_scope_json | {id} | A | flow_role |
| /hrflow/api/flow_match.dspy | GET | 按员工类型/部门匹配流程 | biz_type,employee_type,org_id | {flow_id,flow_name} 或 FLOW_NOT_MATCH | 服务内/HR | — |
| /hrflow/api/flow_start.dspy | POST | 发起审批(通用:业务模块统一入口) | biz_type,biz_id,form_data_json | {instance_id,inst_no} | L | — |
| /hrflow/api/task_todo.dspy | GET | 我的待办 | page,size | {rows,total} | L | — |
| /hrflow/api/task_done.dspy | GET | 已办 | page,size | {rows,total} | L | — |
| /hrflow/api/inst_mine.dspy | GET | 我发起的 | status?,page,size | {rows,total} | L | — |
| /hrflow/api/inst_received.dspy | GET | 我收到的(抄送/知会) | page,size | {rows,total} | L | — |
| /hrflow/api/inst_detail.dspy | GET | 审批单详情(表单数据+流转记录+字段权限) | instance_id | {form_data,nodes:[{op,operator,time,comment}],status} | L(参与者) | — |
| /hrflow/api/task_approve.dspy | POST | 同意 | task_id,comment? | {} | L(任务归属) | — |
| /hrflow/api/task_reject.dspy | POST | 驳回 | task_id,comment | {} | L(任务归属) | — |
| /hrflow/api/task_forward.dspy | POST | 转交 | task_id,to_user_id | {} | L(任务归属) | — |
| /hrflow/api/inst_withdraw.dspy | POST | 撤回(发起人,仅首节点未处理) | instance_id | {} | L(发起人) | — |
| /hrflow/api/inst_query.dspy | GET | 审批数据查询(表单/状态/发起人/编号/时间) | form_name?,status?,initiator?,inst_no?,date_range | {rows,total} | A,H | — |
| /hrflow/api/inst_export.dspy | GET | 审批数据导出 | 同上 | 文件 | A,H | — |
| /hrflow/api/inst_print.dspy | GET | 审批单打印视图 | instance_id | 打印 HTML | L(参与者) | — |
### 2.4 hr-contract/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,start_date,end_date,file | {id} | A,H | contract_info |
| /hrcontract/api/contract_import.dspy | POST | 批量导入 | file | {task_id} | A,H | — |
| /hrcontract/api/contract_apply.dspy | POST | 合同审批(新签/续签/变更/终止) | contract_id?,biz_type=contract_sign/renew/change/stop,form_data_json | {instance_id} | A,H | — |
| /hrcontract/api/contract_remind_rule_save.dspy | POST | 到期提醒规则 | rule_name,days_before,target_role,content_template | {id} | A,H | contract_remind_rule |
| /hrcontract/api/contract_template_save.dspy | POST | 模板维护 | template_name,type_id,file,field_marks_json | {id} | A,H | contract_template |
| /hrcontract/api/contract_expire_soon.dspy | GET | 即将到期列表(工作台/提醒) | days | {rows} | A,H | — |
| /hrcontract/api/esign_stub.dspy | POST | 电子签预留桩(返回未启用提示) | contract_id | {status:'error',code:'NOT_ENABLED'} | A,H | — |
### 2.5 hr-report/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/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[] | {} | A | — |
| /hrsystem/api/get_data_scope.dspy | 内部 | 数据范围查询ServerEnv 注册,供各模块查询叠加) | user_id | {scope_type,org_ids,field_ids} | 服务内 | — |
| /hrsystem/api/audit_log_list.dspy | GET | 操作日志查询(时间/类型/模块) | module?,operation?,date_range,target? | {rows,total} | A | sys_audit_log |
| /hrsystem/api/audit_log_detail.dspy | GET | 日志详情(前后对比) | id | {before_json,after_json,operator,ip,time} | A | — |
| /hrsystem/api/workbench_employee.dspy | GET | 员工工作台聚合(档案摘要/待办数/可发起流程) | — | {profile,todo_n,flows:[...]} | E | — |
| /hrsystem/api/workbench_manager.dspy | GET | 经理工作台聚合(团队统计/待审批/关怀提醒) | — | {stats,todos:[],care:[...]} | M | — |
| /hrsystem/api/workbench_admin.dspy | GET | 管理员工作台聚合(人事统计/合同到期/提醒) | — | {stats,contracts:[],care:[...]} | A,H | — |
| /hrsystem/api/remind_rule_save.dspy | POST | 通用提醒规则(多场景自定义) | scene_code,rule_name,days_before,content_template,target_role | {id} | A,H | sys_remind_rule |
| /hrsystem/api/care_config_save.dspy | POST | 生日/周年关怀文案配置 | care_type,template,enable | {} | A,H | sys_care_config |
| /hrsystem/api/announcement_save.dspy | POST | 公告发布 | title,content,publish_scope_json | {id} | A,H | sys_announcement |
| /hrsystem/api/policy_save.dspy | POST | 政策发布(查阅范围/下载权限) | title,file,view_scope_json,downloadable | {id} | A,H | sys_policy |
| /hrsystem/api/message_list.dspy | GET | 我的站内消息 | is_read?,msg_type? | {rows,total} | L | — |
| /hrsystem/api/message_read.dspy | POST | 标记已读 | ids[] | {} | L | — |
| /hrsystem/api/remind_scan.dspy | 内部 | 提醒扫描cron/启动任务:转正/合同/生日等到期扫描推送) | — | {sent_n} | 服务内 | — |
### 2.7 appbase/rbac 沿用(不自研)
登录/登出、用户管理、字典 appcodes 维护、rbac 角色路径绑定由 appbase/rbac 包自带页面与端点承载(`/appbase/*``/rbac/*`迭代1仅在各模块 init/data.json 中初始化字典与角色。
## 3. 典型调用链示例
### 3.1 转正审批F05 流程2
1. `POST /hrorg/api/regular_apply.dspy` {employee_id, regular_date} → hr-org 校验员工状态probation
2. 内部调用 `flow_match(biz_type=regular, employee_type, org_id)``POST /hrflow/api/flow_start.dspy` {biz_type:'regular', biz_id:regularization_id, form_data_json} → 生成 flow_instance + 首节点 flow_task发站内消息给审批人
3. 审批人 `POST /hrflow/api/task_approve.dspy` → 全部节点通过 → flow_instance.inst_status=approved
4. hr-flow 完成回调 → hr-org `regular_confirm` → hr-roster `roster_writeback`roster_employee.employee_status=regular、regular_date 更新,写 roster_timeline
5. 各步均写 sys_audit_log转正提醒由 `remind_scan` 按预计日期提前推送管理员与直属主管。
### 3.2 花名册列表F03
`GET /hrroster/api/roster_list.dspy?keyword=张&org_id=..&status=regular&page=1&size=50` → 权限校验(数据范围 org_ids/field_ids→ 主表条件分页 → 值表批量拼装显示字段 → 敏感字段按角色脱敏 → `{"status":"success","data":{"rows":[...],"total":N}}`
### 3.3 入职黑名单拦截F04
`POST /hrorg/api/entry_approval.dspy` → id_number 哈希匹配 org_blacklist → 命中返回 `{"status":"error","data":{"code":"BLACKLIST_HIT"}}`,前端待入职列表高亮标注;手动入职返回 blocked 名单。
## 4. 与 v1 接口的替代关系(衔接 staff-mgr
| v1 端点JWT RESTful | 迭代1替代 |
|---|---|
| POST /api/v1/staff | /hrorg/api/entry_manual.dspy 或 /hrroster/api/roster_employee_create.dspy |
| GET /api/v1/staff | /hrroster/api/roster_list.dspy+ CRUD 列表页) |
| GET /api/v1/staff/{id} | /hrroster/api/employee_detail.dspy |
| PUT /api/v1/staff/{id} | /hrroster/api/roster_employee_update.dspy |
| DELETE /api/v1/staff/{id}、batch-delete | 离职流程 /hrorg/api/leave_manual.dspy迭代1不做删除语义裁决 Q6 |
| GET /api/v1/staff/{id}/change-logs | /hrroster/api/timeline.dspy |
| GET /api/v1/staff/audit-logs | /hrsystem/api/audit_log_list.dspy |
| GET /api/v1/staff/check/employee-no | /hrroster/api/check_employee_no.dspy |
| GET /api/v1/staff/departments | /hrorg/api/org_tree.dspy |
## 5. 安全设计要点
1. 所有路径 load_path.py 注册;未注册即拒绝(含 .css/.js 静态资源)。
2. 敏感字段身份证全角色脱敏前3后3手机前3后4职级/薪资类字段仅 admin/hr由 roster_field_def.sensitive + 角色矩阵驱动,服务端脱敏后返回。
3. 全部 SQL 经 sqlor 绑定参数(`${var}$` 占位),禁止拼接用户输入。
4. 审批操作校验任务归属人;员工自助类接口校验本人(或白名单字段)。
5. 导入导出、登录、权限变更全量写 sys_audit_log含 IP