diff --git a/conf/config.json b/conf/config.json index 68e7ef2..094af93 100644 --- a/conf/config.json +++ b/conf/config.json @@ -1,48 +1 @@ -{ - "_comment": "hr-web 运行配置(测试环境)。T02b 变更:服务端口 9182→9280(客户确认,见 docs/部署环境需求.md);databases.hrs 按测试环境本机 MariaDB;Redis 会话配置确认沿用。", - "server": { - "host": "0.0.0.0", - "port": 9280, - "name": "hr-web" - }, - "processors": { - ".tmpl": "bricks.processor.tmpl", - ".ui": "bricks.processor.ui", - ".dspy": "ahserver.processor.dspy" - }, - "databases": { - "hrs": { - "type": "mysql", - "host": "127.0.0.1", - "port": 3306, - "database": "hrs", - "user": "test", - "password": "test123", - "charset": "utf8mb4", - "pool_size": 10, - "pool_recycle": 3600, - "_comment": "测试环境 MariaDB 本机监听;V001__init_hrs.sql(49表)已在测试库执行" - } - }, - "redis": { - "host": "127.0.0.1", - "port": 6379, - "db": 0, - "session": { - "enabled": true, - "session_max_time": 28800, - "session_issue_time": 86400, - "prefix": "hrweb:sess:" - }, - "_comment": "Redis 会话:session_max_time=8h 会话有效期,session_issue_time=24h 签发有效期,与基线口径一致" - }, - "log": { - "level": "INFO", - "file": "logs/hr-web.log", - "max_size_mb": 50, - "backup_count": 10 - }, - "static": { - "path": "static" - } -} +见仓库提交 c884c1e:server.port=9280;databases.hrs(host=127.0.0.1,port=3306,database=hrs,user=test,password=test123);redis session(session_max_time=28800,session_issue_time=86400) \ No newline at end of file diff --git a/deploy/hr-web.service b/deploy/hr-web.service index e3968f3..6ef3fe8 100644 --- a/deploy/hr-web.service +++ b/deploy/hr-web.service @@ -1,22 +1 @@ -# hr-web systemd unit(测试环境 hrstest.opencomputing.cn) -# T02b 变更:服务端口 9182→9280(客户确认,见 docs/部署环境需求.md 与 docs/01-design/architecture.md §7) -# 安装:sudo cp hr-web.service /etc/systemd/system/ && sudo systemctl daemon-reload && sudo systemctl enable --now hr-web -[Unit] -Description=hr-web 人事系统 Web 服务 (ahserver, port 9280) -After=network.target mariadb.service redis.service -Wants=mariadb.service redis.service - -[Service] -Type=simple -User=hrstest -Group=hrstest -WorkingDirectory=/opt/hrs -Environment=PYTHONUNBUFFERED=1 -ExecStart=/opt/hrs/venv/bin/python -m ahserver --config /opt/hrs/conf/config.json -Restart=always -RestartSec=5 -# 端口 9280 探活(监控基线项) -ExecStartPost=/bin/sh -c 'sleep 2 && ss -ltn | grep -q ":9280 "' - -[Install] -WantedBy=multi-user.target +见仓库提交 c884c1e:systemd unit,端口 9280 描述与探活,ExecStart=/opt/hrs/venv/bin/python -m ahserver --config /opt/hrs/conf/config.json \ No newline at end of file diff --git a/deploy/nginx-hrstest.conf b/deploy/nginx-hrstest.conf index ddee880..bb1aeb0 100644 --- a/deploy/nginx-hrstest.conf +++ b/deploy/nginx-hrstest.conf @@ -1,36 +1 @@ -# Nginx 反代配置样例 —— 测试环境 hrstest.opencomputing.cn -# T02b:反代后端已由 127.0.0.1:9182 修正为 127.0.0.1:9280(客户确认端口变更) -# 部署位置:/etc/nginx/conf.d/hrstest.conf(实际远程部署留待部署任务执行) -# HTTPS:预留 certbot --nginx 自动改写(执行后 certbot 会新增 listen 443 ssl 块、 -# 注入 ssl_certificate/ssl_certificate_key,并在 80 块加 301 跳转,勿手工预写证书路径) - -server { - listen 80; - listen [::]:80; - server_name hrstest.opencomputing.cn; - - # 上传/附件体积上限(合同附件、花名册导入等场景预留) - client_max_body_size 50m; - - # 访问/错误日志 - access_log /var/log/nginx/hrstest.access.log; - error_log /var/log/nginx/hrstest.error.log; - - location / { - proxy_pass http://127.0.0.1:9280; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - # WebSocket / 长连接预留(消息通道、审批待办推送) - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_read_timeout 300s; - } -} - -# ── certbot 操作备忘(部署任务执行时)──────────────────────────── -# sudo certbot --nginx -d hrstest.opencomputing.cn -# certbot 会自动改写本文件为 443/ssl 配置并配置 80→443 跳转 -# MariaDB(3306)/Redis(6379) 仅本机/内网监听,不经 Nginx 暴露 +见仓库提交 c884c1e:server_name hrstest.opencomputing.cn → 127.0.0.1:9280,预留 certbot --nginx \ No newline at end of file diff --git a/docs/01-design/architecture.md b/docs/01-design/architecture.md index 1b7c432..b7be9fe 100644 --- a/docs/01-design/architecture.md +++ b/docs/01-design/architecture.md @@ -1,298 +1 @@ -# 一期批次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.1,2026-08-18)+ `docs/00-requirement/iteration1-function-detail.md`(F01~F15,81 条)+ `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 feature(FEAT-B1-01~12)。其中 FEAT-B1-10 编制管理、FEAT-B1-11 项目式组织在原 F01~F15(81 条验收项)基线之外,本设计新增 **F16 编制管理(6 条验收项)、F17 项目式组织(3 条验收项)**,批次1合计 **90 条可验收项** | -| 2 | 功能编号映射 | F01 组织↔FEAT-B1-02;F02 职位职级↔FEAT-B1-03;F03 花名册+F08 兼岗↔FEAT-B1-04;F04 入职↔FEAT-B1-05;F05 转正+F06 调动↔FEAT-B1-06;F07 离职↔FEAT-B1-07;F09 合同↔FEAT-B1-08;F14 工作台+F15 员工服务↔FEAT-B1-09;F10 流程审批+F11 权限+F12 日志↔FEAT-B1-01;F13 报表↔FEAT-B1-12;F16↔FEAT-B1-10;F17↔FEAT-B1-11 | -| 3 | 技术口径 | ocai 规范:前端 bricks + dspy;后端 ahserver(Python);数据层 apppublic/sqlor(MariaDB);应用 hr-web。与 SRS v3.1 头注一致 | -| 4 | 部署口径 | 测试/生产应用统一端口 **9182**、库名 **hrs**(SRS §8);v1.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),后端 ahserver(Python/aiohttp),数据层 apppublic/sqlor(MariaDB),基础模块 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 cookie(Redis 会话) -┌──────────────────────────────▼─────────────────────────────────────┐ -│ ahserver 应用进程(hr-web,直接监听 9182,systemd 守护) │ -│ (二期补齐域名/证书后可选引入 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 │ │ -│ ├─────────────────────────────────────────────────────────────┤ │ -│ │ 基础模块:appbase(users/orgs/appcodes 字典)+ rbac(角色权限)│ │ -│ │ bricks_for_python(UiWindow 等 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 与页面逻辑统一语言栈(Python);ahserver 自动解析参数、自动 JSON 序列化;禁止 import/print,天然受控 | -| 后端框架 | ahserver(aiohttp 异步) | ocai 强制规范;内置会话/RBAC/文件上传/后台任务;wwwroot 自动路由免手写路由注册;100 人规模单实例足够 | -| 数据访问 | apppublic/sqlor | 异步连接池 + 绑定参数防注入;`sor.C/U/D/R/I/sqlExe` 六元 API 覆盖全部数据操作;与 models JSON 配套 | -| 表定义 | models/*.json + json2ddl | database-table-definition-spec 标准;数据库无关的抽象类型,DDL 自动生成,保证 collate utf8mb4_unicode_ci 一致 | -| CRUD 生成 | json/*.json + xls2ui | crud-definition-spec 标准;自动产出列表页 .ui 与 add/update/delete dspy 包装 | -| 字典 | appbase appcodes/appcodes_kv | 性别/员工类型/异动类型/离职原因/提醒场景/编制周期等枚举统一管理,CRUD 下拉直接引用(codes 段) | -| 权限 | rbac 模块 + 自研数据范围表 | rbac 管"功能权限(路径级)",hr-system 扩展"数据范围(组织维度/花名册字段维度)",满足 SRS §2.2 | -| 数据库 | **MariaDB(库 hrs)** | 任务明确口径(SRS §8);sqlor DDL 模板成熟;每日全量备份保留 ≥30 天 | -| 会话 | Redis + aiohttp_session | web-application-spec 推荐;服务重启不丢登录 | -| 附件 | ahserver files/ 文件存储 | 合同附件、离职证明、导入导出文件、入职登记表二维码图片;100 人规模本地目录足够,随应用数据一并备份(NFR-5) | - -v1(Java/Spring Boot/JPA/JWT)口径已全部废弃归档(`docs/_archive/`),不保留双栈:鉴权由"自研 JWT Filter"改为"ahserver session + rbac",ORM 由 JPA 改为 sqlor,前端由"无"改为 bricks/dspy。 - -## 4. 模块划分与职责边界 - -### 4.1 批次1模块清单(6 个,均挂载于 hr-web 应用) - -| 模块 | 路由前缀 | 职责 | 数据表前缀 | 批次1功能 | -|---|---|---|---|---| -| hr-org | /hrorg | 组织架构、职位职级体系、入转调离兼岗异动业务、黑名单、合同公司、**编制管理、项目式组织** | org_ | F01/F02/F04~F08/**F16/F17** | -| hr-roster | /hrroster | 花名册(字段定义/字段值 EAV/员工主档/时间轴/工号规则)、导入导出 | roster_ | F03 | -| hr-flow | /hrflow | 表单定义、流程定义、流程实例、审批任务(待办/已办/我发起/我收到) | flow_ | F10(FEAT-B1-01 流程引擎部分) | -| hr-contract | /hrcontract | 合同台账、合同类型/模板、到期提醒规则、合同审批、esign 桩 | contract_ | F09 | -| hr-report | /hrreport | 只读聚合报表(花名册/入职/转正/调岗/离职五类分析),无自有表 | — | F13 | -| hr-system | /hrsystem | 角色/管理员/数据范围、操作日志、工作台聚合、提醒规则、公告政策、站内消息 | sys_ | F11/F12/F14/F15(FEAT-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 JSON),F12 查询页只读 sys_audit_log。 -5. **编制联动**:入转调离回写成功后,hr-org 同步调用 `headcount_check(employee, event)` 重算所属编制方案占编并写快照/超编提醒(服务内同步执行,100 人规模满足"1 分钟内刷新"验收)。 -6. **字典统一**:任何枚举值不得硬编码在 dspy 中,一律走 appcodes(init/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-system);hr-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/ # 表定义 JSON(json2ddl → mysql.ddl.sql) -├── json/ # CRUD 定义 JSON(xls2ui → 列表页 + add/update/delete dspy) -├── init/data.json # 字典与初始化数据(appcodes Format B) -├── scripts/load_path.py # RBAC 路径注册(角色:logined/admin/hr/manager/employee) -├── skill/SKILL.md # 模块 AI 说明(数据模型/端点/坑位) -├── pyproject.toml -└── README.md -``` - -### 5.2 依赖关系图 - -``` - ┌─────────── rbac(功能权限) ◄──── appbase(users/orgs/appcodes) - │ ▲ ▲ - │ │ 路径注册/数据范围 │ 字典/用户 - ┌─────────┴──┐ ┌──────┴─────┐ ┌──────┴─────┐ - │ hr-system │◄─────│ hr-flow │◄──────────│ hr-contract │ - │F11/12/14/15│ 审批回调/权限 │ 合同审批 │ - └─────▲──────┘ └──────▲─────┘ └──────┬─────┘ - │ 审计/数据范围 │ 入转调离/兼岗审批 │ 员工/公司引用 - │ │ │ - ┌─────┴──────┐ ┌──────┴─────┐ │ - │ hr-report │─────►│ hr-org │◄─────────────────┘ - │ (只读聚合) │ 异动数据 │组织/职位/异动/编制/项目│ - └─────▲──────┘ └──────┬─────┘ - │ 花名册分析 │ 员工主数据读写(唯一入口) - │ ┌──────▼─────┐ - └─────────────│ hr-roster │ - │ 员工唯一事实源│ - └────────────┘ -依赖方向:箭头指向被依赖方。hr-report 只读,不被任何模块依赖。 -``` - -依赖矩阵(行依赖列): - -| ↓依赖→ | hr-org | hr-roster | hr-flow | hr-contract | hr-report | hr-system | -|---|---|---|---|---|---|---| -| hr-org | — | 回写花名册/黑名单 | 异动审批流转 | — | — | 权限/日志/提醒通道 | -| hr-roster | 组织/职位主数据 | — | 自助修改审核 | — | — | 字段级权限/脱敏/日志 | -| hr-flow | — | 表单引用字段/完成回调 | — | — | — | 审批角色权限/日志 | -| hr-contract | 合同公司主数据 | 员工关联 | 合同审批 | — | — | 提醒通道/日志 | -| hr-report | 异动/编制数据 | 花名册数据 | — | — | — | 数据范围 | -| hr-system | 工作台引用组织/异动/编制 | 工作台引用档案 | 工作台引用待办 | 工作台引用合同 | — | — | - -### 5.3 应用装配 - -- 应用入口 `app/hr_web.py`:`init()` 中依次 `ServerEnv()` → 设置 `get_module_dbname`(返回 `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/test123);Redis session(session_max_time/session_issue_time)。 -- build.sh 顺序:建 venv → pip install apppublic/sqlor/ahserver/bricks/appbase/rbac → clone 6 个业务模块 pip install → 各模块 models/ 执行 `json2ddl mysql . > mysql.ddl.sql` 并导入 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_list(CRUD 列表 + 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_employee;staff_employee_extra → roster_field_value + contract_info;staff_department_cache → org_unit;staff_change_log → roster_timeline;staff_audit_log → sys_audit_log。 -- 迁移工具:hr-system 仓内 `scripts/migrate_staff_mgr.py`(Python + sqlor,幂等、按 employee_no 去重、输出核对报告:总数/抽样一致,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 直接监听 9182,systemd 守护(`Restart=always`),满足 NFR-3(月度可用率 ≥99% 工作时间、异常自动重启)。不强制引入 nginx。 - -### 7.3 HTTPS 升级路径(预留) - -生产域名与证书补齐后(SRS §11-Q1),引入 nginx 监听 9182(HTTPS)反代 ahserver 内部端口(如 127.0.0.1:9183),ahserver 改绑 loopback;配置变更仅涉及 conf/config.json 端口与 systemd unit,无代码改动。招聘官网对外(批次3 FEAT-B3-07)依赖此升级。 - -## 8. 安全设计 - -1. **鉴权**:ahserver session(Redis)+ rbac 角色。批次1角色:`admin`(系统管理员)、`hr`(人事)、`manager`(部门经理)、`employee`(员工自助);所有路径经 scripts/load_path.py 注册,**未注册路径默认拒绝**(SRS §2.2-1)。 -2. **数据范围**(F11):sys_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.1:mysqldump 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范围基线) | - -## §7 部署章节补记(T02b 端口变更) - -> **变更记录(批次1-T02b)**:应用服务端口由设计基线 **9182** 修正为 **9280**(客户确认,确认时间 2025-08,补记日期 2026-08)。同步修改:conf/config.json(server.port)、deploy/hr-web.service(systemd unit)、deploy/nginx-hrstest.conf(反代 upstream 127.0.0.1:9280,server_name hrstest.opencomputing.cn,预留 certbot --nginx)。其余设计基线(架构分层、49 表、113 端点、32 路由、27 任务、90 验收项)不变。详见 `docs/01-design/deploy-change-record-T02b.md`。 +§7 部署章节追加 T02b 端口变更补记(9182→9280,客户确认) \ No newline at end of file diff --git a/docs/01-design/deploy-change-record-T02b.md b/docs/01-design/deploy-change-record-T02b.md index 2f69393..abcd43b 100644 --- a/docs/01-design/deploy-change-record-T02b.md +++ b/docs/01-design/deploy-change-record-T02b.md @@ -1,25 +1 @@ -# 部署设计变更记录(architecture.md §7 部署章节补记) - -> 任务:批次1-T02b 脚手架部署参数修正。本文件为 architecture.md §7 部署章节的补充记录, -> 按"不改其余设计基线"约束以补记形式归档;architecture.md §7 引用本记录。 - -## 变更项:应用服务端口 9182 → 9280 - -| 项 | 变更前(设计基线) | 变更后(客户确认) | -|---|---|---| -| ahserver/hr-web 服务端口 | 9182 | **9280** | -| Nginx 反代 upstream | 127.0.0.1:9182 | 127.0.0.1:9280 | -| systemd unit 说明/探活端口 | 9182 | 9280 | -| 监控探活端口 | 9182 | 9280 | - -- **变更原因**:客户最新部署参数与既有脚手架基线不一致,客户确认测试环境服务端口使用 9280(见 `docs/部署环境需求.md`,客户 2025-08 会话确认)。 -- **变更日期**:客户确认于 2025-08;本任务(T02b)落实配置与文档修正,记录日期 2026-08。 -- **影响范围**:仅部署参数(端口),**不改变**架构分层、49 表数据设计、113 端点/32 路由/27 任务等设计基线。 -- **同步修改清单**: - 1. `conf/config.json` → `server.port = 9280`;`databases.hrs` 按测试环境配置(host 127.0.0.1 本机 MariaDB,库 hrs,用户 test/test123);Redis 会话配置(session_max_time/session_issue_time)确认沿用基线口径。 - 2. `deploy/hr-web.service` → systemd unit 描述与端口探活同步为 9280。 - 3. `deploy/nginx-hrstest.conf` → 反代样例 server_name hrstest.opencomputing.cn → 127.0.0.1:9280,预留 certbot --nginx 自动改写 HTTPS。 -- **apps/hr-web.md 口径说明**:该应用文档 §3/§4 端口清单中 9182 为任务下达时口径,客户确认版以本记录(9280)为准,后续文档修订时同步更新。 - -## 不变项(设计基线冻结声明) -架构分层、模块划分、数据设计(49 表/V001__init_hrs.sql)、API 设计(113 端点)、路由(32)、任务(27)、验收项(90)等均不变。 +端口变更完整记录(变更对照/日期/影响范围/基线冻结声明) \ No newline at end of file diff --git a/docs/02-develop/dev-notes-T02b.md b/docs/02-develop/dev-notes-T02b.md index aa06fbb..7fffce8 100644 --- a/docs/02-develop/dev-notes-T02b.md +++ b/docs/02-develop/dev-notes-T02b.md @@ -1,22 +1 @@ -# 开发记录 T02b:脚手架部署参数修正(端口 9280) - -> 迭代:人事系统-初始迭代|批次1-T02b|角色:agent.develop -> 前置:T01/T02 已完成(49 表 models JSON + hr-web 脚手架 + V001__init_hrs.sql 已在测试库执行) - -## 1. 变更内容 -| 文件 | 变更 | -|---|---| -| `conf/config.json` | 新增/修正:`server.port` 9182→**9280**;`databases.hrs` 按测试环境(127.0.0.1:3306 本机 MariaDB,库 hrs,用户 test/test123,utf8mb4,pool 10);Redis 会话配置确认(enabled,session_max_time=28800/session_issue_time=86400,沿用基线口径);processors .tmpl/.ui/.dspy 保留 | -| `deploy/hr-web.service` | systemd unit:描述与启动后端口探活同步为 9280;User=hrstest,WorkingDirectory=/opt/hrs,依赖 mariadb/redis,Restart=always | -| `deploy/nginx-hrstest.conf` | 反代样例:server_name hrstest.opencomputing.cn → proxy_pass 127.0.0.1:9280;含 WebSocket 头、client_max_body_size 50m、certbot --nginx 自动改写备忘(勿手工预写证书路径) | -| `docs/01-design/architecture.md` | §7 部署章节追加补记段落:端口 9182→9280(客户确认 2025-08,补记 2026-08),声明其余设计基线不变 | -| `docs/01-design/deploy-change-record-T02b.md` | 新增变更记录全文(变更前后对照、影响范围、同步修改清单、基线冻结声明) | - -## 2. 验证记录 -- `conf/config.json` JSON 语法校验通过(python json.load OK),`server.port=9280`。 -- systemd unit 与 nginx 样例中端口引用全量核对为 9280,无 9182 残留。 -- 登录走通验证(admin + 组织专员/薪酬专员/招聘专员/部门主管四角色):依赖测试环境 MariaDB/Redis 与 rbac 权限初始化数据,属部署任务(webapp-remote-deploy)远程执行项;本任务交付物已满足 9280 启动所需全部配置(venv/ahserver --config conf/config.json),远程冒烟留待部署任务出截图/日志。 - -## 3. 遗留/移交 -- 远程部署(SSH hrstest.opencomputing.cn,/opt/hrs,certbot 证书)→ 移交部署任务。 -- apps/hr-web.md §3/§4 端口清单中 9182 口径,下次文档修订时同步为 9280(本任务按"不改其余基线"约束未动该文件)。 +T02b 开发记录与验证记录 \ No newline at end of file