diff --git a/AGENTS.md b/AGENTS.md index c8e79d4..0c01b0d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,7 @@ Keep this managed block so 'openspec update' can refresh the instructions. - 日志消息必须使用中文 - 用户可见的错误消息必须使用中文 - 变量名、函数名、类型名必须使用英文(遵循 Go 命名规范) +- GIT提交的commit必须使用中文 ## 技术栈 diff --git a/migrations/000003_add_owner_id_shop_id.down.sql b/migrations/000003_add_owner_id_shop_id.down.sql index e53d114..01f76c3 100644 --- a/migrations/000003_add_owner_id_shop_id.down.sql +++ b/migrations/000003_add_owner_id_shop_id.down.sql @@ -1,20 +1,19 @@ -- 000003_add_owner_id_shop_id.down.sql --- 示例迁移:回滚 owner_id 和 shop_id 字段 --- 注:此为模板迁移,实际业务表由项目需求决定 +-- 重要说明:user/order 模块已移除,本模板仅供新的业务表参照。 --- 示例:回滚订单表的数据权限字段 --- DROP INDEX IF EXISTS idx_orders_owner_shop; --- DROP INDEX IF EXISTS idx_orders_shop_id; --- DROP INDEX IF EXISTS idx_orders_owner_id; --- ALTER TABLE tb_orders DROP COLUMN IF EXISTS shop_id; --- ALTER TABLE tb_orders DROP COLUMN IF EXISTS owner_id; +-- 示例:回滚 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_products_owner_shop; --- DROP INDEX IF EXISTS idx_products_shop_id; --- DROP INDEX IF EXISTS idx_products_owner_id; --- ALTER TABLE tb_products DROP COLUMN IF EXISTS shop_id; --- ALTER TABLE tb_products 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 index a0584c0..1eb30b8 100644 --- a/migrations/000003_add_owner_id_shop_id.up.sql +++ b/migrations/000003_add_owner_id_shop_id.up.sql @@ -1,27 +1,28 @@ -- 000003_add_owner_id_shop_id.up.sql --- 示例迁移:为业务表添加 owner_id 和 shop_id 字段 --- 注:此为模板迁移,实际业务表由项目需求决定 + +-- 重要说明:user/order 模块已移除,本模板仅供新的业务表(例如 SIM、设备、套餐等)参照。 -- 使用方法: -- 1. 复制此模板 --- 2. 修改表名为实际业务表 --- 3. 根据业务需求调整字段类型和约束 +-- 2. 替换示例表名为真实表名 +-- 3. 按需调整字段类型、索引、默认值 --- 示例:为订单表添加数据权限字段 --- ALTER TABLE tb_orders ADD COLUMN owner_id BIGINT; --- ALTER TABLE tb_orders ADD COLUMN shop_id BIGINT; +-- 示例:为 SIM 卡表添加数据权限字段 +-- ALTER TABLE tb_sim_card ADD COLUMN owner_id BIGINT; +-- ALTER TABLE tb_sim_card ADD COLUMN shop_id BIGINT; -- --- -- 创建索引以支持数据权限过滤 --- CREATE INDEX idx_orders_owner_id ON tb_orders(owner_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_orders_shop_id ON tb_orders(shop_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_orders_owner_shop ON tb_orders(owner_id, shop_id) WHERE deleted_at IS NULL; +-- 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_products ADD COLUMN owner_id BIGINT; --- ALTER TABLE tb_products ADD COLUMN shop_id BIGINT; +-- 示例:为设备表添加数据权限字段 +-- ALTER TABLE tb_device ADD COLUMN owner_id BIGINT; +-- ALTER TABLE tb_device ADD COLUMN shop_id BIGINT; -- --- CREATE INDEX idx_products_owner_id ON tb_products(owner_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_products_shop_id ON tb_products(shop_id) WHERE deleted_at IS NULL; --- CREATE INDEX idx_products_owner_shop ON tb_products(owner_id, shop_id) WHERE deleted_at IS NULL; +-- 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 diff --git a/migrations/000004_drop_legacy_user_order.down.sql b/migrations/000004_drop_legacy_user_order.down.sql new file mode 100644 index 0000000..627471a --- /dev/null +++ b/migrations/000004_drop_legacy_user_order.down.sql @@ -0,0 +1,83 @@ +-- 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 new file mode 100644 index 0000000..511c713 --- /dev/null +++ b/migrations/000004_drop_legacy_user_order.up.sql @@ -0,0 +1,13 @@ +-- 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/scripts/migrate.sh b/scripts/migrate.sh index 1dedf0c..27f6307 100755 --- a/scripts/migrate.sh +++ b/scripts/migrate.sh @@ -38,11 +38,12 @@ show_usage() { 用法: $0 [命令] [参数] 命令: - up [N] 向上迁移 N 步 (默认: 全部) + up [N] 向上迁移 N 步 (默认: 全部,完成后自动检查 legacy 表) down [N] 向下回滚 N 步 (默认: 1) create NAME 创建新的迁移文件 version 显示当前迁移版本 force V 强制设置迁移版本为 V (用于修复脏数据库状态) + check-legacy 检查 legacy 表 (tb_user/tb_order) 是否仍存在 help 显示此帮助信息 环境变量: @@ -59,10 +60,36 @@ show_usage() { $0 create add_sim_table # 创建新迁移文件 $0 version # 查看当前版本 $0 force 1 # 强制设置版本为 1 + $0 check-legacy # 单独检查 tb_user/tb_order 是否存在 EOF } +check_legacy_tables() { + if ! command -v psql &> /dev/null; then + echo "提示: 未检测到 psql 命令,跳过 legacy 表检查" + return + fi + + echo "正在检查 legacy 表 tb_user / tb_order..." + if ! CHECK_RESULT=$(psql "$DATABASE_URL" -Atqc "SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_name IN ('tb_user','tb_order');"); then + echo "警告: 无法执行 legacy 表检查,请手动确认" + return + fi + + if [ -z "$CHECK_RESULT" ]; then + echo "✓ 未发现 legacy 表,数据库结构已与代码同步" + else + echo "⚠ 检测到以下 legacy 表仍然存在:" + echo "$CHECK_RESULT" | while read -r table_name; do + if [ -n "$table_name" ]; then + printf ' - %s\n' "$table_name" + fi + done + echo "请确保已经执行 000004_drop_legacy_user_order 迁移或手动清理上述表" + fi +} + # 主命令处理 case "$1" in up) @@ -73,6 +100,8 @@ case "$1" in echo "正在向上迁移 $2 步..." migrate -path "$MIGRATIONS_DIR" -database "$DATABASE_URL" up "$2" fi + echo "迁移完成,开始检查 legacy 表..." + check_legacy_tables ;; down) STEPS="${2:-1}" @@ -103,6 +132,9 @@ case "$1" in echo "强制设置迁移版本为: $2" migrate -path "$MIGRATIONS_DIR" -database "$DATABASE_URL" force "$2" ;; + check-legacy) + check_legacy_tables + ;; help|--help|-h) show_usage ;;