This commit is contained in:
张成
2025-11-21 16:53:49 +08:00
commit 8309808835
286 changed files with 32656 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
const fs = require("fs");
let api_front_dir = "../api/controller_front";
let admin_api_dir = "../api/controller_admin";
let rootApiPath = "/admin_api";
const baseController = {
// 普通api
init(routerGloab) {
rootApiPath = "/api";
this.registerRouter(routerGloab, api_front_dir);
return routerGloab;
},
init_admin(routerGloab) {
rootApiPath = "/admin_api";
this.registerRouter(routerGloab, admin_api_dir);
return routerGloab;
},
// 注册路由
registerRouter(routerGloab, dir) {
let folderPath = __dirname + "/" + dir;
let controllerFiles = fs.readdirSync(folderPath).filter((f) => {
return f.endsWith(".js");
});
controllerFiles.forEach((f) => {
let controllerName = require(folderPath + "/" + f);
console.warn(`${f}`);
this.fileRouter(routerGloab, controllerName);
});
},
// 注册 路由至 routerGloab
fileRouter(routerGloab, controller) {
try {
for (let url in controller) {
let path = "";
if (url.startsWith("GET ")) {
path = rootApiPath + url.substring(4);
routerGloab.get(path, controller[url]);
} else if (url.startsWith("POST ")) {
path = rootApiPath + url.substring(5);
routerGloab.post(path, controller[url]);
} else {
console.warn("无效路由:" + url);
}
console.log(path);
}
console.log("\n");
} catch (e) {
console.warn(e);
}
},
};
module.exports = () => {
let routerGloab = require("koa-router")();
baseController.init_admin(routerGloab);
baseController.init(routerGloab);
return routerGloab.routes();
};

17
middleware/baseModel.js Normal file
View File

@@ -0,0 +1,17 @@
const Sequelize = require("sequelize");
const common = require("../tool/common");
let models = common.mapFiles("../api/model/");
const db = require("./db");
models["Sequelize"] = Sequelize;
models["op"] = Sequelize.Op;
models["sys_user"].belongsTo(models["sys_role"], { foreignKey: "roleId", targetKey: "id", as: "role" });
models["sys_form"].belongsTo(models["sys_model"], { foreignKey: "model_id", targetKey: "id", as: "model" });
models["sys_form_field"].belongsTo(models["sys_model_field"], { foreignKey: "model_field_id", targetKey: "id", as: "field" });
models.querySql = async (sql) => {
return await db.sequelize.query(sql, { type: Sequelize.QueryTypes.SELECT });
};
module.exports = models;

241
middleware/baseRequest.js Normal file
View File

@@ -0,0 +1,241 @@
const token = require("../api/service/token");
const logsUtil = require("../tool/logs");
const xml2js = require("xml2js");
const nodeExcel = require("excel-export");
const UUID = require("uuid");
const config = require("../config/config");
const builder = new xml2js.Builder({
headless: true,
allowSurrogateChars: true,
rootName: "xml",
cdata: true,
});
module.exports = function () {
return async (ctx, next) => {
// 合并对象 兼容处理参数
ctx.get = (id) => {
let obj = Object.assign({}, ctx.request.query, ctx.request.body);
if (obj && typeof obj === "string") {
obj = JSON.parse(obj);
}
let value = obj[id] === undefined ? "" : obj[id];
return value;
};
ctx.getQuery = () => {
return ctx.request.query;
};
ctx.getIp = () => {
let req = ctx.req;
let ip = "";
let forwardedIpsStr = req.headers["x-forwarded-for"];
if (forwardedIpsStr) {
//如果有则将头信息中第一个地址拿出该地址就是真实的客户端IP
let forwardedIps = forwardedIpsStr.split(",");
ip = forwardedIps[0];
} else {
ip = req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
}
return ip;
};
ctx.getBody = () => {
let obj = Object.assign({}, ctx.body, ctx.request.body);
if (obj && typeof obj === "string") {
obj = JSON.parse(obj);
}
return obj;
};
ctx.getXml = () => {
let getxml = ctx.request.body;
return new Promise(async (resolveT, rejectT) => {
let paramsJson = null;
const parseObj = await new Promise(function (resolve) {
xml2js.parseString(getxml, { explicitArray: false }, function (err, json) {
if (err) throw err;
return resolve(json);
});
});
if (parseObj.xml) delete parseObj.xml._;
paramsJson = parseObj.xml;
console.log("getXml", paramsJson);
resolveT(paramsJson);
});
};
// admin
ctx.getAdminUserId = () => {
let adminToken = ctx.header["admin-token"];
if (adminToken) {
let userInfo = token.parse(adminToken);
if (userInfo) {
return userInfo.id;
}
}
return 0;
};
ctx.getAdminProjectId = () => {
let id = ctx.header["admin-project"];
if (id) {
return id;
}
return 0;
};
// 获取小程序id
ctx.getPappletUserId = () => {
// 模拟用户登陆
let userId = ctx.request.query["userId206"];
if (userId) {
return userId;
}
let appletToken = ctx.header["applet-token"];
if (appletToken) {
let userInfo = token.parse(appletToken);
if (userInfo.weixin_openid && userInfo.id) {
return userInfo.id;
}
}
return 0;
};
ctx.getSessionKey = () => {
let appletToken = ctx.header["applet-token"];
if (appletToken) {
let userInfo = token.parse(appletToken);
if (userInfo.session_key) {
return userInfo.session_key;
}
}
return "";
};
// 获取分页排序
ctx.getPageSize = () => {
let pageOption = ctx.get("pageOption");
if (pageOption && typeof pageOption === "string") {
pageOption = JSON.parse(pageOption);
}
let page = pageOption.page || 1;
let size = pageOption.pageSize || 20;
return {
limit: size,
offset: size * (page - 1),
};
};
// 获取订单排序相关 [['sale_price','desc']]
ctx.getOrder = (key) => {
key = key || "order";
let order = ctx.get(key);
if (Array.isArray(order)) {
return order;
} else {
try {
order = eval("(" + order + ")");
} catch (e) {
console.warn("error " + e.message);
order = [];
}
return order;
}
};
//返回自定义code
ctx.json = (code, message, data) => {
ctx.response.type = "application/json";
let resObj = {
code,
message,
data,
};
ctx.response.body = resObj;
};
ctx.jsonToXml = (return_code, return_msg) => {
ctx.response.type = "application/xml";
let resObj = {
return_code,
return_msg,
};
const xmlOption = builder.buildObject(resObj);
ctx.response.body = xmlOption;
};
ctx.downFile = ({ title, cols, rows }) => {
let fileName = title + "_" + UUID.v4() + ".xlsx";
let result = nodeExcel.execute({ cols, rows });
let data = new Buffer.from(result, "binary");
ctx.set("Content-Type", "application/vnd.openxmlformats");
ctx.set("Content-Disposition", "attachment; filename=" + fileName);
ctx.set("filename", fileName);
ctx.body = data;
};
// 成功请求
ctx.success = (data) => {
ctx.json(0, "请求成功!", data);
};
// 失败请求
ctx.fail = (msg) => {
let message = msg || "请求失败!";
ctx.json(-1, message, {});
};
//token 失效
ctx.tokenFail = (data) => {
ctx.json(-2, "非法请求,或登录已超时!", data);
};
console.log(`Process API ${ctx.request.method} ${ctx.request.url}...`);
let allowUrls = config.allowUrls;
try {
// 登录注册不需要验证token
const checkApi = (path) => {
let isCheck = false;
for (let i = 0; i < allowUrls.length; i++) {
let url = allowUrls[i];
if (path.indexOf(url) > -1) {
isCheck = true;
}
}
return isCheck;
};
if (checkApi(ctx.request.path)) {
return await next();
} else {
if (ctx.request.path.indexOf("/admin_api/") > -1) {
let id = ctx.getAdminUserId();
if (id) {
return await next();
}
} else if (ctx.request.path.indexOf("/api/") > -1) {
return await next();
}
return ctx.tokenFail(); // 非法请求
}
} catch (e) {
logsUtil.ctxError(e, ctx);
return ctx.fail(e.message);
}
};
};

160
middleware/db.js Normal file
View File

@@ -0,0 +1,160 @@
const Sequelize = require("sequelize");
const config = require("../config/config")["db"];
const dayjs = require("dayjs");
let model = {};
const logEditField = (oldRow, newRow) => {
let str = ``;
oldRow = oldRow.toJSON ? oldRow.toJSON() : oldRow;
newRow = newRow ? newRow.toJSON() : newRow;
let keyRows = Object.keys(oldRow);
for (let i = 0; i < keyRows.length; i++) {
let key = keyRows[i];
if (key !== "create_time" && key !== "last_modify_time" && oldRow[key] !== newRow[key]) {
let oldVal = oldRow[key];
if (typeof oldVal === "string") {
oldVal = oldVal.replace(/<p>/g, "").replace(/<\/p>/g, "");
}
let newVal = newRow[key];
if (typeof newVal === "string") {
newVal = newVal.replace(/<p>/g, "").replace(/<\/p>/g, "");
}
str += ` ${key} 从<span class="bold"> ${oldVal} </span> 变更为 <span class="bold"> ${newVal} </span><br>`;
}
}
return str;
};
const logCreateField = (oldRow) => {
let str = ``;
oldRow = oldRow.toJSON ? oldRow.toJSON() : oldRow;
let keyRows = Object.keys(oldRow);
for (let i = 0; i < keyRows.length; i++) {
let key = keyRows[i];
if (key !== "create_time" && key !== "last_modify_time") {
let newVal = oldRow[key];
if (typeof newVal === "string") {
newVal = newVal.replace(/<p>/g, "").replace(/<\/p>/g, "");
}
str += `<span class="bold"> ${key} </span> 为 <span class="bold"> ${newVal} </span><br>`;
}
}
return str;
};
let sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: config.dialect,
pool: {
max: 5,
min: 0,
idle: 10000,
},
dialectOptions: {
charset: "utf8mb4",
collate: "utf8mb4_unicode_ci",
supportBigNumbers: true,
bigNumberStrings: true,
},
});
const define = (name, attributes) => {
let attrs = {};
for (let key in attributes) {
let value = attributes[key];
if (typeof value === "object" && value["type"]) {
value.allowNull = value.allowNull || false;
attrs[key] = value;
} else {
attrs[key] = {
type: value,
allowNull: false,
};
}
}
attrs.create_time = {
type: Sequelize.DATE,
allowNull: false,
defaultValue: sequelize.literal("CURRENT_TIMESTAMP"),
comment: "创建时间",
get() {
return dayjs(this.getDataValue("create_time")).format("YYYY-MM-DD HH:mm:ss");
},
};
attrs.last_modify_time = {
type: Sequelize.DATE,
allowNull: false,
comment: "最后更新时间",
defaultValue: sequelize.literal("CURRENT_TIMESTAMP"),
get() {
return dayjs(this.getDataValue("last_modify_time")).format("YYYY-MM-DD HH:mm:ss");
},
};
model[name] = sequelize.define(name, attrs, {
tableName: name,
timestamps: false,
hooks: {
beforeValidate: (obj) => {
let now = Date.now();
if (obj.isNewRecord) {
obj.create_time = now;
obj.last_modify_time = now;
} else {
obj.last_modify_time = now;
}
},
afterCreate: async (obj) => {
let tableName = obj._modelOptions.tableName;
if (tableName !== "sys_log") {
let logStr = logCreateField(obj);
await model["sys_log"].create({ table_name: tableName, operate: "新增", content: logStr });
}
},
afterDestroy: async (obj) => {
let id = obj.id;
let tableName = obj._modelOptions.tableName;
if (tableName !== "sys_log") {
await model["sys_log"].create({ table_name: tableName, operate: "删除", content: `用户删除id为 <span class="bold"> ${id} </span>` });
}
},
beforeUpdate: async (obj) => {
let tableName = obj._modelOptions.tableName;
if (tableName !== "sys_log") {
let id = obj.id;
let tableName = obj._modelOptions.tableName;
let updateRow = await model[tableName].findOne({ where: { id } });
let logStr = logEditField(updateRow, obj);
await model["sys_log"].create({ table_name: tableName, operate: "修改", content: logStr });
}
},
},
});
return model[name];
};
let exp = {
sequelize,
define,
sync: () => {
if (process.env.NODE_ENV !== "production") {
sequelize.sync({ force: false });
} else {
throw new Error("Cannot sync() when NODE_ENV is set to 'production'.");
}
},
};
module.exports = exp;

7
middleware/schedule.js Normal file
View File

@@ -0,0 +1,7 @@
const node_schedule = require("node-schedule");
class Schedule {
init() {}
}
const schedule = new Schedule();
module.exports = schedule;

52
middleware/sqlUpdate.js Normal file
View File

@@ -0,0 +1,52 @@
const { querySql, user, good, business, good_evaluate, shp_profit, user_apply_cash, user_dividend, user_meet, user_note_invite, user_question, op } = require("./baseModel");
class SqlUpdate {
async init() {
// await this.udateGoodSelePrice()
// await this.udateShippingFee()
// await this.initDb()
}
// 更新邮费
async udateShippingFee() {
let resBusiness = await querySql(`select a.business_id,sum(a.shipping_fee) as shipping_fee_total from business_profit_dtl as a
where a.shipping_fee!=0
GROUP BY a.business_id`);
if (resBusiness && resBusiness.length > 0) {
for (let i = 0; i < resBusiness.length; i++) {
let row = resBusiness[i];
let { shipping_fee_total, business_id } = row;
await business.update({ shipping_fee_total: shipping_fee_total }, { where: { id: business_id } });
}
}
}
async udateGoodSelePrice() {
let goodRows = await good.findAll();
for (let i = 0; i < goodRows.length; i++) {
let goodRow = goodRows[i];
await goodRow.update({ sale_price: goodRow.specificationStr.sale_price });
}
}
// 测试数据库专用用于 初始化db
async initDb() {
await order.destroy({ where: {}, truncate: true });
await order_dtls.destroy({ where: {}, truncate: true });
await good_evaluate.destroy({ where: {}, truncate: true });
await shp_profit.destroy({ where: {}, truncate: true });
await user_apply_cash.destroy({ where: {}, truncate: true });
await user_dividend.destroy({ where: {}, truncate: true });
await user_meet.destroy({ where: {}, truncate: true });
await user_note_invite.destroy({ where: {}, truncate: true });
await user_question.destroy({ where: {}, truncate: true });
let userRows = await user.findAll({});
for (let i = 0; i < userRows.length; i++) {
let userRow = userRows[i];
await userRow.update({ in_come: 0, extend_come: 0, total_consume: 0, overage_money: 0, consume_equity: 0, seed_number: 10, vip_grade_id: 1 });
}
}
}
const sqlUpdate = new SqlUpdate();
module.exports = sqlUpdate;