日期: 2026-07-30
状态: 已实现(计划见 docs/superpowers/plans/2026-07-30-oa-confirmation-kit.md)
范围: web-admin 用户管理主数据补齐;审批设计器「套件」Tab 转正套件;发起/详情运行时默认与联动;backend 审批通过后回写发起人 sys_user
界面模式: 对齐请假套件与 FormCreate 控件库;视觉 Fresh Mint
前置:
docs/superpowers/specs/2026-07-30-oa-leave-kit-design.md(套件组装体模式)docs/superpowers/specs/2026-07-30-oa-post-select-design.md(职位组件)docs/superpowers/specs/2026-07-27-oa-dept-select-design.md(部门组件)docs/superpowers/specs/2026-07-30-oa-owner-fields-design.md(发起人默认值模式可参考)在「2 表单设计」套件 Tab 增加 转正套件:一键插入转正申请常用字段;发起时自动带出申请人主数据;审批全部通过后将约定字段回写发起人用户主数据。
sys_user 补齐 入职日期、试用期(月数);用户管理可编辑。| 项 | 决策 |
|---|---|
| 实现方案 | 方案 1:套件容器 + 子字段拼装(非一体值对象) |
| 容器类型 | confirmationKit |
| 回写时机 | 审批 全部通过 后再回写 |
| 回写对象 | 始终 发起人 的 sys_user |
| 回写字段 | 入职日期、试用期月数、姓名、邮箱、部门、手机号 |
| 不回写 | 职位、岗位职级、转正日期(仅审批单) |
| 试用期存储 | 整数月数(如 3),界面展示「3 个月」 |
| 转正日期 | 有入职日 + 试用期时自动建议,仍可改 |
| 转正日联动 | 未手改则随入职/试用期重算;手改后断开;可「恢复自动计算」 |
| 职位默认 | 不默认,发起人自选 |
| 职位选择 | 保持现有职位组件 多选 |
| 部门控件 | 现有「部门」组件,值 { id, name } |
| 显示/隐藏 | 设计器按子字段配置;隐藏不展示、不前端必填 |
| 隐藏与回写 | 隐藏字段若有默认/提交值,通过后 仍回写(设计器弱提示) |
| 回写空值 | 某字段为空则 跳过该列,不清空主数据 |
| 回写失败 | 校验失败 不回滚 审批通过状态,记日志/告警 |
┌─ 转正套件(confirmationKit / 容器)────────────────────┐
│ 套件属性:子字段显示/隐藏 │
│ │
│ · datePicker → 入职日期 ← 默认申请人 │
│ · inputNumber → 试用期(月) ← 默认申请人 │
│ · datePicker → 转正日期 ← 自动建议,可改 │
│ · post → 职位 ← 不默认,多选 │
│ · input → 岗位职级 ← 空 │
│ · input → 姓名 ← 默认申请人 │
│ · input → 邮箱 ← 默认申请人 │
│ · dept → 部门 ← 默认主部门 │
│ · input → 手机号 ← 默认申请人 │
└─────────────────────────────────────────────────────────┘
| 语义 key | 建议 title | type | 必填默认 | 回写 |
|---|---|---|---|---|
hireDate |
入职日期 | datePicker(仅日期,YYYY-MM-DD) |
是 | ✓ → hire_date |
probationMonths |
试用期(月) | inputNumber,整数 ≥0 |
是 | ✓ → probation_months |
confirmationDate |
转正日期 | datePicker(仅日期) |
否 | ✗ |
post |
职位 | post(现有,多选) |
否 | ✗ |
jobLevel |
岗位职级 | input |
否 | ✗ |
name |
姓名 | input |
是 | ✓ → nick_name |
email |
邮箱 | input |
否 | ✓ → email |
dept |
部门 | dept(现有,建议单选) |
是 | ✓ → dept_id ← id |
phone |
手机号 | input |
否 | ✓ → phone_no |
插入时子字段 field 生成唯一 ID(同表单可多套,自动去重后缀)。语义识别优先稳定标记(如 props._fc_kit_field: 'hireDate'),避免仅依赖 title。
{
"type": "confirmationKit",
"props": {
"visibleFields": {
"hireDate": true,
"probationMonths": true,
"confirmationDate": true,
"post": true,
"jobLevel": true,
"name": true,
"email": true,
"dept": true,
"phone": true
}
},
"children": [
{
"type": "datePicker",
"field": "hireDate_xxxx",
"title": "入职日期",
"props": {
"_fc_kit_field": "hireDate",
"type": "date",
"valueFormat": "YYYY-MM-DD"
},
"$required": true
},
{
"type": "inputNumber",
"field": "probationMonths_xxxx",
"title": "试用期(月)",
"props": { "_fc_kit_field": "probationMonths", "min": 0, "precision": 0 },
"$required": true
},
{
"type": "datePicker",
"field": "confirmationDate_xxxx",
"title": "转正日期",
"props": {
"_fc_kit_field": "confirmationDate",
"type": "date",
"valueFormat": "YYYY-MM-DD",
"confirmationDateManual": false
},
"$required": false
},
{
"type": "post",
"field": "post_xxxx",
"title": "职位",
"props": { "_fc_kit_field": "post", "multiple": true }
},
{
"type": "input",
"field": "jobLevel_xxxx",
"title": "岗位职级",
"props": { "_fc_kit_field": "jobLevel" }
},
{
"type": "input",
"field": "name_xxxx",
"title": "姓名",
"props": { "_fc_kit_field": "name" },
"$required": true
},
{
"type": "input",
"field": "email_xxxx",
"title": "邮箱",
"props": { "_fc_kit_field": "email" }
},
{
"type": "dept",
"field": "dept_xxxx",
"title": "部门",
"props": { "_fc_kit_field": "dept", "multiple": false },
"$required": true
},
{
"type": "input",
"field": "phone_xxxx",
"title": "手机号",
"props": { "_fc_kit_field": "phone" }
}
]
}
容器为布局类,不计可填字段数;visibleFields 与子字段 hidden 保持同步(实现时二选一为主、另一派生即可,文档以「隐藏不展示」为准)。
| 字段 | 格式 |
|---|---|
| 日期 | YYYY-MM-DD |
| 试用期 | 整数 |
| 部门 | { id, name }(全路径名称优先) |
| 职位 | 与现有 post 一致(多选为数组) |
| 姓名/邮箱/手机号/职级 | 字符串 |
sys_user 增补| 列 | 类型 | 说明 |
|---|---|---|
hire_date |
DATE NULL |
入职日期 |
probation_months |
INT NULL |
试用期月数(≥0) |
同步范围:
SysUser、CRUD _row_to_dict、Create/Update BodyuserInfo / _build_user_info_payload 带出 hireDate、probationMonthsdocs/sql/ 增量脚本;字段一致性检查既有已具备且用户管理可编辑:nick_name(姓名)、email、dept_id、phone_no。
仅对 空字段 写入(不覆盖用户已填):
| 语义 | 来源 |
|---|---|
| hireDate | userInfo.hireDate |
| probationMonths | userInfo.probationMonths |
| confirmationDate | 入职 + 试用期可算则写入建议值;否则空 |
| post | 不填 |
| jobLevel | 空 |
| name | 显示名 / nickName |
email |
|
| dept | 主部门 { id, name }(全路径优先) |
| phone | phoneNo |
formData(便于通过后回写)。form_data,不按当前查看者覆盖。confirmationDate = hireDate 按自然月加 probationMonths(实现时与前端/后端同一工具函数,可单测)。confirmationDateManual === false:入职日或试用期变化时重算并写回转正日。confirmationDateManual = true,断开联动。formData。confirmationKit;套件子节点缺失 → 警告可发(对齐请假)。实例状态变为 全部通过 时调用:
apply_confirmation_kit_user_sync(db, instance)
挂在现有「通过」后置点,避免散落多 API。
实例 → 全部通过
→ 扫描 form schema 中 confirmationKit
→ 解析 children 语义标记 → 从 form_data 取值
→ 目标用户 = 发起人 user_id
→ 有值则更新对应列;空则跳过
→ 格式校验失败:记日志,不回滚通过状态
| 语义 | sys_user 列 |
|---|---|
| hireDate | hire_date |
| probationMonths | probation_months |
| name | nick_name |
email |
|
| dept | dept_id(取 id) |
| phone | phone_no |
不写:post、jobLevel、confirmationDate。
hidden / visibleFields。| 区域 | 路径(示意) |
|---|---|
| 套件容器 | web-admin/src/components/oa-approval/OaConfirmationKit.vue |
| DragRule | web-admin/src/utils/oa-confirmation-kit-rule.ts |
| 注册 | 现有 kit 注册入口旁增加转正 |
| 默认值 + 联动 | web-admin/src/utils/oa-confirmation-kit-runtime.ts |
| 自然月加 | 前后端共享算法(前端 TS + 后端 Python,行为一致) |
| 用户管理 | web-admin/src/views/system/user/index.vue + API 类型 |
| 模型 / SQL | SysUser + docs/sql/ 增量 |
| userInfo | backend _build_user_info_payload |
| 回写服务 | backend/app/services/oa_confirmation_kit_sync.py + 通过态钩子 |
userInfo 可带出。{id,name};职位为现有多选控件。visibleFields 与子字段 hidden 以何者为 source of truth:实现选一并在 runtime 归一化。