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

21 KiB
Raw Blame History

迭代1总体设计 —— 系统架构与技术选型hr-web

  • 版本v1.1迭代1-总体设计v1.1 变更database/api/ui 三份配套文档已按 ocai 口径重写为 v2.0,表数量与端点数量同步修正)
  • 状态评审通过主agent评审基线冻结
  • 需求基线:docs/00-requirement/requirement-spec.mdSRS v2+ docs/00-requirement/iteration1-function-detail.mdF01~F15
  • 应用定义:apps/hr-web.md;模块定义:modules/hr-org.mdhr-roster.mdhr-flow.mdhr-contract.mdhr-report.mdhr-system.md
  • 开发规范ocai 技能集 —— web-application-spec、module-development-spec、database-table-definition-spec、crud-definition-spec、dspy-file-implementation-spec

0. 审核退回意见响应索引

PM 退回意见要求交付件至少包含 6 项内容,落点如下:

# 退回意见要求 落点文档/章节
1 系统总体架构与模块划分hr-system、staff-mgr 职责边界) 本文 §2、§4、§6
2 数据库设计(核心表、字段、索引、关系、迁移策略) database-design.md 全文§4 表结构、§5 索引策略、§7 迁移策略)
3 API 设计(路径、方法、请求/响应、鉴权、错误码) api-design.md 全文§1 通用约定、§2 端点清单、§3 示例)
4 UI 设计(页面结构、核心交互、组件/路由) ui-design.md 全文§2 路由、§3 组件树、§4 交互流程)
5 与现有 staff-mgr 员工管理模块的衔接方案 本文 §6 + database-design.md §6 数据迁移
6 技术可行性说明与后续开发任务拆解 iteration1-task-breakdown.md 全文

1. 概述

迭代1交付「Web 版人事系统hr-web」组织人事底座功能范围 F01~F15组织架构、职位职级体系、花名册、入职/转正/调动/离职/兼岗、合同台账(不含电子签)、流程审批、权限/日志、报表、工作台、员工服务与提醒。规模规格 100 人账号。

设计原则:

  1. 全栈遵循 ocai 规范:前端 bricks 组件体系(.ui 纯 JSON 声明式页面 + dspy 驱动的 CRUD后端 ahserverPython/aiohttp数据层 apppublic/sqlor基础模块 appbase字典/用户)+ rbac角色权限
  2. 配置驱动表结构models/.json、CRUD 界面json/.json、字典appcodes全部声明式定义减少硬编码支撑 SRS 的"字段/流程/表单自定义"诉求。
  3. 模块宿主无关:每个模块仅依赖基础包与自己的数据表,通过 load_{module}() 注册 ServerEnv可被任意宿主应用加载module-development-spec
  4. 单一事实来源花名册roster_employee是全系统员工数据唯一事实来源入转调离审批通过后统一回写花名册。

2. 总体架构

┌────────────────────────────────────────────────────────────────────┐
│                        浏览器PC Web 为主)                          │
│   bricks.js 渲染引擎:.ui(JSON) 页面 + DataViewer/Tree/Form/Chart    │
└──────────────────────────────┬─────────────────────────────────────┘
                               │ HTTP(S)  session cookieRedis 会话)
┌──────────────────────────────▼─────────────────────────────────────┐
│                     nginx 反向代理prod: 443                      │
└──────────────────────────────┬─────────────────────────────────────┘
┌──────────────────────────────▼─────────────────────────────────────┐
│              ahserver 应用进程hr-webdev:9080                   │
│  路由wwwroot 自动路由 /{module}/{file}.ui|.dspy|.css|.js           │
│  processors: .tmpl→tmpl, .ui→bui, .dspy→dspy                       │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │ 业务模块load_xxx 注册 ServerEnv                          │   │
│  │ hr-org | hr-roster | hr-flow | hr-contract | hr-report |    │   │
│  │ hr-system                                                      │   │
│  ├─────────────────────────────────────────────────────────────┤   │
│  │ 基础模块appbaseusers/appcodes 字典)+ rbac角色/权限)   │   │
│  │           bricks_for_pythonUiWindow 等 pybricks           │   │
│  └─────────────────────────────────────────────────────────────┘   │
└──────────┬───────────────────────────────┬─────────────────────────┘
           │ sqlor 连接池sor.C/U/D/R/I/sqlExe │ Redis session
┌──────────▼──────────┐           ┌────────▼────────┐
│  MySQL 8.0(库 hr  │           │  Redis会话   │
│  json2ddl 生成 DDL   │           └─────────────────┘
└─────────────────────┘      files/ 目录:附件存储(合同文件、头像、导入导出文件)

请求处理链路(以花名册列表为例):

  1. 浏览器访问 /hrroster/roster_list.ui(由 json/roster_employee_list.json 经 xls2ui 生成的 DataViewer 页);
  2. DataViewer 按 CRUD JSON 中的 dataurl/new_data_url 等调用 /hrroster/api/xxx.dspy
  3. ahserver 将 GET query + POST body 统一解析为 params_kw 注入 dspy 上下文;
  4. dspy 调用 load_hrroster() 注册的业务函数(内部经 sqlor sor.R 查询,叠加 rbac 数据范围过滤与敏感字段脱敏);
  5. dspy 显式 return JSON列表必须 {status:'success', data:{rows:[...], total:N}}bricks 渲染。

3. 技术选型与理由

选型 选型理由
前端 bricks 组件体系 + .ui 纯 JSON 页面 ocai 强制规范CRUD JSON 自动生成列表/表单/树页面F01~F15 中 80% 的增删改查页面零 Vue 代码DataViewer 自带筛选data_filter、子表subtables、工具栏 bind
声明式页面脚本 .dspy受控 Python 后端 API 与页面逻辑统一语言栈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 §3.1.14
数据库 MySQL 8.0 产线既有设施staff-mgr 亦为 MySQLsqlor DDL 模板成熟
会话 Redis + aiohttp_session web-application-spec 推荐;服务重启不丢登录
附件 ahserver files/ 文件存储 合同附件、离职证明、导入导出文件100 人规模本地目录足够

与 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
hr-roster /hrroster 花名册(字段定义/字段值 EAV/员工主档/时间轴/工号规则)、导入导出 roster_ F03
hr-flow /hrflow 表单定义、流程定义、流程实例、审批任务(待办/已办/我发起) flow_ F10
hr-contract /hrcontract 合同台账、合同模板、到期提醒规则、合同审批 contract_ F09
hr-report /hrreport 只读聚合报表(花名册分析/入职/转正/调岗/离职分析),无自有表 F13
hr-system /hrsystem 角色/管理员/数据范围、操作日志、工作台聚合、提醒规则、公告政策、站内消息 sys_ F11/F12/F14/F15

4.2 职责边界规则

  1. 员工主数据唯一入口:所有模块读写员工信息必须经 hr-roster 的注册函数ServerEnv 暴露),禁止跨模块直接 SQL 写 roster_ 表。入转调离审批通过后由 hr-flow 回调 hr-org 的业务函数,再调用 hr-roster 回写接口更新员工状态。
  2. 审批引擎与业务解耦hr-flow 只管"表单+流程+实例+任务"的流转,不含业务语义;业务回写通过 biz_type + biz_id 关联 + 流程完成回调ServerEnv 注册的 hook 函数)实现。
  3. 权限横切:功能权限(路径级 RBAC由 rbac 模块统一拦截(各模块 scripts/load_path.py 注册路径与角色);数据范围由 hr-system 提供 get_data_scope(user_id) 公共函数hr-org/hr-roster/hr-report 在查询时强制叠加。
  4. 操作日志横切所有写操作sor.C/U/D统一经 hr-system 的 write_audit_log(...) 记录前后值before/after JSONF12 查询页只读 sys_audit_log。
  5. 字典统一:任何枚举值不得硬编码在 dspy 中,一律走 appcodesinit/data.json 初始化CRUD 下拉用 models codes 段引用。

4.3 hr-system 与 staff-mgr 的职责边界(重点澄清)

对象 性质 职责 状态
hr-system模块repos/hr-system 迭代1 ocai 规范模块 系统支撑层F11 权限管理、F12 操作日志、F14 工作台、F15 员工服务与提醒;并承载全应用的横切能力(数据范围、审计、站内消息) 迭代1新建复用现有空仓 hr-system.git
staff-mgrrepos/staff-mgr v1 遗留 Java 模块 旧员工 CRUD REST 服务(/api/v1/staff/*Spring Boot + JPA + JWT 已归档,冻结不再开发仅作迭代1数据迁移来源与参考实现见 §6

边界结论:

  • 迭代1上线后 staff-mgr 不再承担任何线上职责;其员工数据一次性迁移至 hr-rosterroster_employee + roster_field_value部门缓存迁移至 hr-orgorg_unit日志迁移/归档至 hr-systemsys_audit_log
  • 旧模块的"员工 CRUD"职责由 hr-roster 承接(不是 hr-systemhr-system 只承接其"操作日志/权限"类横切职责。详见 §6 衔接方案。
  • v1 应用定义 apps/hr-system.mdJava 后端服务)已废弃,与模块 hr-systemocai 支撑模块)仅重名,无继承关系。

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.pyinit() 中依次 ServerEnv() → 设置 get_module_dbname(返回 hr)→ load_appbase()load_rbac()load_pybricks()load_hrsystem/load_hrorg/load_hrroster/load_hrflow/load_hrcontract/load_hrreport()
  • conf/config.jsonprocessors 必含 [".tmpl","tmpl"], [".ui","bui"], [".dspy","dspy"]indexes 含 index.uidatabases 配置 hr 库Redis 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 并导入 → init/data.json 导入 → json/ 执行 xls2ui 生成 CRUD → symlink 各模块 wwwroot 与 bricks dist → systemd 服务。
  • 环境dev/test 单实例容器nginx:8080 → ahserver:9080prod nginx:443 反代ahserver 不直接暴露MySQL/Redis 仅内网数据每日备份。100 人规模单实例即可满足"列表页 ≤500ms"指标(见 §8

6. 与现有 staff-mgr 员工管理模块的衔接方案

6.1 衔接定位

staff-mgr 是 v1 Java 口径下的员工 CRUD 模块(已通过端到端验证,见其 README与 ocai 规范冲突,不改造、不并行演进,采取一次性数据迁移 + 接口替代 + 退役策略。

6.2 职责与接口替代映射

staff-mgr 旧接口(/api/v1/staff 迭代1替代hr-roster/hr-system dspy 说明
POST /(创建员工) /hrroster/api/roster_employee_create.dspy或手动入职 /hrorg/api/entry_manual.dspy 新建一律走入职流程或花名册新增
GET /(分页列表) /hrroster/roster_listCRUD 列表 + data_filter 筛选能力增强(自定义字段)
GET /{id}(详情) /hrroster/employee_detail.dspy 档案 Tabs + 时间轴
PUT /{id}(更新) /hrroster/api/roster_employee_update.dspy 可配置自助修改 + 审核
DELETE /{id}、POST /batch-delete 离职流程 /hrorg/api/leave_manual.dspy 迭代1不做物理/逻辑删除员工,统一走离职
GET /{id}/change-logs /hrroster/timeline.dspy 时间轴(含迁移进来的旧变更记录)
GET /audit-logs /hrsystem/audit_log_listCRUD 历史日志迁入 sys_audit_log
GET /check/employee-no /hrroster/api/check_employee_no.dspy 工号查重保留
GET /departments /hrorg/api/org_tree.dspy 部门缓存表废弃,直接查 org_unit

脱敏规则延续并按 SRS 加强身份证号全角色脱敏前3后3、手机号前3后4、薪资职级类字段仅 admin/hr 可见——由 hr-system 字段级权限表驱动,替代 staff-mgr 硬编码 MaskUtil。

6.3 数据迁移方案(详见 database-design.md §6

  • 迁移对象staff_employee → roster_employeestaff_employee_extra → roster_field_value学历/专业等映射到预置字段定义)+ contract_info合同起止staff_department_cache → org_unitstaff_change_log → roster_timelinestaff_audit_log → sys_audit_log。
  • 迁移工具hr-system 仓内 scripts/migrate_staff_mgr.pyPython + sqlor幂等、按 employee_no 去重、输出核对报告)。
  • 切换策略迭代1 UAT 通过后一次性切换;切换后 staff-mgr 服务下线、仓库冻结归档(保留只读访问一个迭代周期)。

6.4 风险与对策

风险 对策
旧数据字段语义不一致(如 status 枚举) 迁移脚本内置映射表 + 人工核对报告UAT 期间双库比对
旧 department_id 无组织主数据 先迁 staff_department_cache 建 org_unit再按 department_id 关联
身份证号加密算法不同AesCipher 迁移时解密后按 hr-web 统一加密方案重新落库

7. 安全设计

  1. 鉴权ahserver sessionRedis+ rbac 角色。迭代1角色admin(系统管理员)、hr(人事)、manager(部门经理)、employee(员工自助);所有路径经 scripts/load_path.py 注册,未注册路径默认拒绝。
  2. 数据范围F11sys_role_data_scope 支持两类范围——组织维度org_id 集合含子树、花名册字段维度field_id 可见集合)。查询层强制拼接范围条件;报表同样受控。
  3. 脱敏:敏感字段(身份证/手机/薪资级)在 roster_field_def 标记 sensitivedspy 返回前按角色脱敏。
  4. 审计F12全量写操作记录前后值 JSON、操作人、IP审批、导入导出同样记录。
  5. SQL 注入:全部经 sqlor 绑定参数dspy 禁止拼接用户输入sqlExe 使用 ${var}$ 占位)。

8. 非功能设计响应

SRS 非功能项 设计响应
列表响应 ≤500ms 100 人规模 + 索引设计database-design.md §5列表页分页默认 50组织树一次性加载≤200 节点)
批量导入导出 100 人量级 openpyxl 同步处理ahserver 已内置),导入走后台任务 + 结果文件下载
字段/流程/表单自定义 roster_field_defEAV、flow_form_def/flow_def JSON 化配置,无硬编码
PC 为主 + 员工自助移动端兼容 员工自助页面(个人档案/发起审批/待办)使用 ResponsableBox 自适应布局

9. 配套设计文档

  • database-design.mdv2.0ER、43 张表结构、索引、字典、models JSON 示例、staff-mgr 迁移策略
  • api-design.mdv2.0dspy 端点清单(约 100 个)、请求/响应、鉴权角色、错误码
  • ui-design.mdv2.0):页面结构、组件树、路由表、核心交互流程
  • iteration1-task-breakdown.mdv1.0可行性分析、风险、开发任务拆解T01~T24