Files
wechatWeb/api/service/biz_admin_crud.js
张成 aa8eaa6ccd init
2026-03-24 16:07:02 +08:00

190 lines
4.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 订阅模块通用 CRUD与 admin 约定 POST /{model}/page|add|edit|del GET /{model}/detail|all
*/
const baseModel = require("../../middleware/baseModel");
const { op } = baseModel;
function getRequestBody(ctx) {
if (ctx.request && ctx.request.body && Object.keys(ctx.request.body).length > 0) {
return ctx.request.body;
}
if (typeof ctx.getBody === "function") {
return ctx.getBody() || {};
}
return {};
}
function getModel(modelName) {
const m = baseModel[modelName];
if (!m) {
throw new Error(`模型不存在: ${modelName}`);
}
return m;
}
function normalizeForWrite(model, data, { forCreate } = {}) {
const attrs = model.rawAttributes;
const out = {};
for (const k of Object.keys(data || {})) {
if (!attrs[k]) continue;
let v = data[k];
if (v === "") {
if (k === "id" && forCreate) continue;
if (k.endsWith("_id") || k === "id") {
v = null;
} else if (attrs[k].allowNull) {
v = null;
}
}
if (k === "enabled_features" && typeof v === "string" && v.trim() !== "") {
try {
v = JSON.parse(v);
} catch (e) {
/* 保持原字符串,由 Sequelize 或 DB 报错 */
}
}
out[k] = v;
}
if (forCreate && out.id !== undefined && (out.id === "" || out.id === null)) {
delete out.id;
}
return out;
}
function buildSearchWhere(model, seachOption) {
const key = seachOption && seachOption.key;
const raw = seachOption && seachOption.value;
if (!key || raw === undefined || raw === null) return {};
const str = String(raw).trim();
if (str === "") return {};
const attr = model.rawAttributes[key];
if (!attr) {
return { [key]: { [op.like]: `%${str}%` } };
}
const typeKey = attr.type && attr.type.key;
if (typeKey === "BOOLEAN") {
if (str === "true" || str === "1" || str === "是") return { [key]: true };
if (str === "false" || str === "0" || str === "否") return { [key]: false };
return {};
}
if (typeKey === "ENUM") {
return { [key]: str };
}
if (
typeKey === "INTEGER" ||
typeKey === "BIGINT" ||
typeKey === "FLOAT" ||
typeKey === "DOUBLE" ||
typeKey === "DECIMAL"
) {
const n = Number(str);
if (!Number.isNaN(n)) return { [key]: n };
return {};
}
if (typeKey === "DATE" || typeKey === "DATEONLY") {
return { [key]: str };
}
return { [key]: { [op.like]: `%${str}%` } };
}
async function page(modelName, body) {
const model = getModel(modelName);
const param = body.param || body;
const pageOption = param.pageOption || {};
const seachOption = param.seachOption || {};
const pageNum = parseInt(pageOption.page, 10) || 1;
const pageSize = parseInt(pageOption.pageSize, 10) || 20;
const offset = (pageNum - 1) * pageSize;
const where = buildSearchWhere(model, seachOption);
const { count, rows } = await model.findAndCountAll({
where,
offset,
limit: pageSize,
order: [["id", "DESC"]],
});
return { rows, count };
}
async function add(modelName, body) {
const model = getModel(modelName);
const payload = normalizeForWrite(model, body, { forCreate: true });
const row = await model.create(payload);
return row;
}
async function edit(modelName, body) {
const model = getModel(modelName);
const id = body.id;
if (id === undefined || id === null || id === "") {
throw new Error("缺少 id");
}
const payload = normalizeForWrite(model, body, { forCreate: false });
delete payload.id;
await model.update(payload, { where: { id } });
return {};
}
async function del(modelName, body) {
const model = getModel(modelName);
const id = body.id !== undefined ? body.id : body;
if (id === undefined || id === null || id === "") {
throw new Error("缺少 id");
}
await model.destroy({ where: { id } });
return {};
}
async function detail(modelName, query) {
const model = getModel(modelName);
const id = query && (query.id || query.ID);
if (id === undefined || id === null || id === "") {
throw new Error("缺少 id");
}
const row = await model.findByPk(id);
return row;
}
async function all(modelName) {
const model = getModel(modelName);
const rows = await model.findAll({
limit: 2000,
order: [["id", "DESC"]],
});
return rows;
}
async function exportCsv(modelName, body) {
const model = getModel(modelName);
const param = body.param || body;
const where = buildSearchWhere(model, param.seachOption || {});
const rows = await model.findAll({
where,
limit: 10000,
order: [["id", "DESC"]],
});
return { rows };
}
module.exports = {
page,
add,
edit,
del,
detail,
all,
exportCsv,
getRequestBody,
buildSearchWhere,
};