diff --git a/.cursor/rules/node-core-framework.mdc b/.cursor/rules/node-core-framework.mdc index 03a87c5..b92a88c 100644 --- a/.cursor/rules/node-core-framework.mdc +++ b/.cursor/rules/node-core-framework.mdc @@ -19,7 +19,7 @@ alwaysApply: true | 模型关联 | `./config/model.associations.js` | | 白名单 | `./config/config.js` → `allowUrls` | | `beforeInitApi` 实现体 | `./config/before_init_api.js`(由 `framework.config.js` 挂到 `init` 参数) | -| 管理端通用工具(非业务域) | `api/utils/query_helpers.js`(分页/筛选/导出)、`api/utils/biz_audit.js`(审计) | +| 管理端通用工具(非业务域) | `api/utils/query_helpers.js`(仅 `build_search_where` / `normalize_for_write`;分页与导出在各 controller 内 `findAndCountAll` / `findAll`)、`api/utils/biz_audit.js`(审计) | | 跨端/复杂业务 | `api/service/*`(如 `biz_auth_verify`、`biz_proxy_service`、`biz_subscription_logic`、`biz_token_logic`) | --- diff --git a/api/controller_admin/biz_api_stats.js b/api/controller_admin/biz_api_stats.js index ecb6b5a..80514b0 100644 --- a/api/controller_admin/biz_api_stats.js +++ b/api/controller_admin/biz_api_stats.js @@ -1,7 +1,7 @@ const Sequelize = require("sequelize"); const { Op } = Sequelize; const baseModel = require("../../middleware/baseModel"); -const { find_page } = require("../utils/query_helpers"); +const { build_search_where } = require("../utils/query_helpers"); function build_date_where(start_date, end_date) { const where = {}; @@ -107,7 +107,20 @@ module.exports = { "POST /biz_api_call_log/page": async (ctx) => { const body = ctx.getBody(); - const { count, rows } = await find_page(baseModel.biz_api_call_log, "biz_api_call_log", body); + const param = body.param || body; + const page_option = param.pageOption || {}; + const seach_option = param.seachOption || {}; + const page_num = parseInt(page_option.page, 10) || 1; + const page_size = parseInt(page_option.pageSize, 10) || 20; + const offset = (page_num - 1) * page_size; + const biz_api_call_log = baseModel.biz_api_call_log; + const where = build_search_where(biz_api_call_log, seach_option); + const { count, rows } = await biz_api_call_log.findAndCountAll({ + where, + offset, + limit: page_size, + order: [["id", "DESC"]], + }); ctx.success({ rows, count }); }, }; diff --git a/api/controller_admin/biz_audit_log.js b/api/controller_admin/biz_audit_log.js index abff093..a1cfe6f 100644 --- a/api/controller_admin/biz_audit_log.js +++ b/api/controller_admin/biz_audit_log.js @@ -1,15 +1,43 @@ const baseModel = require("../../middleware/baseModel"); -const { find_page, find_for_export } = require("../utils/query_helpers"); +const { build_search_where } = require("../utils/query_helpers"); module.exports = { "POST /biz_audit_log/page": async (ctx) => { const body = ctx.getBody(); - const { count, rows } = await find_page(baseModel.biz_audit_log, "biz_audit_log", body); + const param = body.param || body; + const page_option = param.pageOption || {}; + const seach_option = param.seachOption || {}; + const page_num = parseInt(page_option.page, 10) || 1; + const page_size = parseInt(page_option.pageSize, 10) || 20; + const offset = (page_num - 1) * page_size; + const biz_audit_log = baseModel.biz_audit_log; + const where = build_search_where(biz_audit_log, seach_option); + const tn = biz_audit_log.tableName; + const { count, rows } = await biz_audit_log.findAndCountAll({ + where, + offset, + limit: page_size, + order: [["id", "DESC"]], + attributes: { + include: [[biz_audit_log.sequelize.col(`${tn}.created_at`), "created_at"]], + }, + }); ctx.success({ rows, count }); }, "POST /biz_audit_log/export": async (ctx) => { const body = ctx.getBody(); - const res = await find_for_export(baseModel.biz_audit_log, "biz_audit_log", body); - ctx.success(res); + const param = body.param || body; + const biz_audit_log = baseModel.biz_audit_log; + const where = build_search_where(biz_audit_log, param.seachOption || {}); + const tn = biz_audit_log.tableName; + const rows = await biz_audit_log.findAll({ + where, + limit: 10000, + order: [["id", "DESC"]], + attributes: { + include: [[biz_audit_log.sequelize.col(`${tn}.created_at`), "created_at"]], + }, + }); + ctx.success({ rows }); }, }; diff --git a/api/controller_admin/biz_plan.js b/api/controller_admin/biz_plan.js index b7c3bcc..9c73c60 100644 --- a/api/controller_admin/biz_plan.js +++ b/api/controller_admin/biz_plan.js @@ -1,11 +1,24 @@ const baseModel = require("../../middleware/baseModel"); -const { find_page, find_for_export, normalize_for_write } = require("../utils/query_helpers"); +const { build_search_where, normalize_for_write } = require("../utils/query_helpers"); const audit = require("../utils/biz_audit"); module.exports = { "POST /biz_plan/page": async (ctx) => { const body = ctx.getBody(); - const { count, rows } = await find_page(baseModel.biz_plan, "biz_plan", body); + const param = body.param || body; + const page_option = param.pageOption || {}; + const seach_option = param.seachOption || {}; + const page_num = parseInt(page_option.page, 10) || 1; + const page_size = parseInt(page_option.pageSize, 10) || 20; + const offset = (page_num - 1) * page_size; + const biz_plan = baseModel.biz_plan; + const where = build_search_where(biz_plan, seach_option); + const { count, rows } = await biz_plan.findAndCountAll({ + where, + offset, + limit: page_size, + order: [["id", "DESC"]], + }); ctx.success({ rows, count }); }, "POST /biz_plan/add": async (ctx) => { @@ -82,7 +95,14 @@ module.exports = { }, "POST /biz_plan/export": async (ctx) => { const body = ctx.getBody(); - const res = await find_for_export(baseModel.biz_plan, "biz_plan", body); - ctx.success(res); + const param = body.param || body; + const biz_plan = baseModel.biz_plan; + const where = build_search_where(biz_plan, param.seachOption || {}); + const rows = await biz_plan.findAll({ + where, + limit: 10000, + order: [["id", "DESC"]], + }); + ctx.success({ rows }); }, }; diff --git a/api/controller_admin/biz_subscription.js b/api/controller_admin/biz_subscription.js index cbf25a7..e796efe 100644 --- a/api/controller_admin/biz_subscription.js +++ b/api/controller_admin/biz_subscription.js @@ -1,12 +1,25 @@ const baseModel = require("../../middleware/baseModel"); -const { find_page, find_for_export } = require("../utils/query_helpers"); +const { build_search_where } = require("../utils/query_helpers"); const logic = require("../service/biz_subscription_logic"); const audit = require("../utils/biz_audit"); module.exports = { "POST /biz_subscription/page": async (ctx) => { const body = ctx.getBody(); - const { count, rows } = await find_page(baseModel.biz_subscription, "biz_subscription", body); + const param = body.param || body; + const page_option = param.pageOption || {}; + const seach_option = param.seachOption || {}; + const page_num = parseInt(page_option.page, 10) || 1; + const page_size = parseInt(page_option.pageSize, 10) || 20; + const offset = (page_num - 1) * page_size; + const biz_subscription = baseModel.biz_subscription; + const where = build_search_where(biz_subscription, seach_option); + const { count, rows } = await biz_subscription.findAndCountAll({ + where, + offset, + limit: page_size, + order: [["id", "DESC"]], + }); ctx.success({ rows, count }); }, "GET /biz_subscription/detail": async (ctx) => { @@ -75,7 +88,14 @@ module.exports = { }, "POST /biz_subscription/export": async (ctx) => { const body = ctx.getBody(); - const res = await find_for_export(baseModel.biz_subscription, "biz_subscription", body); - ctx.success(res); + const param = body.param || body; + const biz_subscription = baseModel.biz_subscription; + const where = build_search_where(biz_subscription, param.seachOption || {}); + const rows = await biz_subscription.findAll({ + where, + limit: 10000, + order: [["id", "DESC"]], + }); + ctx.success({ rows }); }, }; diff --git a/api/controller_admin/biz_token.js b/api/controller_admin/biz_token.js index 662b78e..545a4a4 100644 --- a/api/controller_admin/biz_token.js +++ b/api/controller_admin/biz_token.js @@ -1,12 +1,25 @@ const baseModel = require("../../middleware/baseModel"); -const { find_page, find_for_export } = require("../utils/query_helpers"); +const { build_search_where } = require("../utils/query_helpers"); const tokenLogic = require("../service/biz_token_logic"); const audit = require("../utils/biz_audit"); module.exports = { "POST /biz_token/page": async (ctx) => { const body = ctx.getBody(); - const { count, rows } = await find_page(baseModel.biz_api_token, "biz_api_token", body); + const param = body.param || body; + const page_option = param.pageOption || {}; + const seach_option = param.seachOption || {}; + const page_num = parseInt(page_option.page, 10) || 1; + const page_size = parseInt(page_option.pageSize, 10) || 20; + const offset = (page_num - 1) * page_size; + const biz_api_token = baseModel.biz_api_token; + const where = build_search_where(biz_api_token, seach_option); + const { count, rows } = await biz_api_token.findAndCountAll({ + where, + offset, + limit: page_size, + order: [["id", "DESC"]], + }); ctx.success({ rows, count }); }, "POST /biz_token/create": async (ctx) => { @@ -44,7 +57,14 @@ module.exports = { }, "POST /biz_token/export": async (ctx) => { const body = ctx.getBody(); - const res = await find_for_export(baseModel.biz_api_token, "biz_api_token", body); - ctx.success(res); + const param = body.param || body; + const biz_api_token = baseModel.biz_api_token; + const where = build_search_where(biz_api_token, param.seachOption || {}); + const rows = await biz_api_token.findAll({ + where, + limit: 10000, + order: [["id", "DESC"]], + }); + ctx.success({ rows }); }, }; diff --git a/api/controller_admin/biz_usage.js b/api/controller_admin/biz_usage.js index 4530f3c..98e01ef 100644 --- a/api/controller_admin/biz_usage.js +++ b/api/controller_admin/biz_usage.js @@ -1,10 +1,23 @@ const baseModel = require("../../middleware/baseModel"); -const { find_page, find_for_export, normalize_for_write } = require("../utils/query_helpers"); +const { build_search_where, normalize_for_write } = require("../utils/query_helpers"); module.exports = { "POST /biz_usage/page": async (ctx) => { const body = ctx.getBody(); - const { count, rows } = await find_page(baseModel.biz_usage_monthly, "biz_usage_monthly", body); + const param = body.param || body; + const page_option = param.pageOption || {}; + const seach_option = param.seachOption || {}; + const page_num = parseInt(page_option.page, 10) || 1; + const page_size = parseInt(page_option.pageSize, 10) || 20; + const offset = (page_num - 1) * page_size; + const biz_usage_monthly = baseModel.biz_usage_monthly; + const where = build_search_where(biz_usage_monthly, seach_option); + const { count, rows } = await biz_usage_monthly.findAndCountAll({ + where, + offset, + limit: page_size, + order: [["id", "DESC"]], + }); ctx.success({ rows, count }); }, "POST /biz_usage/add": async (ctx) => { @@ -38,7 +51,14 @@ module.exports = { }, "POST /biz_usage/export": async (ctx) => { const body = ctx.getBody(); - const res = await find_for_export(baseModel.biz_usage_monthly, "biz_usage_monthly", body); - ctx.success(res); + const param = body.param || body; + const biz_usage_monthly = baseModel.biz_usage_monthly; + const where = build_search_where(biz_usage_monthly, param.seachOption || {}); + const rows = await biz_usage_monthly.findAll({ + where, + limit: 10000, + order: [["id", "DESC"]], + }); + ctx.success({ rows }); }, }; diff --git a/api/controller_admin/biz_user.js b/api/controller_admin/biz_user.js index 71a7883..0596b4f 100644 --- a/api/controller_admin/biz_user.js +++ b/api/controller_admin/biz_user.js @@ -1,5 +1,5 @@ const Sequelize = require("sequelize"); -const { find_for_export, normalize_for_write, build_search_where } = require("../utils/query_helpers"); +const { normalize_for_write, build_search_where } = require("../utils/query_helpers"); const baseModel = require("../../middleware/baseModel"); const tokenLogic = require("../service/biz_token_logic"); const audit = require("../utils/biz_audit"); @@ -13,9 +13,9 @@ module.exports = { const pageNum = parseInt(pageOption.page, 10) || 1; const pageSize = parseInt(pageOption.pageSize, 10) || 20; const offset = (pageNum - 1) * pageSize; - const model = baseModel.biz_user; - const where = build_search_where(model, seachOption); - const { count, rows } = await model.findAndCountAll({ + const biz_user = baseModel.biz_user; + const where = build_search_where(biz_user, seachOption); + const { count, rows } = await biz_user.findAndCountAll({ where, offset, limit: pageSize, @@ -35,8 +35,9 @@ module.exports = { }, "POST /biz_user/add": async (ctx) => { const body = ctx.getBody(); - const payload = normalize_for_write(baseModel.biz_user, body, { for_create: true }); - const row = await baseModel.biz_user.create(payload); + const biz_user = baseModel.biz_user; + const payload = normalize_for_write(biz_user, body, { for_create: true }); + const row = await biz_user.create(payload); await audit.logAudit({ admin_user_id: audit.pickAdminId(ctx), biz_user_id: row.id, @@ -51,9 +52,10 @@ module.exports = { const body = ctx.getBody(); const id = body.id; if (id === undefined || id === null || id === "") throw new Error("缺少 id"); - const payload = normalize_for_write(baseModel.biz_user, body, { for_create: false }); + const biz_user = baseModel.biz_user; + const payload = normalize_for_write(biz_user, body, { for_create: false }); delete payload.id; - await baseModel.biz_user.update(payload, { where: { id } }); + await biz_user.update(payload, { where: { id } }); await audit.logAudit({ admin_user_id: audit.pickAdminId(ctx), biz_user_id: body.id, @@ -67,7 +69,8 @@ module.exports = { const body = ctx.getBody(); const id = body.id !== undefined ? body.id : body; if (id === undefined || id === null || id === "") throw new Error("缺少 id"); - await baseModel.biz_user.destroy({ where: { id } }); + const biz_user = baseModel.biz_user; + await biz_user.destroy({ where: { id } }); await audit.logAudit({ admin_user_id: audit.pickAdminId(ctx), biz_user_id: body.id, @@ -81,7 +84,8 @@ module.exports = { const q = ctx.query || {}; const id = q.id || q.ID; if (id === undefined || id === null || id === "") throw new Error("缺少 id"); - const user = await baseModel.biz_user.findByPk(id); + const biz_user = baseModel.biz_user; + const user = await biz_user.findByPk(id); if (!user) { return ctx.fail("用户不存在"); } @@ -107,7 +111,8 @@ module.exports = { }); }, "GET /biz_user/all": async (ctx) => { - const rows = await baseModel.biz_user.findAll({ + const biz_user = baseModel.biz_user; + const rows = await biz_user.findAll({ limit: 2000, order: [["id", "DESC"]], }); @@ -117,7 +122,8 @@ module.exports = { const body = ctx.getBody(); const id = body.id; if (id == null) return ctx.fail("缺少 id"); - await baseModel.biz_user.update({ status: "disabled" }, { where: { id } }); + const biz_user = baseModel.biz_user; + await biz_user.update({ status: "disabled" }, { where: { id } }); await audit.logAudit({ admin_user_id: audit.pickAdminId(ctx), biz_user_id: id, @@ -131,7 +137,8 @@ module.exports = { const body = ctx.getBody(); const id = body.id; if (id == null) return ctx.fail("缺少 id"); - await baseModel.biz_user.update({ status: "active" }, { where: { id } }); + const biz_user = baseModel.biz_user; + await biz_user.update({ status: "active" }, { where: { id } }); await audit.logAudit({ admin_user_id: audit.pickAdminId(ctx), biz_user_id: id, @@ -143,8 +150,15 @@ module.exports = { }, "POST /biz_user/export": async (ctx) => { const body = ctx.getBody(); - const res = await find_for_export(baseModel.biz_user, "biz_user", body); - ctx.success(res); + const param = body.param || body; + const biz_user = baseModel.biz_user; + const where = build_search_where(biz_user, param.seachOption || {}); + const rows = await biz_user.findAll({ + where, + limit: 10000, + order: [["id", "DESC"]], + }); + ctx.success({ rows }); }, "POST /biz_user/revoke_all_tokens": async (ctx) => { const body = ctx.getBody(); diff --git a/api/utils/query_helpers.js b/api/utils/query_helpers.js index 49420fe..ed21a4a 100644 --- a/api/utils/query_helpers.js +++ b/api/utils/query_helpers.js @@ -1,5 +1,5 @@ /** - * 管理端列表筛选、导出、写入字段裁剪(供 controller_admin 配合 baseModel) + * 管理端:筛选条件、写入字段裁剪(分页/导出在各 controller 内直接 findAndCountAll / findAll) */ const Sequelize = require("sequelize"); const { Op } = Sequelize; @@ -76,53 +76,7 @@ function normalize_for_write(model, data, { for_create } = {}) { return out; } -function list_query_extra(model_name, model) { - if (model_name === "biz_audit_log") { - const tn = model.tableName; - return { - attributes: { - include: [[model.sequelize.col(`${tn}.created_at`), "created_at"]], - }, - }; - } - return {}; -} - -async function find_page(model, model_name, body, extra_find_options = {}) { - const param = body.param || body; - const page_option = param.pageOption || {}; - const seach_option = param.seachOption || {}; - const page_num = parseInt(page_option.page, 10) || 1; - const page_size = parseInt(page_option.pageSize, 10) || 20; - const offset = (page_num - 1) * page_size; - const where = build_search_where(model, seach_option); - return model.findAndCountAll({ - where, - offset, - limit: page_size, - order: [["id", "DESC"]], - ...list_query_extra(model_name, model), - ...extra_find_options, - }); -} - -async function find_for_export(model, model_name, body, extra_find_options = {}) { - const param = body.param || body; - const where = build_search_where(model, param.seachOption || {}); - const rows = await model.findAll({ - where, - limit: 10000, - order: [["id", "DESC"]], - ...list_query_extra(model_name, model), - ...extra_find_options, - }); - return { rows }; -} - module.exports = { build_search_where, normalize_for_write, - list_query_extra, - find_page, - find_for_export, };