From 30a909762e72600f06671f6f76a127687be6ff81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Wed, 1 Apr 2026 10:58:28 +0800 Subject: [PATCH] 1 --- _docs/sql/001_biz_schema.sql | 13 ++- _docs/sql/002_subscription_menu_seed.sql | 3 +- _docs/sql/003_biz_audit.sql | 1 + _docs/sql/003_home_menu_seed.sql | 3 +- .../sql/004_migrate_biz_users_to_biz_user.sql | 1 + .../sql/005_biz_timestamp_defaults_alter.sql | 1 + _docs/sql/alter_plan_api_permission.sql | 1 + _docs/sql/biz_api_call_log.sql | 3 + _docs/sql/seed_biz_plans.sql | 96 +++++++++++++++++++ _docs/订阅模块实施计划.md | 4 +- api/model/biz_api_call_log.js | 7 +- api/model/biz_api_token.js | 6 ++ api/model/biz_usage_monthly.js | 2 + 13 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 _docs/sql/seed_biz_plans.sql diff --git a/_docs/sql/001_biz_schema.sql b/_docs/sql/001_biz_schema.sql index 4bf65b0..8856911 100644 --- a/_docs/sql/001_biz_schema.sql +++ b/_docs/sql/001_biz_schema.sql @@ -1,6 +1,15 @@ -- WechatAdminWeb 订阅模块业务表(MySQL 8+) --- 业务用户物理表名:biz_user(与 Sequelize 模型 biz_user、freezeTableName 一致) --- 执行前请确认库名;与 api/model/biz_*.js 字段一致 +-- 执行前请确认库名;字段与 api/model/biz_*.js 中 tableName 完全一致: +-- +-- Sequelize 模型名 物理表名(本文件与其它 _docs/sql) +-- ---------------- ---------------- +-- biz_user biz_user +-- biz_plan biz_plans +-- biz_subscription biz_subscriptions +-- biz_api_token biz_api_token +-- biz_usage_monthly biz_usage_monthly +-- +-- 另见:biz_audit_log(003_biz_audit.sql)、biz_api_call_log(biz_api_call_log.sql) SET NAMES utf8mb4; diff --git a/_docs/sql/002_subscription_menu_seed.sql b/_docs/sql/002_subscription_menu_seed.sql index 8a87651..19aafe9 100644 --- a/_docs/sql/002_subscription_menu_seed.sql +++ b/_docs/sql/002_subscription_menu_seed.sql @@ -1,5 +1,6 @@ -- ============================================================================= --- sys_menu 订阅模块菜单插入脚本(字段与 api/model/sys_menu.js 一致) +-- 表 sys_menu(与 api/model/sys_menu.js 模型同名;执行前以 information_schema 确认实际表名) +-- 订阅模块菜单插入脚本(字段与模型一致) -- path:不含斜杠(与首页 path=home 等约定一致);component 仍为 subscription/xxx 供前端映射 -- 执行前请备份。若已存在同名「订阅管理」父菜单,请先删除子菜单再删父级,或改下面名称。 -- 若数据库表另有 created_at / updated_at 等列,请在 INSERT 中补全或给默认值。 diff --git a/_docs/sql/003_biz_audit.sql b/_docs/sql/003_biz_audit.sql index bb64260..0fdd123 100644 --- a/_docs/sql/003_biz_audit.sql +++ b/_docs/sql/003_biz_audit.sql @@ -1,4 +1,5 @@ -- 审计日志(关键操作留痕) +-- 模型:api/model/biz_audit_log.js → tableName: biz_audit_log SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS `biz_audit_log` ( diff --git a/_docs/sql/003_home_menu_seed.sql b/_docs/sql/003_home_menu_seed.sql index cfe923d..f1e7a36 100644 --- a/_docs/sql/003_home_menu_seed.sql +++ b/_docs/sql/003_home_menu_seed.sql @@ -1,5 +1,6 @@ -- ============================================================================= --- sys_menu 首页(字段与 api/model/sys_menu.js、现有库中菜单数据格式一致) +-- 表 sys_menu(与 api/model/sys_menu.js 模型同名;执行前以 information_schema 确认实际表名) +-- 首页菜单(字段与模型、现有库中菜单数据格式一致) -- -- 参考库中同类数据示例: -- path:首页为 home(无前导 /);订阅子页为 /subscription/xxx diff --git a/_docs/sql/004_migrate_biz_users_to_biz_user.sql b/_docs/sql/004_migrate_biz_users_to_biz_user.sql index 864b5ac..fac1ad7 100644 --- a/_docs/sql/004_migrate_biz_users_to_biz_user.sql +++ b/_docs/sql/004_migrate_biz_users_to_biz_user.sql @@ -1,4 +1,5 @@ -- ============================================================================= +-- 目标物理表名:biz_user(与模型 api/model/biz_user.js 的 tableName 一致;旧名 biz_users 仅为历史迁移说明)。 -- 若早期已按旧版 001 建表 biz_users,而运行时报错查 biz_user,可执行本脚本迁移表名。 -- 执行前备份数据库。若子表尚未创建,可跳过本脚本,直接 DROP biz_users 后重跑新版 001_biz_schema.sql。 -- ============================================================================= diff --git a/_docs/sql/005_biz_timestamp_defaults_alter.sql b/_docs/sql/005_biz_timestamp_defaults_alter.sql index b38bd8e..b4e6a2f 100644 --- a/_docs/sql/005_biz_timestamp_defaults_alter.sql +++ b/_docs/sql/005_biz_timestamp_defaults_alter.sql @@ -1,3 +1,4 @@ +-- 表名与 api/model 中 tableName 一致:biz_user、biz_plans、biz_subscriptions、biz_api_token、biz_usage_monthly、biz_audit_log -- 已有库若 `created_at` / `updated_at` 无默认值,插入会失败(模型已关闭 Sequelize timestamps 且未声明时间字段时依赖库默认值)。 -- 按需对已有表执行(新库直接执行 001/003 即可,无需本文件)。 diff --git a/_docs/sql/alter_plan_api_permission.sql b/_docs/sql/alter_plan_api_permission.sql index cb992a0..e1a4f94 100644 --- a/_docs/sql/alter_plan_api_permission.sql +++ b/_docs/sql/alter_plan_api_permission.sql @@ -1,3 +1,4 @@ +-- 模型 biz_plan → 表 biz_plans;模型 biz_usage_monthly → 表 biz_usage_monthly(与 api/model 中 tableName 一致) -- 在「与后端 app 相同」的 MySQL 库中执行(否则会一直报 Unknown column)。 -- 可重复执行:若列已存在会报错,可忽略对应语句或改用 scripts/migrate_biz_plan_api_columns.js diff --git a/_docs/sql/biz_api_call_log.sql b/_docs/sql/biz_api_call_log.sql index 83bb808..91a3989 100644 --- a/_docs/sql/biz_api_call_log.sql +++ b/_docs/sql/biz_api_call_log.sql @@ -1,3 +1,6 @@ +-- 模型:api/model/biz_api_call_log.js → tableName: biz_api_call_log +SET NAMES utf8mb4; + CREATE TABLE IF NOT EXISTS `biz_api_call_log` ( `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `user_id` BIGINT UNSIGNED NOT NULL COMMENT '业务用户ID', diff --git a/_docs/sql/seed_biz_plans.sql b/_docs/sql/seed_biz_plans.sql new file mode 100644 index 0000000..67a7d01 --- /dev/null +++ b/_docs/sql/seed_biz_plans.sql @@ -0,0 +1,96 @@ +-- 套餐示例数据(表 biz_plans,模型 biz_plan / api/model/biz_plan.js) +-- 执行库须与项目 NODE_ENV 对应库一致;若表无 allowed_apis / api_call_quota 请先执行 alter_plan_api_permission.sql +-- plan_code 唯一:重复执行会主键/唯一冲突,可先 DELETE WHERE plan_code IN (...) 或改用下面「按编码更新」段落 + +SET NAMES utf8mb4; + +-- ========== 1)插入三条示例套餐 ========== +INSERT INTO `biz_plans` ( + `plan_code`, + `plan_name`, + `monthly_price`, + `auth_fee`, + `account_limit`, + `active_user_limit`, + `msg_quota`, + `mass_quota`, + `friend_quota`, + `sns_quota`, + `enabled_features`, + `allowed_apis`, + `api_call_quota`, + `status` +) VALUES +( + 'plan_junior', + '初级版', + 299.00, + 0.00, + 3, + 50, + 3000, + 100, + 200, + 100, + JSON_ARRAY('登录', '好友', '消息', '管理'), + JSON_ARRAY('/login/GetLoginStatus', '/login/DeviceLogin', '/message/SendText', '/friend/GetContactList'), + 50000, + 'active' +), +( + 'plan_senior', + '高级版', + 899.00, + 0.00, + 20, + 500, + 50000, + 2000, + 5000, + 2000, + JSON_ARRAY( + '登录', '好友', '消息', '群聊', '朋友圈', '小程序', '管理', + '设备', '收藏', '视频号', '标签', '支付', '企业微信', '商店', '其他', 'Ws' + ), + NULL, + 500000, + 'active' +), +( + 'plan_custom', + '定制版', + 0.00, + 0.00, + 9999, + 9999, + 0, + 0, + 0, + 0, + NULL, + NULL, + 0, + 'active' +); + +-- ========== 2)仅当列已存在时:按 plan_code 幂等覆盖(无则 INSERT 需自行补全列)========== +-- 若你已手工删过上面 INSERT,可用下面语句改已有编码的数据: + +-- UPDATE `biz_plans` SET +-- `plan_name` = '初级版', +-- `monthly_price` = 299.00, +-- `msg_quota` = 3000, +-- `api_call_quota` = 50000, +-- `allowed_apis` = JSON_ARRAY('/login/GetLoginStatus', '/message/SendText'), +-- `status` = 'active' +-- WHERE `plan_code` = 'plan_junior'; + +-- ========== 3)常用维护语句 ========== +-- 下架套餐 +-- UPDATE `biz_plans` SET `status` = 'inactive' WHERE `plan_code` = 'plan_junior'; + +-- 某套餐改为「全接口 + 不限次数」(接口层 allowed_apis=null、api_call_quota=0 表示不限制) +-- UPDATE `biz_plans` SET `allowed_apis` = NULL, `api_call_quota` = 0 WHERE `plan_code` = 'plan_senior'; + +-- 清空测试套餐(谨慎:有外键订阅时可能拦截) +-- DELETE FROM `biz_plans` WHERE `plan_code` IN ('plan_junior', 'plan_senior', 'plan_custom'); diff --git a/_docs/订阅模块实施计划.md b/_docs/订阅模块实施计划.md index c036199..d9f315b 100644 --- a/_docs/订阅模块实施计划.md +++ b/_docs/订阅模块实施计划.md @@ -77,7 +77,7 @@ 新建迁移或 SQL 脚本(建议 `_docs/sql/` 或 `migrations/`,与团队习惯一致)包含: -- `biz_users`(或 `users`,注意与 `sys_user` 后台账号区分 — **建议业务客户表用前缀 `biz_`**,避免与系统用户混淆) +- `biz_user`(与模型 `api/model/biz_user.js` 的 `tableName` 一致;与 `sys_user` 后台账号区分) - `biz_plans` - `biz_subscriptions`(字段含 `renew_mode`、`payment_channel`、`payment_ref` 等) - `biz_api_token`(`token_hash`、`plan_id` 可选冗余) @@ -100,7 +100,7 @@ | 需求路径 | 实现前缀 | |----------|----------| -| `POST /admin/users` | `POST /admin_api/users` 或 `/admin_api/biz_users` | +| `POST /admin/users` | `POST /admin_api/biz_user/page` 等(以实际 controller 为准) | | `GET /admin/users` | `GET /admin_api/users` | | `GET /admin/users/{id}` | `GET /admin_api/users/:id` | | `PUT /admin/users/{id}` | `PUT /admin_api/users/:id` | diff --git a/api/model/biz_api_call_log.js b/api/model/biz_api_call_log.js index d85b886..e161e7a 100644 --- a/api/model/biz_api_call_log.js +++ b/api/model/biz_api_call_log.js @@ -42,7 +42,12 @@ module.exports = (db) => { defaultValue: Sequelize.NOW, }, }, - + { + tableName: "biz_api_call_log", + freezeTableName: true, + timestamps: false, + underscored: true, + } ); return biz_api_call_log; }; diff --git a/api/model/biz_api_token.js b/api/model/biz_api_token.js index 1918b58..1b08b6a 100644 --- a/api/model/biz_api_token.js +++ b/api/model/biz_api_token.js @@ -31,6 +31,12 @@ module.exports = (db) => { expire_at: { type: Sequelize.DATE, allowNull: false }, last_used_at: { type: Sequelize.DATE, allowNull: true }, }, + { + tableName: "biz_api_token", + freezeTableName: true, + timestamps: false, + underscored: true, + } ); // biz_api_token.sync({ force: true }); return biz_api_token; diff --git a/api/model/biz_usage_monthly.js b/api/model/biz_usage_monthly.js index 4880c9e..520150d 100644 --- a/api/model/biz_usage_monthly.js +++ b/api/model/biz_usage_monthly.js @@ -29,6 +29,8 @@ module.exports = (db) => { }, }, { + tableName: "biz_usage_monthly", + freezeTableName: true, timestamps: false, underscored: true, }