- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro) - CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/ - 新增 /spec-close、/pre-change 两个工作流命令 - DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表) - BD_Manual → BD_manual 命名统一(48 个文件) - 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数) - 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表) - 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档) - docs/database/README.md 索引更新 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9.2 KiB
9.2 KiB
BD 手册:public Schema — RBAC 与工作流(8 表)
目标库:
zqyy_app(通过APP_DB_DSN连接) DDL 位置:docs/database/ddl/zqyy_app__public.sql关联文档:BD_manual_scheduled_tasks.md(调度相关 3 表)、BD_manual_member_retention_clue.md(维客线索表)
1. 概述
public Schema 共 12 张表,本文档覆盖其中 RBAC(角色权限)+ 工作流(任务审批)共 8 张表。其余 4 张表已有独立文档:
| 表 | 文档 |
|---|---|
scheduled_tasks、task_queue、task_execution_log |
BD_manual_scheduled_tasks.md |
member_retention_clue |
BD_manual_member_retention_clue.md |
表关系
admin_users(管理后台登录账户,roles 数组字段)
users ──┬── user_roles ── roles ── role_permissions ── permissions
│ (用户-角色映射) (角色) (角色-权限映射) (权限)
│
├── tasks(任务指派,creator_id / assignee_id → users)
│ │
└── approvals(审批记录,approver_id → users,task_id → tasks)
2. 表结构
public.admin_users(9 字段)
管理后台(admin-web / tenant-admin)登录账户。通过 JWT aud=admin 或 aud=tenant-admin 认证。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
SERIAL | PK | 自增主键 |
username |
VARCHAR(64) | NOT NULL, UNIQUE | 登录用户名 |
password_hash |
VARCHAR(256) | NOT NULL | bcrypt 密码哈希 |
display_name |
VARCHAR(128) | 可空 | 显示名称 |
site_id |
BIGINT | NOT NULL | 所属门店 ID |
is_active |
BOOLEAN | DEFAULT true | 是否启用 |
roles |
TEXT[] | NOT NULL, DEFAULT '{site_admin}' | 角色数组(site_admin / tenant_admin 等) |
created_at |
TIMESTAMPTZ | DEFAULT NOW() | 创建时间 |
updated_at |
TIMESTAMPTZ | DEFAULT NOW() | 更新时间 |
注意:
admin_users.roles是 TEXT 数组字段(快捷权限标记),与roles表的 RBAC 体系并行使用。admin-web 当前主要依赖此数组字段做权限判断。
public.users(8 字段)
小程序端用户(C 端会员),通过微信 code → JWT aud=miniapp 认证。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
BIGSERIAL | PK | 自增主键 |
wx_openid |
TEXT | UNIQUE,可空 | 微信 OpenID(登录唯一标识) |
mobile |
TEXT | 可空 | 手机号 |
nickname |
TEXT | 可空 | 用户昵称 |
status |
INTEGER | DEFAULT 1 | 状态(1=正常) |
site_id |
BIGINT | NOT NULL | 所属门店 ID |
created_at |
TIMESTAMPTZ | DEFAULT NOW() | 创建时间 |
updated_at |
TIMESTAMPTZ | DEFAULT NOW() | 更新时间 |
public.roles(5 字段)
角色定义表,按门店隔离。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
SERIAL | PK | 自增主键 |
name |
TEXT | NOT NULL, UNIQUE | 角色名称(全局唯一) |
description |
TEXT | 可空 | 角色描述 |
site_id |
BIGINT | NOT NULL | 所属门店 ID |
created_at |
TIMESTAMPTZ | DEFAULT NOW() | 创建时间 |
public.permissions(4 字段)
权限定义表(资源+动作组合)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
SERIAL | PK | 自增主键 |
resource |
TEXT | NOT NULL | 资源标识(如 etl、users) |
action |
TEXT | NOT NULL | 操作标识(如 read、write、execute) |
description |
TEXT | 可空 | 权限描述 |
public.role_permissions(2 字段)
角色-权限关联表(多对多)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
role_id |
INTEGER | PK, FK → roles(id) ON DELETE CASCADE | 角色 ID |
permission_id |
INTEGER | PK, FK → permissions(id) ON DELETE CASCADE | 权限 ID |
public.user_roles(3 字段)
用户-角色关联表(多对多),按门店隔离。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
user_id |
BIGINT | PK, FK → users(id) ON DELETE CASCADE | 用户 ID |
role_id |
INTEGER | PK, FK → roles(id) ON DELETE CASCADE | 角色 ID |
site_id |
BIGINT | NOT NULL | 门店 ID |
public.tasks(9 字段)
任务指派表,用于门店内任务管理。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
BIGSERIAL | PK | 自增主键 |
title |
TEXT | NOT NULL | 任务标题 |
description |
TEXT | 可空 | 任务描述 |
status |
TEXT | DEFAULT 'pending' | 状态:pending / in_progress / completed |
assignee_id |
BIGINT | FK → users(id),可空 | 负责人 ID |
creator_id |
BIGINT | FK → users(id),可空 | 创建人 ID |
site_id |
BIGINT | NOT NULL | 门店 ID |
created_at |
TIMESTAMPTZ | DEFAULT NOW() | 创建时间 |
updated_at |
TIMESTAMPTZ | DEFAULT NOW() | 更新时间 |
public.approvals(7 字段)
审批记录表,关联到任务。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
BIGSERIAL | PK | 自增主键 |
task_id |
BIGINT | FK → tasks(id) ON DELETE CASCADE,可空 | 关联任务 ID |
approver_id |
BIGINT | FK → users(id),可空 | 审批人 ID |
status |
TEXT | DEFAULT 'pending' | 状态:pending / approved / rejected |
comment |
TEXT | 可空 | 审批意见 |
site_id |
BIGINT | NOT NULL | 门店 ID |
created_at |
TIMESTAMPTZ | DEFAULT NOW() | 创建时间 |
3. 约束与索引
| 表 | 约束/索引名 | 类型 | 说明 |
|---|---|---|---|
admin_users |
admin_users_pkey |
PK | (id) |
admin_users |
admin_users_username_key |
UNIQUE | (username) |
admin_users |
idx_admin_users_site |
INDEX | (site_id) |
users |
users_pkey |
PK | (id) |
users |
users_wx_openid_key |
UNIQUE | (wx_openid) |
users |
idx_users_site_id |
INDEX | (site_id) |
users |
idx_users_mobile |
INDEX | (mobile) |
roles |
roles_pkey |
PK | (id) |
roles |
roles_name_key |
UNIQUE | (name) |
roles |
idx_roles_site_id |
INDEX | (site_id) |
permissions |
permissions_pkey |
PK | (id) |
permissions |
permissions_resource_action_key |
UNIQUE | (resource, action) |
role_permissions |
role_permissions_pkey |
PK | (role_id, permission_id) |
role_permissions |
FK role_id |
FK | → roles(id) ON DELETE CASCADE |
role_permissions |
FK permission_id |
FK | → permissions(id) ON DELETE CASCADE |
user_roles |
user_roles_pkey |
PK | (user_id, role_id) |
user_roles |
FK user_id |
FK | → users(id) ON DELETE CASCADE |
user_roles |
FK role_id |
FK | → roles(id) ON DELETE CASCADE |
user_roles |
idx_user_roles_site_id |
INDEX | (site_id) |
tasks |
tasks_pkey |
PK | (id) |
tasks |
FK assignee_id |
FK | → users(id) |
tasks |
FK creator_id |
FK | → users(id) |
tasks |
idx_tasks_site_id |
INDEX | (site_id) |
tasks |
idx_tasks_status |
INDEX | (status) |
tasks |
idx_tasks_assignee_id |
INDEX | (assignee_id) |
approvals |
approvals_pkey |
PK | (id) |
approvals |
FK task_id |
FK | → tasks(id) ON DELETE CASCADE |
approvals |
FK approver_id |
FK | → users(id) |
approvals |
idx_approvals_site_id |
INDEX | (site_id) |
approvals |
idx_approvals_task_id |
INDEX | (task_id) |
4. 兼容性影响
| 组件 | 影响 |
|---|---|
| admin-web | 直接依赖。登录用 admin_users,权限判断用 admin_users.roles 数组 |
| tenant-admin | 直接依赖。登录也用 admin_users(aud=tenant-admin),按 site_id 隔离 |
| 后端 API | admin_users 用于 JWT 签发和验证;RBAC 表(roles/permissions/user_roles)用于细粒度权限控制 |
| 小程序 | 通过 users 表完成微信登录注册和用户信息管理 |
| ETL | 无直接影响 |
5. 验证 SQL
-- 1. 验证 8 张表存在
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name IN ('admin_users', 'users', 'roles', 'permissions',
'role_permissions', 'user_roles', 'tasks', 'approvals')
ORDER BY table_name;
-- 预期:8 行
-- 2. 验证 admin_users 字段数量
SELECT COUNT(*)
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'admin_users';
-- 预期:9
-- 3. 验证 admin_users.roles 默认值
SELECT column_default
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'admin_users' AND column_name = 'roles';
-- 预期:'{site_admin}'::text[]
-- 4. 验证外键关系
SELECT tc.table_name, tc.constraint_name, ccu.table_name AS references_table
FROM information_schema.table_constraints tc
JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name
WHERE tc.table_schema = 'public'
AND tc.constraint_type = 'FOREIGN KEY'
AND tc.table_name IN ('approvals', 'tasks', 'role_permissions', 'user_roles')
ORDER BY tc.table_name;
-- 预期:7 行外键
-- 5. 验证 permissions 唯一约束
SELECT constraint_name
FROM information_schema.table_constraints
WHERE table_schema = 'public' AND table_name = 'permissions' AND constraint_type = 'UNIQUE';
-- 预期:permissions_resource_action_key