From 478e37903b711d5a2299a8acbe0d7e8c26559453 Mon Sep 17 00:00:00 2001 From: huang Date: Mon, 15 Dec 2025 14:37:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0callback,=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/bootstrap/bootstrap.go | 5 + internal/model/account.go | 16 +- internal/model/base.go | 12 +- internal/model/permission.go | 2 +- internal/model/role.go | 2 +- internal/model/role_permission.go | 2 +- migrations/000001_add_table_comment.down.sql | 4 + migrations/000001_add_table_comment.up.sql | 4 + .../000002_rbac_data_permission.down.sql | 9 - migrations/000002_rbac_data_permission.up.sql | 185 ------------------ .../000003_add_owner_id_shop_id.down.sql | 19 -- migrations/000003_add_owner_id_shop_id.up.sql | 35 ---- .../000004_drop_legacy_user_order.down.sql | 83 -------- .../000004_drop_legacy_user_order.up.sql | 13 -- pkg/database/postgres.go | 6 + pkg/gorm/callback.go | 22 ++- 16 files changed, 52 insertions(+), 367 deletions(-) create mode 100644 migrations/000001_add_table_comment.down.sql create mode 100644 migrations/000001_add_table_comment.up.sql delete mode 100644 migrations/000002_rbac_data_permission.down.sql delete mode 100644 migrations/000002_rbac_data_permission.up.sql delete mode 100644 migrations/000003_add_owner_id_shop_id.down.sql delete mode 100644 migrations/000003_add_owner_id_shop_id.up.sql delete mode 100644 migrations/000004_drop_legacy_user_order.down.sql delete mode 100644 migrations/000004_drop_legacy_user_order.up.sql diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go index 0b068a2..586cdce 100644 --- a/internal/bootstrap/bootstrap.go +++ b/internal/bootstrap/bootstrap.go @@ -44,6 +44,11 @@ func registerGORMCallbacks(deps *Dependencies, stores *stores) error { return err } + //注册自动添加创建&更新人 Clalback + if err := pkgGorm.RegisterSetCreatorUpdaterCallback(deps.DB); err != nil { + return err + } + // TODO: 在此添加其他 GORM Callbacks return nil diff --git a/internal/model/account.go b/internal/model/account.go index fe6591a..3c90825 100644 --- a/internal/model/account.go +++ b/internal/model/account.go @@ -7,14 +7,14 @@ import ( // Account 账号模型 type Account struct { gorm.Model - BaseModel - Username string `gorm:"uniqueIndex:idx_account_username,where:deleted_at IS NULL;not null;size:50" json:"username"` - Phone string `gorm:"uniqueIndex:idx_account_phone,where:deleted_at IS NULL;not null;size:20" json:"phone"` - Password string `gorm:"not null;size:255" json:"-"` // 不返回给客户端 - UserType int `gorm:"not null;index" json:"user_type"` // 1=root, 2=平台, 3=代理, 4=企业 - ShopID *uint `gorm:"index" json:"shop_id,omitempty"` - ParentID *uint `gorm:"index" json:"parent_id,omitempty"` - Status int `gorm:"not null;default:1" json:"status"` // 0=禁用, 1=启用 + BaseModel `gorm:"embedded"` + Username string `gorm:"uniqueIndex:idx_account_username,where:deleted_at IS NULL;not null;size:50" json:"username"` + Phone string `gorm:"uniqueIndex:idx_account_phone,where:deleted_at IS NULL;not null;size:20" json:"phone"` + Password string `gorm:"not null;size:255" json:"-"` // 不返回给客户端 + UserType int `gorm:"not null;index" json:"user_type"` // 1=root, 2=平台, 3=代理, 4=企业 + ShopID *uint `gorm:"index" json:"shop_id,omitempty"` + ParentID *uint `gorm:"index" json:"parent_id,omitempty"` + Status int `gorm:"not null;default:1" json:"status"` // 0=禁用, 1=启用 } // TableName 指定表名 diff --git a/internal/model/base.go b/internal/model/base.go index b0efe8b..4b1c489 100644 --- a/internal/model/base.go +++ b/internal/model/base.go @@ -1,17 +1,9 @@ package model -import "gorm.io/gorm" - +// atlas:ignore +// // BaseModel 基础模型,包含通用字段 type BaseModel struct { Creator uint `gorm:"not null" json:"creator"` Updater uint `gorm:"not null" json:"updater"` } - -func (b *BaseModel) BeforeCreate(tx *gorm.DB) error { - if userID, ok := tx.Statement.Context.Value("current_user_id").(uint); ok { - b.Creator = userID - b.Updater = userID - } - return nil -} diff --git a/internal/model/permission.go b/internal/model/permission.go index a6615df..6b66f07 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -7,7 +7,7 @@ import ( // Permission 权限模型 type Permission struct { gorm.Model - BaseModel + BaseModel `gorm:"embedded"` PermName string `gorm:"not null;size:50" json:"perm_name"` PermCode string `gorm:"uniqueIndex:idx_permission_code,where:deleted_at IS NULL;not null;size:100" json:"perm_code"` diff --git a/internal/model/role.go b/internal/model/role.go index 5ee994d..49cb08d 100644 --- a/internal/model/role.go +++ b/internal/model/role.go @@ -7,7 +7,7 @@ import ( // Role 角色模型 type Role struct { gorm.Model - BaseModel + BaseModel `gorm:"embedded"` RoleName string `gorm:"not null;size:50" json:"role_name"` RoleDesc string `gorm:"size:255" json:"role_desc"` diff --git a/internal/model/role_permission.go b/internal/model/role_permission.go index 545fcd8..9a67e9c 100644 --- a/internal/model/role_permission.go +++ b/internal/model/role_permission.go @@ -7,7 +7,7 @@ import ( // RolePermission 角色-权限关联模型 type RolePermission struct { gorm.Model - BaseModel + BaseModel `gorm:"embedded"` RoleID uint `gorm:"not null;index;uniqueIndex:idx_role_permission_unique,where:deleted_at IS NULL" json:"role_id"` PermID uint `gorm:"not null;index;uniqueIndex:idx_role_permission_unique,where:deleted_at IS NULL" json:"perm_id"` diff --git a/migrations/000001_add_table_comment.down.sql b/migrations/000001_add_table_comment.down.sql new file mode 100644 index 0000000..a62bc58 --- /dev/null +++ b/migrations/000001_add_table_comment.down.sql @@ -0,0 +1,4 @@ +COMMENT ON TABLE tb_account IS null; +COMMENT ON TABLE tb_permission IS null; +COMMENT ON TABLE tb_role IS null; +COMMENT ON TABLE tb_role_permission IS null; diff --git a/migrations/000001_add_table_comment.up.sql b/migrations/000001_add_table_comment.up.sql new file mode 100644 index 0000000..babfc64 --- /dev/null +++ b/migrations/000001_add_table_comment.up.sql @@ -0,0 +1,4 @@ +COMMENT ON TABLE tb_account IS '账号信息表'; +COMMENT ON TABLE tb_permission IS '权限表'; +COMMENT ON TABLE tb_role IS '角色表'; +COMMENT ON TABLE tb_role_permission IS '角色权限表'; diff --git a/migrations/000002_rbac_data_permission.down.sql b/migrations/000002_rbac_data_permission.down.sql deleted file mode 100644 index dc8efc1..0000000 --- a/migrations/000002_rbac_data_permission.down.sql +++ /dev/null @@ -1,9 +0,0 @@ --- RBAC 表结构回滚迁移 --- 删除所有 RBAC 相关表 - --- 删除表(按依赖顺序反向删除) -DROP TABLE IF EXISTS tb_role_permission; -DROP TABLE IF EXISTS tb_account_role; -DROP TABLE IF EXISTS tb_permission; -DROP TABLE IF EXISTS tb_role; -DROP TABLE IF EXISTS tb_account; diff --git a/migrations/000002_rbac_data_permission.up.sql b/migrations/000002_rbac_data_permission.up.sql deleted file mode 100644 index 41b086c..0000000 --- a/migrations/000002_rbac_data_permission.up.sql +++ /dev/null @@ -1,185 +0,0 @@ --- RBAC 表结构迁移 --- 创建 5 个 RBAC 核心表:账号、角色、权限、账号-角色关联、角色-权限关联 - --- ============================================================================= --- T014: tb_account (账号表) --- ============================================================================= -CREATE TABLE IF NOT EXISTS tb_account ( - id BIGSERIAL PRIMARY KEY, - username VARCHAR(50) NOT NULL, - phone VARCHAR(20) NOT NULL, - password VARCHAR(255) NOT NULL, - user_type SMALLINT NOT NULL, -- 1=root, 2=平台, 3=代理, 4=企业 - shop_id INTEGER, - parent_id INTEGER, -- 上级账号 ID(自关联) - status SMALLINT NOT NULL DEFAULT 1, -- 0=禁用, 1=启用 - creator INTEGER NOT NULL, - updater INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP -); - --- T015: tb_account 索引 -CREATE UNIQUE INDEX IF NOT EXISTS idx_account_username ON tb_account(username) WHERE deleted_at IS NULL; -CREATE UNIQUE INDEX IF NOT EXISTS idx_account_phone ON tb_account(phone) WHERE deleted_at IS NULL; -CREATE INDEX IF NOT EXISTS idx_account_user_type ON tb_account(user_type); -CREATE INDEX IF NOT EXISTS idx_account_shop_id ON tb_account(shop_id); -CREATE INDEX IF NOT EXISTS idx_account_parent_id ON tb_account(parent_id); -CREATE INDEX IF NOT EXISTS idx_account_deleted_at ON tb_account(deleted_at); - --- tb_account 表和字段注释 -COMMENT ON TABLE tb_account IS '账号表:存储系统用户账号信息,支持层级关系和软删除'; -COMMENT ON COLUMN tb_account.id IS '主键 ID'; -COMMENT ON COLUMN tb_account.username IS '用户名(唯一,软删除后可重用)'; -COMMENT ON COLUMN tb_account.phone IS '手机号(唯一,软删除后可重用)'; -COMMENT ON COLUMN tb_account.password IS 'bcrypt 哈希密码'; -COMMENT ON COLUMN tb_account.user_type IS '用户类型:1=root(超级管理员), 2=平台(平台账号), 3=代理(代理商), 4=企业(企业用户)'; -COMMENT ON COLUMN tb_account.shop_id IS '所属店铺 ID(用于数据权限隔离)'; -COMMENT ON COLUMN tb_account.parent_id IS '上级账号 ID(自关联,用于层级关系和递归查询)'; -COMMENT ON COLUMN tb_account.status IS '状态:0=禁用, 1=启用'; -COMMENT ON COLUMN tb_account.creator IS '创建人 ID'; -COMMENT ON COLUMN tb_account.updater IS '更新人 ID'; -COMMENT ON COLUMN tb_account.created_at IS '创建时间'; -COMMENT ON COLUMN tb_account.updated_at IS '更新时间'; -COMMENT ON COLUMN tb_account.deleted_at IS '软删除时间(NULL 表示未删除)'; - --- ============================================================================= --- T016: tb_role (角色表) --- ============================================================================= -CREATE TABLE IF NOT EXISTS tb_role ( - id BIGSERIAL PRIMARY KEY, - role_name VARCHAR(50) NOT NULL, - role_desc VARCHAR(255), - role_type SMALLINT NOT NULL, -- 1=超级, 2=代理, 3=企业 - status SMALLINT NOT NULL DEFAULT 1, -- 0=禁用, 1=启用 - creator INTEGER NOT NULL, - updater INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP -); - --- T017: tb_role 索引 -CREATE INDEX IF NOT EXISTS idx_role_role_type ON tb_role(role_type); -CREATE INDEX IF NOT EXISTS idx_role_deleted_at ON tb_role(deleted_at); - --- tb_role 表和字段注释 -COMMENT ON TABLE tb_role IS '角色表:定义系统角色,支持软删除'; -COMMENT ON COLUMN tb_role.id IS '主键 ID'; -COMMENT ON COLUMN tb_role.role_name IS '角色名称'; -COMMENT ON COLUMN tb_role.role_desc IS '角色描述'; -COMMENT ON COLUMN tb_role.role_type IS '角色类型:1=超级角色, 2=代理角色, 3=企业角色'; -COMMENT ON COLUMN tb_role.status IS '状态:0=禁用, 1=启用'; -COMMENT ON COLUMN tb_role.creator IS '创建人 ID'; -COMMENT ON COLUMN tb_role.updater IS '更新人 ID'; -COMMENT ON COLUMN tb_role.created_at IS '创建时间'; -COMMENT ON COLUMN tb_role.updated_at IS '更新时间'; -COMMENT ON COLUMN tb_role.deleted_at IS '软删除时间(NULL 表示未删除)'; - --- ============================================================================= --- T018: tb_permission (权限表) --- ============================================================================= -CREATE TABLE IF NOT EXISTS tb_permission ( - id BIGSERIAL PRIMARY KEY, - perm_name VARCHAR(50) NOT NULL, - perm_code VARCHAR(100) NOT NULL, -- 权限编码(如 user:create) - perm_type SMALLINT NOT NULL, -- 1=菜单, 2=按钮 - url VARCHAR(255), - parent_id INTEGER, -- 上级权限 ID(层级) - sort INTEGER NOT NULL DEFAULT 0, - status SMALLINT NOT NULL DEFAULT 1, -- 0=禁用, 1=启用 - creator INTEGER NOT NULL, - updater INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP -); - --- T019: tb_permission 索引 -CREATE UNIQUE INDEX IF NOT EXISTS idx_permission_code ON tb_permission(perm_code) WHERE deleted_at IS NULL; -CREATE INDEX IF NOT EXISTS idx_permission_type ON tb_permission(perm_type); -CREATE INDEX IF NOT EXISTS idx_permission_parent_id ON tb_permission(parent_id); -CREATE INDEX IF NOT EXISTS idx_permission_deleted_at ON tb_permission(deleted_at); - --- tb_permission 表和字段注释 -COMMENT ON TABLE tb_permission IS '权限表:定义系统权限(菜单和按钮),支持层级结构和软删除'; -COMMENT ON COLUMN tb_permission.id IS '主键 ID'; -COMMENT ON COLUMN tb_permission.perm_name IS '权限名称'; -COMMENT ON COLUMN tb_permission.perm_code IS '权限编码(唯一,如 user:create)'; -COMMENT ON COLUMN tb_permission.perm_type IS '权限类型:1=菜单, 2=按钮'; -COMMENT ON COLUMN tb_permission.url IS '权限对应的 URL 路径'; -COMMENT ON COLUMN tb_permission.parent_id IS '上级权限 ID(自关联,用于层级结构)'; -COMMENT ON COLUMN tb_permission.sort IS '排序号(用于菜单排序)'; -COMMENT ON COLUMN tb_permission.status IS '状态:0=禁用, 1=启用'; -COMMENT ON COLUMN tb_permission.creator IS '创建人 ID'; -COMMENT ON COLUMN tb_permission.updater IS '更新人 ID'; -COMMENT ON COLUMN tb_permission.created_at IS '创建时间'; -COMMENT ON COLUMN tb_permission.updated_at IS '更新时间'; -COMMENT ON COLUMN tb_permission.deleted_at IS '软删除时间(NULL 表示未删除)'; - --- ============================================================================= --- T020: tb_account_role (账号-角色关联表) --- ============================================================================= -CREATE TABLE IF NOT EXISTS tb_account_role ( - id BIGSERIAL PRIMARY KEY, - account_id INTEGER NOT NULL, - role_id INTEGER NOT NULL, - status SMALLINT NOT NULL DEFAULT 1, -- 0=禁用, 1=启用 - creator INTEGER NOT NULL, - updater INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP -); - --- T021: tb_account_role 索引 -CREATE INDEX IF NOT EXISTS idx_account_role_account_id ON tb_account_role(account_id); -CREATE INDEX IF NOT EXISTS idx_account_role_role_id ON tb_account_role(role_id); -CREATE INDEX IF NOT EXISTS idx_account_role_deleted_at ON tb_account_role(deleted_at); -CREATE UNIQUE INDEX IF NOT EXISTS idx_account_role_unique ON tb_account_role(account_id, role_id) WHERE deleted_at IS NULL; - --- tb_account_role 表和字段注释 -COMMENT ON TABLE tb_account_role IS '账号-角色关联表:实现账号和角色的多对多关系,支持软删除'; -COMMENT ON COLUMN tb_account_role.id IS '主键 ID'; -COMMENT ON COLUMN tb_account_role.account_id IS '账号 ID'; -COMMENT ON COLUMN tb_account_role.role_id IS '角色 ID'; -COMMENT ON COLUMN tb_account_role.status IS '状态:0=禁用, 1=启用'; -COMMENT ON COLUMN tb_account_role.creator IS '创建人 ID'; -COMMENT ON COLUMN tb_account_role.updater IS '更新人 ID'; -COMMENT ON COLUMN tb_account_role.created_at IS '创建时间'; -COMMENT ON COLUMN tb_account_role.updated_at IS '更新时间'; -COMMENT ON COLUMN tb_account_role.deleted_at IS '软删除时间(NULL 表示未删除)'; - --- ============================================================================= --- T022: tb_role_permission (角色-权限关联表) --- ============================================================================= -CREATE TABLE IF NOT EXISTS tb_role_permission ( - id BIGSERIAL PRIMARY KEY, - role_id INTEGER NOT NULL, - perm_id INTEGER NOT NULL, - status SMALLINT NOT NULL DEFAULT 1, -- 0=禁用, 1=启用 - creator INTEGER NOT NULL, - updater INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP -); - --- T023: tb_role_permission 索引 -CREATE INDEX IF NOT EXISTS idx_role_permission_role_id ON tb_role_permission(role_id); -CREATE INDEX IF NOT EXISTS idx_role_permission_perm_id ON tb_role_permission(perm_id); -CREATE INDEX IF NOT EXISTS idx_role_permission_deleted_at ON tb_role_permission(deleted_at); -CREATE UNIQUE INDEX IF NOT EXISTS idx_role_permission_unique ON tb_role_permission(role_id, perm_id) WHERE deleted_at IS NULL; - --- tb_role_permission 表和字段注释 -COMMENT ON TABLE tb_role_permission IS '角色-权限关联表:实现角色和权限的多对多关系,支持软删除'; -COMMENT ON COLUMN tb_role_permission.id IS '主键 ID'; -COMMENT ON COLUMN tb_role_permission.role_id IS '角色 ID'; -COMMENT ON COLUMN tb_role_permission.perm_id IS '权限 ID'; -COMMENT ON COLUMN tb_role_permission.status IS '状态:0=禁用, 1=启用'; -COMMENT ON COLUMN tb_role_permission.creator IS '创建人 ID'; -COMMENT ON COLUMN tb_role_permission.updater IS '更新人 ID'; -COMMENT ON COLUMN tb_role_permission.created_at IS '创建时间'; -COMMENT ON COLUMN tb_role_permission.updated_at IS '更新时间'; -COMMENT ON COLUMN tb_role_permission.deleted_at IS '软删除时间(NULL 表示未删除)'; diff --git a/migrations/000003_add_owner_id_shop_id.down.sql b/migrations/000003_add_owner_id_shop_id.down.sql deleted file mode 100644 index 01f76c3..0000000 --- a/migrations/000003_add_owner_id_shop_id.down.sql +++ /dev/null @@ -1,19 +0,0 @@ --- 000003_add_owner_id_shop_id.down.sql --- 重要说明:user/order 模块已移除,本模板仅供新的业务表参照。 - --- 示例:回滚 SIM 卡表的数据权限字段 --- DROP INDEX IF EXISTS idx_sim_card_owner_shop; --- DROP INDEX IF EXISTS idx_sim_card_shop_id; --- DROP INDEX IF EXISTS idx_sim_card_owner_id; --- ALTER TABLE tb_sim_card DROP COLUMN IF EXISTS shop_id; --- ALTER TABLE tb_sim_card DROP COLUMN IF EXISTS owner_id; - --- 示例:回滚设备表的数据权限字段 --- DROP INDEX IF EXISTS idx_device_owner_shop; --- DROP INDEX IF EXISTS idx_device_shop_id; --- DROP INDEX IF EXISTS idx_device_owner_id; --- ALTER TABLE tb_device DROP COLUMN IF EXISTS shop_id; --- ALTER TABLE tb_device DROP COLUMN IF EXISTS owner_id; - --- 占位语句(避免空迁移文件报错) -SELECT 1; diff --git a/migrations/000003_add_owner_id_shop_id.up.sql b/migrations/000003_add_owner_id_shop_id.up.sql deleted file mode 100644 index 1eb30b8..0000000 --- a/migrations/000003_add_owner_id_shop_id.up.sql +++ /dev/null @@ -1,35 +0,0 @@ --- 000003_add_owner_id_shop_id.up.sql - --- 重要说明:user/order 模块已移除,本模板仅供新的业务表(例如 SIM、设备、套餐等)参照。 --- 使用方法: --- 1. 复制此模板 --- 2. 替换示例表名为真实表名 --- 3. 按需调整字段类型、索引、默认值 - --- 示例:为 SIM 卡表添加数据权限字段 --- ALTER TABLE tb_sim_card ADD COLUMN owner_id BIGINT; --- ALTER TABLE tb_sim_card ADD COLUMN shop_id BIGINT; --- --- CREATE INDEX idx_sim_card_owner_id ON tb_sim_card(owner_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_sim_card_shop_id ON tb_sim_card(shop_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_sim_card_owner_shop ON tb_sim_card(owner_id, shop_id) WHERE deleted_at IS NULL; - --- 示例:为设备表添加数据权限字段 --- ALTER TABLE tb_device ADD COLUMN owner_id BIGINT; --- ALTER TABLE tb_device ADD COLUMN shop_id BIGINT; --- --- CREATE INDEX idx_device_owner_id ON tb_device(owner_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_device_shop_id ON tb_device(shop_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_device_owner_shop ON tb_device(owner_id, shop_id) WHERE deleted_at IS NULL; - --- 批量表处理建议:可将多个 ALTER 语句放入同一次迁移,以保持版本一致。 - --- 通用数据权限字段规范: --- owner_id: 数据所有者账号 ID,关联 tb_account.id --- shop_id: 数据所属店铺 ID,用于店铺级别的数据隔离 --- --- 过滤条件示例: --- WHERE owner_id IN (当前用户及所有下级 ID) AND shop_id = 当前用户 shop_id - --- 占位语句(避免空迁移文件报错) -SELECT 1; diff --git a/migrations/000004_drop_legacy_user_order.down.sql b/migrations/000004_drop_legacy_user_order.down.sql deleted file mode 100644 index 627471a..0000000 --- a/migrations/000004_drop_legacy_user_order.down.sql +++ /dev/null @@ -1,83 +0,0 @@ --- 000004_drop_legacy_user_order.down.sql --- 说明:回滚时恢复 legacy 用户/订单表(与历史 000001_init_schema 一致)。 - -BEGIN; - --- 恢复用户表 -CREATE TABLE IF NOT EXISTS tb_user ( - id SERIAL PRIMARY KEY, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP, - - -- 基本信息 - username VARCHAR(50) NOT NULL, - email VARCHAR(100) NOT NULL, - password VARCHAR(255) NOT NULL, - - -- 状态字段 - status VARCHAR(20) NOT NULL DEFAULT 'active', - - -- 元数据 - last_login_at TIMESTAMP, - - -- 唯一约束 - CONSTRAINT uk_user_username UNIQUE (username), - CONSTRAINT uk_user_email UNIQUE (email) -); - --- 恢复订单表 -CREATE TABLE IF NOT EXISTS tb_order ( - id SERIAL PRIMARY KEY, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP, - - -- 业务唯一键 - order_id VARCHAR(50) NOT NULL, - - -- 关联关系(注意:无数据库外键约束,在代码中管理) - user_id INTEGER NOT NULL, - - -- 订单信息 - amount BIGINT NOT NULL, - status VARCHAR(20) NOT NULL DEFAULT 'pending', - remark VARCHAR(500), - - -- 时间字段 - paid_at TIMESTAMP, - completed_at TIMESTAMP, - - -- 唯一约束 - CONSTRAINT uk_order_order_id UNIQUE (order_id) -); - --- 索引恢复 -CREATE INDEX IF NOT EXISTS idx_user_deleted_at ON tb_user(deleted_at); -CREATE INDEX IF NOT EXISTS idx_user_status ON tb_user(status); -CREATE INDEX IF NOT EXISTS idx_user_created_at ON tb_user(created_at); - -CREATE INDEX IF NOT EXISTS idx_order_deleted_at ON tb_order(deleted_at); -CREATE INDEX IF NOT EXISTS idx_order_user_id ON tb_order(user_id); -CREATE INDEX IF NOT EXISTS idx_order_status ON tb_order(status); -CREATE INDEX IF NOT EXISTS idx_order_created_at ON tb_order(created_at); - --- 注释恢复 -COMMENT ON TABLE tb_user IS '用户表'; -COMMENT ON COLUMN tb_user.username IS '用户名(唯一)'; -COMMENT ON COLUMN tb_user.email IS '邮箱(唯一)'; -COMMENT ON COLUMN tb_user.password IS '密码(bcrypt 哈希)'; -COMMENT ON COLUMN tb_user.status IS '用户状态:active, inactive, suspended'; -COMMENT ON COLUMN tb_user.deleted_at IS '软删除时间'; - -COMMENT ON TABLE tb_order IS '订单表'; -COMMENT ON COLUMN tb_order.order_id IS '订单号(业务唯一键)'; -COMMENT ON COLUMN tb_order.user_id IS '用户 ID(在代码中维护关联,无数据库外键)'; -COMMENT ON COLUMN tb_order.amount IS '金额(分)'; -COMMENT ON COLUMN tb_order.status IS '订单状态:pending, paid, processing, completed, cancelled'; -COMMENT ON COLUMN tb_order.deleted_at IS '软删除时间'; - -COMMIT; - --- 占位,避免空事务报错 -SELECT 1; diff --git a/migrations/000004_drop_legacy_user_order.up.sql b/migrations/000004_drop_legacy_user_order.up.sql deleted file mode 100644 index 511c713..0000000 --- a/migrations/000004_drop_legacy_user_order.up.sql +++ /dev/null @@ -1,13 +0,0 @@ --- 000004_drop_legacy_user_order.up.sql --- 说明:清理已废弃的 legacy 用户/订单表,保证数据库结构与现有代码一致。 - -BEGIN; - --- 先删除依赖度更高的订单表,再删除用户表 -DROP TABLE IF EXISTS tb_order; -DROP TABLE IF EXISTS tb_user; - -COMMIT; - --- 占位,避免空事务报错 -SELECT 1; diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index a22f043..807ff1f 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -87,6 +87,12 @@ func InitPostgreSQL(cfg *config.DatabaseConfig, log *zap.Logger) (*gorm.DB, erro zap.Int("max_idle_conns", maxIdleConns), zap.Duration("conn_max_lifetime", connMaxLifetime)) + // db.AutoMigrate( + // &model.Account{}, + // &model.Role{}, + // &model.Permission{}, + // &model.RolePermission{}, + // ) return db, nil } diff --git a/pkg/gorm/callback.go b/pkg/gorm/callback.go index 625836c..3134004 100644 --- a/pkg/gorm/callback.go +++ b/pkg/gorm/callback.go @@ -3,6 +3,7 @@ package gorm import ( "context" + "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/logger" "github.com/break/junhong_cmp_fiber/pkg/middleware" "go.uber.org/zap" @@ -42,8 +43,8 @@ type AccountStoreInterface interface { // 4. 通过 SkipDataPermission(ctx) 可以绕过权限过滤 // // 注意: -// - Callback 只对包含 creator 字段的表生效 -// - 必须在初始化 Store 之前注册 +// - Callback 只对包含 creator 字段的表生效 +// - 必须在初始化 Store 之前注册 // // 参数: // - db: GORM DB 实例 @@ -110,7 +111,24 @@ func RegisterDataPermissionCallback(db *gorm.DB, accountStore AccountStoreInterf tx.Where("creator IN ?", subordinateIDs) } }) + return err +} +// RegisterSetCreatorUpdaterCallback 注册 GORM 创建数据时创建人更新人 Callback +func RegisterSetCreatorUpdaterCallback(db *gorm.DB) error { + err := db.Callback().Create().Before("gorm:create").Register("set_creator_updater", func(tx *gorm.DB) { + ctx := tx.Statement.Context + if userID, ok := tx.Statement.Context.Value(constants.ContextKeyUserID).(uint); ok { + if f := tx.Statement.Schema; f != nil { + if c, ok := f.FieldsByName["Creator"]; ok { + _ = c.Set(ctx, tx.Statement.ReflectValue, userID) + } + if u, ok := f.FieldsByName["Updater"]; ok { + _ = u.Set(ctx, tx.Statement.ReflectValue, userID) + } + } + } + }) return err }