This commit is contained in:
张成
2026-03-26 09:40:55 +08:00
parent 7d0a921805
commit 60258c6c7d
11 changed files with 58 additions and 20 deletions

View File

@@ -12,8 +12,8 @@ CREATE TABLE IF NOT EXISTS `biz_user` (
`email` VARCHAR(120) NULL DEFAULT NULL, `email` VARCHAR(120) NULL DEFAULT NULL,
`company_name` VARCHAR(200) NULL DEFAULT NULL, `company_name` VARCHAR(200) NULL DEFAULT NULL,
`status` ENUM('active', 'disabled') NOT NULL DEFAULT 'active', `status` ENUM('active', 'disabled') NOT NULL DEFAULT 'active',
`created_at` DATETIME NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `idx_biz_user_mobile` (`mobile`), KEY `idx_biz_user_mobile` (`mobile`),
KEY `idx_biz_user_status` (`status`) KEY `idx_biz_user_status` (`status`)
@@ -34,8 +34,8 @@ CREATE TABLE IF NOT EXISTS `biz_plans` (
`sns_quota` INT NOT NULL DEFAULT 0, `sns_quota` INT NOT NULL DEFAULT 0,
`enabled_features` JSON NULL, `enabled_features` JSON NULL,
`status` ENUM('active', 'inactive') NOT NULL DEFAULT 'active', `status` ENUM('active', 'inactive') NOT NULL DEFAULT 'active',
`created_at` DATETIME NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uk_biz_plans_code` (`plan_code`) UNIQUE KEY `uk_biz_plans_code` (`plan_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='套餐'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='套餐';
@@ -71,8 +71,8 @@ CREATE TABLE IF NOT EXISTS `biz_api_tokens` (
`status` ENUM('active', 'revoked', 'expired') NOT NULL DEFAULT 'active', `status` ENUM('active', 'revoked', 'expired') NOT NULL DEFAULT 'active',
`expire_at` DATETIME NOT NULL, `expire_at` DATETIME NOT NULL,
`last_used_at` DATETIME NULL DEFAULT NULL, `last_used_at` DATETIME NULL DEFAULT NULL,
`created_at` DATETIME NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uk_biz_token_hash` (`token_hash`), UNIQUE KEY `uk_biz_token_hash` (`token_hash`),
KEY `idx_biz_token_user` (`user_id`), KEY `idx_biz_token_user` (`user_id`),
@@ -92,8 +92,8 @@ CREATE TABLE IF NOT EXISTS `biz_usage_monthly` (
`friend_count` INT NOT NULL DEFAULT 0, `friend_count` INT NOT NULL DEFAULT 0,
`sns_count` INT NOT NULL DEFAULT 0, `sns_count` INT NOT NULL DEFAULT 0,
`active_user_count` INT NOT NULL DEFAULT 0, `active_user_count` INT NOT NULL DEFAULT 0,
`created_at` DATETIME NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uk_biz_usage_user_month` (`user_id`, `stat_month`), UNIQUE KEY `uk_biz_usage_user_month` (`user_id`, `stat_month`),
KEY `idx_biz_usage_plan` (`plan_id`), KEY `idx_biz_usage_plan` (`plan_id`),

View File

@@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS `biz_audit_log` (
`resource_type` VARCHAR(64) NOT NULL DEFAULT '', `resource_type` VARCHAR(64) NOT NULL DEFAULT '',
`resource_id` BIGINT UNSIGNED NULL DEFAULT NULL, `resource_id` BIGINT UNSIGNED NULL DEFAULT NULL,
`detail` JSON NULL, `detail` JSON NULL,
`created_at` DATETIME NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `idx_biz_audit_action` (`action`), KEY `idx_biz_audit_action` (`action`),
KEY `idx_biz_audit_created` (`created_at`) KEY `idx_biz_audit_created` (`created_at`)

View File

@@ -0,0 +1,27 @@
-- 已有库若 `created_at` / `updated_at` 无默认值,插入会失败(模型已关闭 Sequelize timestamps 且未声明时间字段时依赖库默认值)。
-- 按需对已有表执行(新库直接执行 001/003 即可,无需本文件)。
SET NAMES utf8mb4;
ALTER TABLE `biz_user`
MODIFY `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFY `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE `biz_plans`
MODIFY `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFY `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE `biz_subscriptions`
MODIFY `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFY `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE `biz_api_tokens`
MODIFY `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFY `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE `biz_usage_monthly`
MODIFY `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFY `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE `biz_audit_log`
MODIFY `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

View File

@@ -38,7 +38,7 @@ module.exports = (db) => {
}, },
{ {
tableName: "biz_api_tokens", tableName: "biz_api_tokens",
timestamps: true, timestamps: false,
underscored: true, underscored: true,
comment: "API Token", comment: "API Token",
} }

View File

@@ -34,10 +34,6 @@ module.exports = (db) => {
type: Sequelize.JSON, type: Sequelize.JSON,
allowNull: true, allowNull: true,
}, },
created_at: {
type: Sequelize.DATE,
allowNull: false,
},
}, },
{ {
tableName: "biz_audit_log", tableName: "biz_audit_log",

View File

@@ -48,7 +48,7 @@ module.exports = (db) => {
}, },
{ {
tableName: "biz_plans", tableName: "biz_plans",
timestamps: true, timestamps: false,
underscored: true, underscored: true,
comment: "套餐", comment: "套餐",
} }

View File

@@ -40,7 +40,7 @@ module.exports = (db) => {
}, },
{ {
tableName: "biz_subscriptions", tableName: "biz_subscriptions",
timestamps: true, timestamps: false,
underscored: true, underscored: true,
comment: "订阅", comment: "订阅",
} }

View File

@@ -30,7 +30,7 @@ module.exports = (db) => {
}, },
{ {
tableName: "biz_usage_monthly", tableName: "biz_usage_monthly",
timestamps: true, timestamps: false,
underscored: true, underscored: true,
comment: "月用量", comment: "月用量",
} }

View File

@@ -39,7 +39,7 @@ module.exports = (db) => {
// 与库表名一致:单数 biz_user与模型名一致避免部分环境下 tableName 未生效时落到默认表名 biz_user // 与库表名一致:单数 biz_user与模型名一致避免部分环境下 tableName 未生效时落到默认表名 biz_user
tableName: "biz_user", tableName: "biz_user",
freezeTableName: true, freezeTableName: true,
timestamps: true, timestamps: false,
underscored: true, underscored: true,
comment: "业务用户", comment: "业务用户",
} }

View File

@@ -94,6 +94,19 @@ function buildSearchWhere(model, seachOption) {
return { [key]: { [op.like]: `%${str}%` } }; return { [key]: { [op.like]: `%${str}%` } };
} }
/** 模型未声明但表中存在的列(列表/导出需要带出) */
function extraListAttributes(modelName, model) {
if (modelName === "biz_audit_log") {
const tn = model.tableName;
return {
attributes: {
include: [[model.sequelize.col(`${tn}.created_at`), "created_at"]],
},
};
}
return {};
}
async function page(modelName, body) { async function page(modelName, body) {
const model = getModel(modelName); const model = getModel(modelName);
const param = body.param || body; const param = body.param || body;
@@ -111,6 +124,7 @@ async function page(modelName, body) {
offset, offset,
limit: pageSize, limit: pageSize,
order: [["id", "DESC"]], order: [["id", "DESC"]],
...extraListAttributes(modelName, model),
}); });
return { rows, count }; return { rows, count };
@@ -151,7 +165,7 @@ async function detail(modelName, query) {
if (id === undefined || id === null || id === "") { if (id === undefined || id === null || id === "") {
throw new Error("缺少 id"); throw new Error("缺少 id");
} }
const row = await model.findByPk(id); const row = await model.findByPk(id, extraListAttributes(modelName, model));
return row; return row;
} }
@@ -160,6 +174,7 @@ async function all(modelName) {
const rows = await model.findAll({ const rows = await model.findAll({
limit: 2000, limit: 2000,
order: [["id", "DESC"]], order: [["id", "DESC"]],
...extraListAttributes(modelName, model),
}); });
return rows; return rows;
} }
@@ -172,6 +187,7 @@ async function exportCsv(modelName, body) {
where, where,
limit: 10000, limit: 10000,
order: [["id", "DESC"]], order: [["id", "DESC"]],
...extraListAttributes(modelName, model),
}); });
return { rows }; return { rows };
} }

View File

@@ -20,7 +20,6 @@ async function logAudit(p) {
resource_type: p.resource_type || "", resource_type: p.resource_type || "",
resource_id: p.resource_id != null ? p.resource_id : null, resource_id: p.resource_id != null ? p.resource_id : null,
detail: p.detail || null, detail: p.detail || null,
created_at: new Date(),
}); });
} catch (e) { } catch (e) {
logs.error("[biz_audit] 写入失败", e); logs.error("[biz_audit] 写入失败", e);