This commit is contained in:
张成
2026-04-01 09:59:54 +08:00
parent aac2d4a8d5
commit 14f5d75d9d
11 changed files with 98 additions and 43 deletions

View File

@@ -1,8 +1,14 @@
-- biz_plans 新增:可访问接口列表 + 每月API调用次数上限 -- 在「与后端 app 相同」的 MySQL 库中执行(否则会一直报 Unknown column
ALTER TABLE `biz_plans` -- 可重复执行:若列已存在会报错,可忽略对应语句或改用 scripts/migrate_biz_plan_api_columns.js
ADD COLUMN `allowed_apis` JSON DEFAULT NULL COMMENT '可访问的接口路径列表null=不限制' AFTER `enabled_features`,
ADD COLUMN `api_call_quota` INT NOT NULL DEFAULT 0 COMMENT '每月API总调用次数上限0=不限制' AFTER `allowed_apis`;
-- biz_usage_monthly 新增当月API调用总次数 SET NAMES utf8mb4;
-- biz_plans分两条方便只缺其中一列时单独执行
ALTER TABLE `biz_plans`
ADD COLUMN `allowed_apis` JSON DEFAULT NULL COMMENT '可访问的接口路径列表null=不限制';
ALTER TABLE `biz_plans`
ADD COLUMN `api_call_quota` INT NOT NULL DEFAULT 0 COMMENT '每月API总调用次数上限0=不限制';
-- biz_usage_monthly
ALTER TABLE `biz_usage_monthly` ALTER TABLE `biz_usage_monthly`
ADD COLUMN `api_call_count` INT NOT NULL DEFAULT 0 COMMENT '当月API转发总调用次数' AFTER `active_user_count`; ADD COLUMN `api_call_count` INT NOT NULL DEFAULT 0 COMMENT '当月API转发总调用次数';

View File

@@ -79,6 +79,7 @@
<FormItem label="friend_count"><Input v-model="form.friend_count" type="number" /></FormItem> <FormItem label="friend_count"><Input v-model="form.friend_count" type="number" /></FormItem>
<FormItem label="sns_count"><Input v-model="form.sns_count" type="number" /></FormItem> <FormItem label="sns_count"><Input v-model="form.sns_count" type="number" /></FormItem>
<FormItem label="active_user_count"><Input v-model="form.active_user_count" type="number" /></FormItem> <FormItem label="active_user_count"><Input v-model="form.active_user_count" type="number" /></FormItem>
<FormItem label="api_call_count转发调用"><Input v-model="form.api_call_count" type="number" /></FormItem>
</Form> </Form>
</Modal> </Modal>
</div> </div>
@@ -122,6 +123,7 @@ export default {
{ title: 'friend', key: 'friend_count', minWidth: 72 }, { title: 'friend', key: 'friend_count', minWidth: 72 },
{ title: 'sns', key: 'sns_count', minWidth: 72 }, { title: 'sns', key: 'sns_count', minWidth: 72 },
{ title: 'active_user', key: 'active_user_count', minWidth: 100 }, { title: 'active_user', key: 'active_user_count', minWidth: 100 },
{ title: 'api_calls', key: 'api_call_count', minWidth: 88 },
{ {
title: '操作', title: '操作',
key: 'a', key: 'a',
@@ -178,6 +180,7 @@ export default {
friend_count: 0, friend_count: 0,
sns_count: 0, sns_count: 0,
active_user_count: 0, active_user_count: 0,
api_call_count: 0,
} }
} }
this.modal = true this.modal = true

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_api_call_log = db.define( const biz_api_call_log = db.define(
"biz_api_call_log", "biz_api_call_log",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
user_id: { user_id: {
type: Sequelize.BIGINT.UNSIGNED, type: Sequelize.BIGINT.UNSIGNED,
allowNull: false, allowNull: false,

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_api_token = db.define( const biz_api_token = db.define(
"biz_api_token", "biz_api_token",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
user_id: { user_id: {
type: Sequelize.BIGINT.UNSIGNED, type: Sequelize.BIGINT.UNSIGNED,
allowNull: false, allowNull: false,

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_audit_log = db.define( const biz_audit_log = db.define(
"biz_audit_log", "biz_audit_log",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
admin_user_id: { admin_user_id: {
type: Sequelize.BIGINT.UNSIGNED, type: Sequelize.BIGINT.UNSIGNED,
allowNull: true, allowNull: true,

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_plan = db.define( const biz_plan = db.define(
"biz_plan", "biz_plan",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
plan_code: { plan_code: {
type: Sequelize.STRING(64), type: Sequelize.STRING(64),
allowNull: false, allowNull: false,
@@ -64,6 +60,6 @@ module.exports = (db) => {
comment: "套餐", comment: "套餐",
} }
); );
// biz_plan.sync({ alter: true }); // biz_plan.sync({ alter: true });
return biz_plan; return biz_plan;
}; };

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_subscription = db.define( const biz_subscription = db.define(
"biz_subscription", "biz_subscription",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
user_id: { user_id: {
type: Sequelize.BIGINT.UNSIGNED, type: Sequelize.BIGINT.UNSIGNED,
allowNull: false, allowNull: false,

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_usage_monthly = db.define( const biz_usage_monthly = db.define(
"biz_usage_monthly", "biz_usage_monthly",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
user_id: { user_id: {
type: Sequelize.BIGINT.UNSIGNED, type: Sequelize.BIGINT.UNSIGNED,
allowNull: false, allowNull: false,

View File

@@ -4,11 +4,7 @@ module.exports = (db) => {
const biz_user = db.define( const biz_user = db.define(
"biz_user", "biz_user",
{ {
id: {
type: Sequelize.BIGINT.UNSIGNED,
primaryKey: true,
autoIncrement: true,
},
name: { name: {
type: Sequelize.STRING(100), type: Sequelize.STRING(100),
allowNull: false, allowNull: false,

View File

@@ -68,7 +68,8 @@
"load": "node __tests__/loadtest-both.js", "load": "node __tests__/loadtest-both.js",
"api": " nodemon ./app.js ", "api": " nodemon ./app.js ",
"serve": "cd ./admin&&npm run dev -- --port 9001 ", "serve": "cd ./admin&&npm run dev -- --port 9001 ",
"build": "cd ./admin&&npm run build " "build": "cd ./admin&&npm run build ",
"migrate:plan_api": "node scripts/migrate_biz_plan_api_columns.js"
}, },
"license": "MIT" "license": "MIT"
} }

View File

@@ -0,0 +1,73 @@
/**
* 为 biz_plans / biz_usage_monthly 补齐套餐 API 权限相关字段(可重复执行)
*/
const mysql = require("mysql2/promise");
const config = require("../config/config");
async function column_exists(conn, schema, table, column) {
const [rows] = await conn.query(
`SELECT COUNT(*) AS c FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?`,
[schema, table, column]
);
return Number(rows[0].c) > 0;
}
async function table_exists(conn, schema, table) {
const [rows] = await conn.query(
`SELECT COUNT(*) AS c FROM information_schema.TABLES
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?`,
[schema, table]
);
return Number(rows[0].c) > 0;
}
async function main() {
const db = config.db;
if (!db || !db.database) {
throw new Error("config.db.database 未配置");
}
const conn = await mysql.createConnection({
host: db.host,
port: db.port || 3306,
user: db.username,
password: db.password,
database: db.database,
});
const schema = db.database;
try {
if (!(await table_exists(conn, schema, "biz_plans"))) {
console.warn("跳过 biz_plans当前库中不存在该表请确认连接的是已部署订阅模块的库");
} else if (!(await column_exists(conn, schema, "biz_plans", "allowed_apis"))) {
await conn.query(
"ALTER TABLE `biz_plans` ADD COLUMN `allowed_apis` JSON DEFAULT NULL COMMENT '可访问的接口路径列表null=不限制'"
);
console.log("已添加 biz_plans.allowed_apis");
}
if (
(await table_exists(conn, schema, "biz_plans")) &&
!(await column_exists(conn, schema, "biz_plans", "api_call_quota"))
) {
await conn.query(
"ALTER TABLE `biz_plans` ADD COLUMN `api_call_quota` INT NOT NULL DEFAULT 0 COMMENT '每月API总调用次数上限0=不限制'"
);
console.log("已添加 biz_plans.api_call_quota");
}
if (!(await table_exists(conn, schema, "biz_usage_monthly"))) {
console.warn("跳过 biz_usage_monthly当前库中不存在该表");
} else if (!(await column_exists(conn, schema, "biz_usage_monthly", "api_call_count"))) {
await conn.query(
"ALTER TABLE `biz_usage_monthly` ADD COLUMN `api_call_count` INT NOT NULL DEFAULT 0 COMMENT '当月API转发总调用次数'"
);
console.log("已添加 biz_usage_monthly.api_call_count");
}
console.log("字段检查完成");
} finally {
await conn.end();
}
}
main().catch((e) => {
console.error(e);
process.exit(1);
});