明树Git Lab

Commit f16459c9 authored by zfp1's avatar zfp1

merge

parents 3f1edd1a c4c723e5
Pipeline #103790 failed with stage
in 1 second
const _ = require('lodash');
let a = [
{
xjlr: 100,
xjlc: 200,
sdsqjxjll: 300,
tzsds: 400,
sdshjxjll: 500,
year: "合计",
},
{
xjlr: 100,
xjlc: 200,
sdsqjxjll: 300,
tzsds: 400,
sdshjxjll: 500,
year: 2022,
},
{
xjlr: 101,
xjlc: 201,
sdsqjxjll: 301,
tzsds: 401,
sdshjxjll: 501,
year: 2023,
},
{
xjlr: 1003,
xjlc: 2003,
sdsqjxjll: 3003,
tzsds: 4003,
sdshjxjll: 5003,
year: "2024",
},
{
xjlr: 1004,
xjlc: 2004,
sdsqjxjll: 3004,
tzsds: 4004,
sdshjxjll: 5004,
year: "2025",
}
]
const b = _.sortBy(a, 'year');
console.log(b);
function thvc(a) {
let xjlr = [], xjlc = [], sdsqjxjll = [], tzsds = [], sdshjxjll =[];
let retArr = [];
for (let index = 0; index < a.length; index++) {
const element = a[index];
xjlr.push(element.xjlr);
xjlc.push(element.xjlc);
sdsqjxjll.push(element.sdsqjxjll);
tzsds.push(element.tzsds);
sdshjxjll.push(element.sdshjxjll);
// year.push(element.year);
}
return [xjlr, xjlc, sdsqjxjll, tzsds, sdshjxjll];
}
console.log(thvc(a));
function cvht(obj) {
for (const key in obj) {
const element = obj[key];
}
}
function reverseTransform(transformedData) {
// 获取第一个字段的数组长度作为对象数量
const field = Object.keys(transformedData)[0];
const itemCount = transformedData[field].length;
const result = [];
// 遍历每个索引位置构建对象
for (let i = 0; i < itemCount; i++) {
const item = {};
// 为每个字段赋值
for (const key in transformedData) {
if (transformedData.hasOwnProperty(key)) {
item[key] = transformedData[key][i];
}
}
result.push(item);
}
return result;
}
// 使用示例
const transformed = {
xjlr: [100, 100, 101, 1003, 1004],
xjlc: [200, 200, 201, 2003, 2004],
sdsqjxjll: [300, 300, 301, 3003, 3004],
tzsds: [400, 400, 401, 4003, 4004],
sdshjxjll: [500, 500, 501, 5003, 5004]
};
// console.log(reverseTransform(transformed));
// console.log(thvc(a));
\ No newline at end of file
{ {
"tokenEx": 86400000000, "tokenEx": 86400000000,
"dbURI": "mongodb://127.0.0.1:27017/letian?authSource=admin", "userDefaultPassword": "GZB123JT.",
"file": { "file": {
"storagePath": "/uploadfiles" "storagePath": "/uploadfiles"
}, },
"cron": { "cron": {
"excel": true
}, },
"mysql": { "mysql": {
"host": "localhost", "host": "localhost",
"port": 3306, "port": 3306,
"username": "root", "username": "root",
"password": "123456", "password": "123456",
"database": "test", "database": "gzbjt",
"logging": true "logging": true
}, },
"dmdb": {
"host": "localhost",
"port": 5236,
"username": "SYSDBA",
"password": "SYSDBA",
"database": "letian",
"logging": true,
"connectString": "dm://SYSDBA:SYSDBA@localhost:5236"
},
"redis": { "redis": {
"host": "localhost", "host": "localhost",
"port": 6379, "port": 6379,
......
{ {
"tokenEx": 86400, "tokenEx": 86400000000,
"dbURI": "mongodb://root:letian2024.@127.0.0.1:27017/letian?authSource=admin", "userDefaultPassword": "GZB123JT.",
"file": { "file": {
"storagePath": "/mnt/vdb1/uploadfiles" "storagePath": "/uploadfiles"
}, },
"cron": { "cron": {
"excel": true
},
"mysql": {
"host": "10.40.8.8",
"port": 3306,
"username": "root",
"password": "gzbjt@2025",
"database": "gzbjt",
"logging": true
},
"redis": {
"host": "localhost",
"port": 6379,
"password": "",
"db": 0
} }
} }
\ No newline at end of file
const errorMessage = require("../utils/errorMessage");
const { Op } = require('sequelize');
async function createDepart(req, res, next) {
try {
const body = req.body;
if (body.parentId) {
//查父节点
let parendNode = await DB.Depart.findOne({ where: { id: body.parentId }, raw: true, attributes: ['parentIds'] });
if (!parendNode) {
return res.sendError(errorMessage.resourceNotFound);
}
if (parendNode.parentIds) {
body.parentIds = parendNode.parentIds + "," + String(body.parentId);
} else {
body.parentIds = String(body.parentId);
}
}
const ret = await DB.Depart.create(body);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function updateDepart(req, res, next) {
try {
let body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
if(body.parentId) {
let parendNode = await DB.Depart.findOne({ where: { id: body.parentId }, raw: true, attributes: ['parentIds'] });
if (!parendNode) {
return res.sendError(errorMessage.resourceNotFound);
}
if (parendNode.parentIds) {
body.parentIds = parendNode.parentIds + "," + String(body.parentId);
} else {
body.parentIds = String(body.parentId);
}
}
// sequelize 只有update 写时需要注意条件 不能为空
const ret = await DB.Depart.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listDepart(req, res, next) {
try {
let search = { where: { del: 0 } };
let page = req.body.page || 1;
let limit = req.body.pageSize || 10;
let offset = (page - 1) * limit;
if (req.body.name) {
search.where = {
[Op.or]: [
{ name: { [Op.like]: `%${req.body.name}%` } }
],
del: 0,
}
}
search.limit = limit;
search.offset = offset;
let ret = await DB.Depart.findAndCountAll(search);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function treeDepart(req, res, next) {
try {
let nodes = await DB.Depart.findAll({ where: { del: 0 }, raw: true });
let tree = utils.buildTree(nodes);
return res.sendData(tree);
} catch (error) {
next(error);
}
}
/**
*
* 删除菜单,则此菜单所有子菜单借删除
*/
async function deleteDepart(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
let curNode = await DB.Depart.findOne({ where: { id: req.body.id } });
if (!(curNode && curNode.id)) {
return res.sendError(errorMessage.resourceNotFound);
}
let parStr = curNode.parentIds ? `${curNode.parentIds},${curNode.id}` : curNode.id; //拼接父字符串查找所有的子
const ret = await DB.Depart.update(
{ del: 1 },
{
where: {
[Op.or]: [
{ parentIds: { [Op.startsWith]: parStr } }, //删除所有以自己为父节点得子节点
{ id: curNode.id } //删除自己
]
}
});
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function getDepart(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.Depart.findOne({ where: { id: req.body.id }, raw: true });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
module.exports = {
createDepart,
updateDepart,
deleteDepart,
listDepart,
treeDepart,
getDepart,
}
\ No newline at end of file
const ExcelJS = require('exceljs');
const _ = require('lodash');
const errorMessage = require('../utils/errorMessage');
const Path = require('path');
const fs = require('fs');
async function upload(req, res, next) {
try {
console.log(req.file, req.body);
// let nginxpath = _.last(String(req.file.path).split('/mnt/vdb1'));
let ret = await DB.File.create({
originalname: req.file.originalname,
mimetype: req.file.mimetype,
filename: req.file.filename,
path: req.file.path,
// nginxpath,
size: req.file.size,
});
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function batchUpload(req, res, next) {
try {
let ret = [];
for (let index = 0; index < req.files.length; index++) {
const element = req.files[index];
// let nginxpath = _.last(String(element.path).split('/mnt/vdb1'));
ret.push({
originalname: element.originalname,
mimetype: element.mimetype,
filename: element.filename,
path: element.path,
size: element.size,
// nginxpath,
})
}
let data = await DB.File.insertMany(ret);
res.sendData(data);
} catch (error) {
next(error);
}
}
/**
*
*/
async function downloadFileById(req, res, next) {
try {
let fileId = req.params.fileId;
let fileinfo = await DB.File.findOne({ where: {id: fileId}, raw: true });
if (!(fileinfo && fileinfo.id)) {
return res.sendError(errorMessage.resourceNotFound)
}
let {
originalname,
filename,
size,
mimetype,
url,
path,
nginxpath,
} = fileinfo;
//TODO:path处理
const filePath = Path.join(__dirname, '../../../', path);
if (!fs.existsSync(filePath)) {
return res.sendError(errorMessage.resourceNotFound)
}
// 3. 设置强制下载响应头
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(originalname)}"`);
// 4. 创建文件流并传输
const fileStream = fs.createReadStream(filePath);
fileStream.pipe(res);
// 错误处理
fileStream.on('error', (err) => {
console.error(`File stream error: ${err}`);
if (!res.headersSent) res.status(500).send('File streaming error');
});
} catch (error) {
next(error);
}
}
async function showFileById(req, res, next) {
try {
// ----------
let fileId = req.params.fileId;
let fileinfo = await DB.File.findOne({ where: {id: fileId}, raw: true });
if (!(fileinfo && fileinfo.id)) {
return res.sendError(errorMessage.resourceNotFound)
}
let {
originalname,
filename,
size,
mimetype,
url,
path,
nginxpath,
} = fileinfo;
//TODO:path处理
const filePath = Path.join(__dirname, '../../../', path);
if (!fs.existsSync(filePath)) {
return res.sendError(errorMessage.resourceNotFound)
}
// 3. 设置强制下载响应头
res.setHeader('Content-Type', mimetype);
res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(filename)}"`);
// 4. 创建文件流并传输
const fileStream = fs.createReadStream(filePath);
fileStream.pipe(res);
// 错误处理
fileStream.on('error', (err) => {
console.error(`File stream error: ${err}`);
if (!res.headersSent) res.status(500).send('File streaming error');
});
} catch (error) {
next(error);
}
}
module.exports = {
upload,
batchUpload,
downloadFileById,
showFileById,
}
\ No newline at end of file
const errorMessage = require("../utils/errorMessage");
const { Op } = require('sequelize');
async function createMenu(req, res, next) {
try {
const body = req.body;
if (body.parentId) {
//查父节点
let parendNode = await DB.Menu.findOne({ where: { id: body.parentId }, raw: true, attributes: ['parentIds'] });
if (!parendNode) {
return res.sendError(errorMessage.resourceNotFound);
}
if (parendNode.parentIds) {
body.parentIds = parendNode.parentIds + "," + String(body.parentId);
} else {
body.parentIds = String(body.parentId);
}
}
const ret = await DB.Menu.create(body);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function updateMenu(req, res, next) {
try {
let body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
if (body.parentId) {
//查父节点
let parendNode = await DB.Menu.findOne({ where: { id: body.parentId }, raw: true, attributes: ['parentIds'] });
if (!parendNode) {
return res.sendError(errorMessage.resourceNotFound);
}
if (parendNode.parentIds) {
body.parentIds = parendNode.parentIds + "," + String(body.parentId);
} else {
body.parentIds = String(body.parentId);
}
}
// sequelize 只有update 写时需要注意条件 不能为空
const ret = await DB.Menu.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listMenu(req, res, next) {
try {
let search = { where: { del: 0 } };
let page = req.body.page || 1;
let limit = req.body.pageSize || 10;
let offset = (page - 1) * limit;
if (req.body.name) {
search.where = {
[Op.or]: [
{ name: { [Op.like]: `%${req.body.name}%` } }
],
del: 0,
}
}
search.limit = limit;
search.offset = offset;
let ret = await DB.Menu.findAndCountAll(search);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function treeMenu(req, res, next) {
try {
let nodes = await DB.Menu.findAll({ where: { del: 0 }, raw: true });
let tree = utils.buildTree(nodes);
return res.sendData(tree);
} catch (error) {
next(error);
}
}
/**
*
* 删除菜单,则此菜单所有子菜单借删除
*/
async function deleteMenu(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
let curNode = await DB.Menu.findOne({ where: { id: req.body.id } });
if (!(curNode && curNode.id)) {
return res.sendError(errorMessage.resourceNotFound);
}
let parStr = curNode.parentIds ? `${curNode.parentIds},${curNode.id}` : curNode.id;
const ret = await DB.Menu.update(
{ del: 1 },
{
where: {
[Op.or]: [
{ parentIds: { [Op.startsWith]: parStr } },
{ id: curNode.id }
]
}
});
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function getMenu(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.Depart.findOne({ where: { id: req.body.id }, raw: true });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
module.exports = {
createMenu,
getMenu,
listMenu,
updateMenu,
deleteMenu,
treeMenu,
}
\ No newline at end of file
const errorMessage = require("../utils/errorMessage");
const { Op } = require("sequelize");
async function getMessageInfo(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const message = await DB.Message.findOne({
where: { id: req.body.id, del: 0 },
include: [
{
model: DB.User,
as: 'creatorInfo',
attributes: ['id', 'name', 'avatar']
}
]
});
message.alreadyRead = message.alreadyRead || [];
message.alreadyRead.push(req.user.id);
await message.save();
return res.sendData(message);
} catch (error) {
next(error);
}
}
async function deleteMessage(req, res, next) {
try {
if (req.body.id) {
await DB.Message.update(
{ del: 1 },
{ where: { id: req.body.id } }
);
return res.sendData();
}
if (req.body.ids && Array.isArray(req.body.ids)) {
await DB.Message.update(
{ del: 1 },
{ where: { id: { [Op.in]: req.body.ids } } }
);
return res.sendData();
}
} catch (error) {
next(error);
}
}
/**
* 获取信息列表
* @param {*} req
* @param {*} res
* @param {*} next
* @returns
*/
async function getUserMessages(req, res, next) {
try {
const messages = await DB.Message.findAll({
where: {
receivers: { [Op.contains]: [req.user.id] },
del: 0
},
include: [
{
model: DB.User,
as: 'creatorInfo',
attributes: ['id', 'name', 'avatar']
}
],
raw: true,
order: [['createdAt', 'DESC']],
});
let newRet = [];
for (let index = 0; index < messages.length; index++) {
const element = messages[index];
element.alreadyRead = element.alreadyRead || [];
element.isRead = false;
if (element.alreadyRead.includes(req.user.id)) {
element.isRead = true;
}
newRet.push(element);
}
return res.sendData(newRet);
}
catch (error) {
next(error)
}
}
async function getMesCount(req, res, next) {
try {
const count = await DB.Message.count({
where: {
receivers: { [Op.contains]: [req.user.id] },
del: 0,
alreadyRead: { [Op.not]: {[Op.contains]: [req.user.id]} }
}
});
return res.sendData({ count });
} catch (error) {
next(error);
}
}
module.exports = {
getUserMessages,
getMesCount,
getMessageInfo,
deleteMessage,
};
\ No newline at end of file
const errorMessage = require("../utils/errorMessage");
const { Op } = require('sequelize');
async function createPosition(req, res, next) {
try {
const body = req.body;
const ret = await DB.Position.create(body);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function updatePosition(req, res, next) {
try {
let body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
const ret = await DB.Position.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deletePosition(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.Position.update({ del: 1 }, { where: { id: req.body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listPosition(req, res, next) {
try {
let search = {where: {del: 0}};
let page = req.body.page || 1;
let limit = req.body.pageSize || 10;
let offset = (page - 1) * limit;
if (req.body.name) {
search.where = {
[Op.or]: [
{ name: { [Op.like]: `%${req.body.name}%` } }
],
del: 0,
}
}
search.limit = limit;
search.offset = offset;
let ret = await DB.Position.findAndCountAll(search);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
module.exports = {
createPosition,
listPosition,
deletePosition,
updatePosition,
}
\ No newline at end of file
This diff is collapsed.
const { buildTree } = require("../utils");
const errorMessage = require("../utils/errorMessage");
const { Op, where } = require('sequelize');
/**
* 资源库controller
*/
async function createResource(req, res, next) {
try {
const body = req.body;
// await DB.Resources.bulkCreate(
// [
// { "key": "k1a92f", "name": "公交车" },
// { "key": "u3b81x", "name": "地铁" },
// { "key": "p9c44m", "name": "高铁" },
// { "key": "n7d22t", "name": "出租车" },
// { "key": "q4e93z", "name": "轻轨" },
// { "key": "t6f81k", "name": "磁悬浮列车" },
// { "key": "r8g55w", "name": "轮渡" },
// { "key": "s2h19p", "name": "共享单车" },
// { "key": "w9j73v", "name": "电动车" },
// { "key": "a5k33q", "name": "自驾车" },
// { "key": "y1l87u", "name": "长途客车" },
// { "key": "d3m41b", "name": "飞机" },
// { "key": "f8n22h", "name": "直升机" },
// { "key": "c4p66r", "name": "城际铁路" },
// { "key": "m2q99s", "name": "轨道交通" },
// { "key": "j7r55d", "name": "大巴车" },
// { "key": "z3s13e", "name": "顺风车" },
// { "key": "e9t80y", "name": "三轮车" },
// { "key": "h5u28i", "name": "地面有轨电车" },
// { "key": "b6v71o", "name": "高速公路客运" }
// ]
// )
const ret = await DB.Resources.create(body);
return res.sendData(ret);
} catch (error) {
next(error);
}
};
async function updateResource(req, res, next) {
try {
const body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
const ret = await DB.Resources.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteResource(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.Resources.update({ del: 1 }, { where: { id: req.body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listResource(req, res, next) {
try {
let search = { where: { del: 0 } };
let page = req.body.page || 1;
let limit = req.body.pageSize || 10;
//翻页
let offset = (page - 1) * limit;
if (req.body.name) {
search.where = {
[Op.or]: [
//根据名字模糊搜索
{ name: { [Op.like]: `%${req.body.name}%` } }
],
del: 0,
}
}
search.limit = limit;
search.offset = offset;
//指定显示字段,空数组会报错
search.attributes = req.body.attributes || null;
let ret = await DB.Resources.findAndCountAll(search);
return res.sendData(ret);
} catch (error) {
next(error);
}
};
/**
* 资源库字段controller
*/
async function createResourceInfo(req, res, next) {
try {
const body = req.body;
if (!body.resourceId) {
return res.sendError(errorMessage.resourceNotFound)
}
const resource = await DB.Resources.findOne({ where: { id: body.resourceId } });
if (!resource) {
return res.sendError(errorMessage.resourceNotFound)
}
const ret = await DB.ResourcesInfo.create(body);
return res.sendData(ret);
} catch (error) {
next(error);
}
};
async function updateResourceInfo(req, res, next) {
try {
const body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
const ret = await DB.ResourcesInfo.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteResourceInfo(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.ResourcesInfo.update({ del: 1 }, { where: { id: req.body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listResourceInfo(req, res, next) {
try {
const body = req.body;
if (!body.resourceId) {
return res.sendError(errorMessage.resourceNotFound)
}
const resource = await DB.Resources.findOne({ where: { id: body.resourceId }, raw: true });
let search = {
where: {
[Op.and]: [
{ del: 0 },
{ resourceId: resource.id },
(req.body.name ? [{ value: { [Op.like]: `%${req.body.name}%` } }] : [])
]
},
raw: true
}
//指定显示字段,空数组会报错
// search.attributes = req.body.attributes || null;
let ret = await DB.ResourcesInfo.findAll(search);
console.log("ret", ret)
if (resource.type === 1) {
return res.sendData(ret);
} else if (resource.type === 2) {
//ret为json数据数组
const treeData = buildTree(ret);
return res.sendData(treeData);
}
} catch (error) {
next(error);
}
};
async function saveAllResourceInfo(req, res, next) {
try {
const { resourceId, data = [] } = req.body;
if (!resourceId || !Array.isArray(data)) {
return res.sendError(errorMessage.resourceNotFound);
}
const resource = await DB.Resources.findOne({
where: { id: resourceId },
raw: true
});
if (!resource) {
return res.sendError(errorMessage.resourceNotFound);
}
if (resource.type === 1) {
const existingRecords = await DB.ResourcesInfo.findAll({
where: { del: 0, resourceId: resourceId },
raw: true
});
console.log("existingRecords", existingRecords);
const existMap = new Map();
existingRecords.forEach(r => existMap.set(r.id, r));
const toCreate = [];
const toUpdate = [];
const incomingIds = new Set();
for (const item of data) {
if (item.resourceId != resourceId) {
console.log(item.value, "不属于当前资源,跳过");
continue;
}
console.log("每条aaa记录", item);
const record = {
...item,
//绑定ID
resourceId: Number(resourceId),
del: 0
};
//传进来有id,数据库能查到的为更新
if (item.id != null && existMap.has(item.id)) {
toUpdate.push(record);
incomingIds.add(item.id);
} else {
//没id的统一为新增
toCreate.push(record);
}
}
// 数据库中的id,但是没传进来的自动为删除
const toDeleteIds = existingRecords
.filter(r => !incomingIds.has(r.id))
.map(r => r.id);
console.log('本次新增:', toCreate.length);
console.log('本次更新:', toUpdate.length);
console.log('本次软删:', toDeleteIds);
if (toCreate.length > 0) {
await DB.ResourcesInfo.bulkCreate(toCreate);
}
if (toUpdate.length > 0) {
for (const item of toUpdate) {
await DB.ResourcesInfo.update(item, {
where: { id: item.id }
});
}
}
if (toDeleteIds.length > 0) {
await DB.ResourcesInfo.destroy(
{ del: 1 },
{ where: { id: toDeleteIds } }
);
}
const ret = await DB.ResourcesInfo.findAll({
where: { del: 0, resourceId: resourceId },
raw: true
});
return res.sendData(ret);
}
return res.sendData([]);
} catch (error) {
console.error('saveAllResourceInfo error:', error);
next(error);
}
}
module.exports = {
createResource,
updateResource,
deleteResource,
listResource,
createResourceInfo,
updateResourceInfo,
deleteResourceInfo,
listResourceInfo,
saveAllResourceInfo
}
\ No newline at end of file
const errorMessage = require("../utils/errorMessage");
const userModule = require('../module/userModule');
async function createRole(req, res, next) {
try {
const body = req.body;
const ret = await DB.Role.create(body);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function updateRole(req, res, next) {
try {
let body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
let role = await DB.Role.findOne({
where: {del: 0},
raw: true,
include: [
{
model: DB.Menu,
as: 'menus',
where: {del: 0},
attributes: ["id"],
through: { attributes: [] },
}
]
})
if(!(role && role.id)) {
return res.sendError(errorMessage.resourceNotFound);
}
if(body.menus) { //如果这里前端给的是树形结构 需要把它拆成平行,//TODO:
// body.menus = utils.disTree(body.menus);
await userModule.setRoleMenu(role.id, body.menus, role.menus);
delete body.menus;
}
// sequelize 只有update 写时需要注意条件 不能为空
const ret = await DB.Role.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteRole(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.Role.update({ del: 1 }, { where: { id: req.body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listRole(req, res, next) {
try {
let search = {where: {del: 0}};
let page = req.body.page || 1;
let limit = req.body.pageSize || 10;
let offset = (page - 1) * limit;
if (req.body.name) {
search.where = {
[Op.or]: [
{ name: { [Op.like]: `%${req.body.name}%` } }
],
del: 0,
}
}
search.limit = limit;
search.offset = offset;
let ret = await DB.Role.findAndCountAll(search);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function getRole(req, res, next) {
try {
if (!req.body.id) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.Role.findOne({
where: { id: req.body.id }, raw: true ,
include: [
{
model: DB.Menu,
as: 'menus',
where: {del: 0},
// attributes: ["id"],
through: { attributes: [] },
}
]
});
if(ret && ret.menus && ret.menus.length) {
ret.menus = utils.buildTree(ret.menus);
}
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function setRoleMenu(req, res, next) {
try {
const {roleId, menuIds} = req.body;
if(!roleId) {
return res.sendError(errorMessage.resourceNotFound);
}
const rolemenus = await DB.RoleMenu.findAll({where: {roleId: roleId}, raw: true});
await userModule.setRoleMenu(roleId, menuIds, rolemenus);
return res.sendData();
} catch (error) {
next(error);
}
}
module.exports = {
getRole,
createRole,
listRole,
updateRole,
deleteRole,
setRoleMenu,
}
\ No newline at end of file
/**
* 项目相关excel文件处理:
* 1. 下载模板(携带当前数据,若无数据则为空)
* 2. 上传文件导入数据 解析数据并存入数据库
* 3.
*/
const errorMessage = require("../utils/errorMessage");
async function getExcelTemplate(req, res, next) {
try {
let { tampName, projectId, startYear, endYear } = req.body;
const workbook = new ExcelJS.Workbook();
if (tampName === 'xmtzzjll') { // 项目投资资金流量表
if (!startYear || !endYear) {
errorMessage.paramsError.message = "当前模板开始年份和结束年份不能为空";
return res.sendError(errorMessage.paramsError);
}
// 1. 读取空模板文件
const inputFilePath = path.join(__dirname, '../public/templates/项目投资资金流量表.xlsx');
// 2. 处理excel 文件,动态生成表格
await workbook.xlsx.readFile(inputFilePath);
const worksheet = await workbook.getWorksheet(1);
// 2.1 处理表头
let count = endYear - startYear;
let columns = [];
for (let index = 0; index <= count; index++) {
columns.push({ name: Number(startYear + index) });
}
// 2.2 处理数据
let rows = Array(5).fill([]); // 5 是模板有5行
if (!projectId) {
let tzzjlls = await ProjectTzzjll.findAll({
where: { projectId: projectId, del: 0 },
raw: true,
});
tzzjlls = _.sortBy(tzzjlls, 'year');
rows = thvc(tzzjlls);
}
console.log(rows, "=============")
// 使用addTable创建表格
worksheet.addTable({
name: 'FinancialData',
ref: 'D3',
headerRow: true,
totalsRow: false,
style: {
theme: null,
showRowStripes: false,
showColumnStripes: false,
},
columns: columns,
rows: rows
});
worksheet.mergeCells(2, 3, 2, (3 + columns.length))
worksheet.mergeCells(1, 1, 1, (3 + columns.length))
const BLACK_BORDER = {
top: { style: 'thin', color: { argb: 'FF000000' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'thin', color: { argb: 'FF000000' } },
right: { style: 'thin', color: { argb: 'FF000000' } }
};
// 遍历所有单元格添加边框
worksheet.eachRow((row, rowNumber) => {
row.eachCell((cell, colNumber) => {
if (rowNumber >= 4 && rowNumber <= 8 && colNumber >= 4 && colNumber <= (3 + columns.length)) {
cell.numFmt = '#,##0.00'; //数字格式
}
cell.alignment = {
horizontal: 'center',
vertical: 'middle', //垂直居中
wrapText: true
};
cell.border = BLACK_BORDER; //边框
});
});
// 3. 将处理后的文件发送给前端
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', 'attachment; filename=' + encodeURIComponent('项目投资资金流量表.xlsx'));
const buffer = await workbook.xlsx.writeBuffer();
// 发送文件并结束响应
res.end(buffer);
}
else {
res.status(400).json({ message: '未知的模板名称' });
}
} catch (error) {
next(error);
}
}
//处理 项目投资资金流量表 以【数据项、年度】为【数据库表结构字段】 转化为excel行数据
function thvc(a) {
let xjlr = [], xjlc = [], sdsqjxjll = [], tzsds = [], sdshjxjll = [];
for (let index = 0; index < a.length; index++) {
const element = a[index];
xjlr.push(element.xjlr);
xjlc.push(element.xjlc);
sdsqjxjll.push(element.sdsqjxjll);
tzsds.push(element.tzsds);
sdshjxjll.push(element.sdshjxjll);
// year.push(element.year);
}
return [xjlr, xjlc, sdsqjxjll, tzsds, sdshjxjll];
}
async function importExcelTempData(req, res, next) {
try {
let { tampName, projectId } = req.body;
if (tampName == 'xmtzzjll') {
if (!projectId) {
errorMessage.paramsError.message = "项目ID不能为空";
return res.sendError(errorMessage.paramsError);
}
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.load(req.file.buffer);
const worksheet = await workbook.getWorksheet(1);
let years = [], data = [];
worksheet.eachRow((row, rowIndex) => {
if (rowIndex === 3) {
years = row.values.slice(4);
}
if (rowIndex > 3) {
data.push(row.values.slice(4));
}
});
const fieldMap = {
1: 'xjlr', // 现金流入
2: 'xjlc', // 现金流出
3: 'sdsqjxjll', // 所得税前净现金流量
4: 'tzsds', // 调整所得税
5: 'sdshjxjll' // 所得税后净现金流量
};
let retData = [];
years.map((year, yearIndex) => {
const yearData = { year };
for (let rowIndex = 1; rowIndex <= data.length; rowIndex++) {
const fieldKey = fieldMap[rowIndex];
if (fieldKey) {
const value = data[rowIndex - 1][yearIndex];
yearData[fieldKey] = parseFloat(value) || 0;
}
}
retData.push(yearData);
});
await ProjectTzzjll.destroy({
where: { projectId: projectId },
});
await ProjectTzzjll.bulkCreate(retData);
}
} catch (error) {
next(error)
}
}
module.exports = {
getExcelTemplate,
importExcelTempData,
}
\ No newline at end of file
const crypto = require('crypto'); const crypto = require('crypto');
const _ = require('lodash'); const _ = require('lodash');
const CryptoJS = require('crypto-js'); const CryptoJS = require('crypto-js');
const { Op } = require('sequelize');
const userModule = require('../module/userModule');
const errorMessage = require('../utils/errorMessage'); const errorMessage = require('../utils/errorMessage');
async function regist(req, res, next) { async function regist(req, res, next) {
try {
const { salt, passwordHash } = utils.saltHashPassword(req.body.password);
const ret = await DB.User.create({
...req.body,
salt,
password: passwordHash,
});
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function login(req, res, next) {
try {
if (req.body.encryptLogStr) {
//避免差异 选用跟前端一样的包
let encryptLogStr = CryptoJS.AES.decrypt(req.body.encryptLogStr, "GFG5w5AP0Ja2rNaa").toString(CryptoJS.enc.Utf8);
let encArr = encryptLogStr.split(",");
req.body.mobile = encArr[0].trim();
req.body.password = encArr[1];
}
const { mobile, password } = req.body;
let user = await DB.User.findOne({
where: { mobile, del: 0, enable: 0 },
include: [{
model: DB.Role,
as: 'roles',
// where: { del: 0 },
attributes: ["id", "name"],
through: { attributes: [] },
include: [{
model: DB.Menu,
as: 'menus',
// where: { del: 0 },
// attributes: ['id', 'name', 'parentId'],
through: { attributes: [] },
}]
},
{
model: DB.Depart,
as: 'departs',
// where: { del: 0 }, 当刚注册的用户 没有分配角色、部门时加上条件会查不到
attributes: ["id", "name"],
through: { attributes: [] },
}
]
});
// console.log('this is user login', user)
user = user.toJSON();
if (!user) {
return res.sendError(errorMessage.loginError);
}
//判断删除状态 ,暂时不加
const check = utils.checkUserPassword({
reqPw: password,
salt: user.salt,
userPw: user.password,
});
if (!check) {
return res.sendError(errorMessage.loginError)
}
// 生成一个串 返回前端
let token = crypto.randomUUID();
user.token = token.split('-').join("");
let userStr = JSON.stringify(user);
await ioRedis.set(`token:${user.token}`, userStr, 'EX', sysConfig.tokenEx);
user = _.omit(user, ['password', 'salt']);
//处理菜单
const roles = user.roles || [];
let newRoles = [], menus = [];
for (let index = 0; index < roles.length; index++) {
const element = roles[index];
menus = menus.concat(element.menus);
delete element.menus;
newRoles.push(element);
}
user.roles = newRoles || [];
user.menus = utils.buildTree(menus);
return res.sendData(user);
} catch (error) {
next(error);
}
}
/**
* 管理端功能
*/
async function createUser(req, res, next) {
try { try {
const body = req.body; const body = req.body;
const ret = await userModule.create(body); body.password = body.password || sysConfig.userDefaultPassword;
const { salt, passwordHash } = utils.saltHashPassword(req.body.password);
body.salt = salt;
body.password = passwordHash;
const ret = await DB.User.create(body);
if (!(ret && ret.id)) {
return res.sendError(errorMessage.databaseQueryError);
}
//处理部门 角色
body.departs = body.departs || [];
body.roles = body.roles || [];
let userDeparts = body.departs.map(o => { return { userId: ret.id, departId: o && o.id || o } });
let userRoles = body.roles.map(o => { return { userId: ret.id, roleId: o && o.id || o } });
await DB.UserDepart.bulkCreate(userDeparts);
await DB.UserRole.bulkCreate(userRoles);
return res.sendData(ret); return res.sendData(ret);
} catch (error) { } catch (error) {
next(error); next(error);
} }
} }
async function getUserInfo(req, res, next) {
try {
let query = {};
const { id, mobile } = req.body;
if (id) {
query.id = id;
}
if (mobile) {
query.mobile = mobile;
}
const ret = await DB.User.findOne({
where: query,
// raw: true,
attributes: { exclude: ['password', 'salt'] },
include: [{
model: DB.Role,
as: 'roles',
where: { del: 0 },
// attributes: ['id']
}]
});
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function updateUser(req, res, next) {
try {
let body = req.body;
if (!body.id) {
return res.sendError(errorMessage.resourceNotFound)
}
let user = await DB.User.findOne({
where: { id: body.id },
include: [
{
model: DB.Role,
as: 'roles',
where: { del: 0 },
attributes: ["id"],
through: { attributes: [] },
}, {
model: DB.Depart,
as: 'departs',
where: { del: 0 },
attributes: ["id"],
through: { attributes: [] },
}
],
raw: true,
});
if (!(user && user.id)) {
return res.sendError(errorMessage.resourceNotFound);
}
if (body.departs && body.departs.length) {
//跟现有情况对比 确定增删关系
const departIds = body.departs.map(o => { return o && o.id || o });
await userModule.setUserDepart(user.id, departIds, user.departs);
delete body.departs;
}
if (body.roles && body.roles.length) {
//跟现有情况对比 确定增删关系
const roleIds = body.roles.map(o => { return o && o.id || o });
await userModule.setUserRole(user.id, roleIds, user.roles);
delete body.roles;
}
const ret = await DB.User.update(body, { where: { id: body.id } });
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function listUser(req, res, next) {
try {
let search = { where: { del: 0 } };
let page = req.body.page || 1;
let limit = req.body.pageSize || 10;
let offset = (page - 1) * limit;
if (req.body.name) {
search.where = {
[Op.or]: [
{ name: { [Op.like]: `%${req.body.name}%` } },
{ mobile: { [Op.like]: `%${req.body.name}%` } }
],
del: 0,
}
}
search.limit = limit;
search.offset = offset;
search.attributes = req.body.attributes || { exclude: ['password', 'salt'] };
let ret = await DB.User.findAndCountAll(search);
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteUser(req, res, next) {
try {
const body = req.body;
const search = {};
if (body.id) {
search = { id: body.id };
}
if (body.mobile) {
search = { mobile: body.mobile }
}
if (_.isEmpty(search)) {
return res.sendError(errorMessage.resourceNotFound);
}
const ret = await DB.User.update({ del: 1 }, { where: search });//删除标记
return res.sendData(ret);
} catch (error) {
next(error);
}
}
async function setUserRole(req, res, next) {
try {
let { userId, roleIds } = req.body;
//1. 先查被设置用户 有什么角色
const roles = await DB.UserRole.findAll({ where: { userId: req.body.userId }, raw: true, attributes: ['roleId', 'userId'] });
await userModule.setUserRole(userId, roleIds, roles);
return res.sendData();
} catch (error) {
console.log(error)
next(error);
}
}
module.exports = { module.exports = {
regist regist,
login,
listUser,
createUser,
getUserInfo,
updateUser,
deleteUser,
setUserRole,
} }
\ No newline at end of file
// // 气象
// const httpRequest = require('../utils/httpRequest');
// const deviceModule = require('../module/deviceModule');
// const collectIPSModule = require('../module/collectIPSModule');
// const _ = require('lodash');
// const moment = require('moment');
// const ExcelJS = require('exceljs');
// const fs = require('fs');
// // exportExcel()
// async function exportExcel() {
// let info = await DB.ExcelRecord.findOne({ type: 2, status: 1, del: 0 });
// console.log(info);
// if (info && info._id && info.modleName) {
// let workbook = new ExcelJS.Workbook();
// let name = `${info._id}`
// let worksheet = workbook.addWorksheet(name);
// let columns = [];
// if (!_.isEmpty(DB[info.modleName] && DB[info.modleName].schema && DB[info.modleName].schema.obj)) {
// for (const key in DB[info.modleName].schema.obj) {
// const element = DB[info.modleName].schema.obj[key];
// if (element && element.comment) {
// // 有comment的导出,其他需要标注 不需要导出的用comment1
// columns.push({ header: element.comment, key });
// }
// }
// }
// console.log(columns.length, "-=-=-", name);
// if (columns.length > 0) {
// // TODO: 可以优化根据count翻页 暂时
// worksheet.columns = columns;
// let list = await DB[info.modleName].find(info.search || { del: 0 });
// for (let index = 0; index < list.length; index++) {
// const element = list[index];
// worksheet.addRow(element);
// }
// console.log("-----------------------------------",list.length,"---------------------------------------------")
// if (list.length > 0) {
// let path = sysConfig.file.storagePath + '/' + moment().format('YYYYMMDD');
// if (!fs.existsSync(path)) {
// fs.mkdirSync(path, { recursive: true });
// }
// let excelUrl = path + '/' + name + '.xlsx'
// // 1. 写入数据到存储位置
// await workbook.xlsx.writeFile(excelUrl);
// // 2. 创建文件信息
// let fileInfo = await DB.File.create({
// originalname: name + '.xlsx',
// mimetype: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
// filename: name + '.xlsx',
// path: excelUrl,
// nginxpath: _.last(String(path).split('/mnt/vdb1')),
// type: 2,
// });
// // 3. 更新任务结果
// await DB.ExcelRecord.findOneAndUpdate({_id: info._id}, {status: 2, excelUrl: fileInfo._id})
// } else {
// await DB.ExcelRecord.findOneAndUpdate({_id: info._id}, {status: 3});
// }
// }
// }
// // let workbook = new Excel.Workbook();
// // // 添加一个工作表
// // let worksheet = workbook.addWorksheet('我的工作表');
// // // 添加表头
// // worksheet.columns = [
// // { header: '姓名', key: 'name' },
// // { header: '年龄', key: 'age' },
// // { header: '职业', key: 'occupation' }
// // ];
// // // 添加数据行
// // worksheet.addRow({ name: '张三', age: 30, occupation: '软件工程师' });
// // worksheet.addRow({ name: '李四', age: 25, occupation: '产品经理' });
// // // 写入文件到磁盘
// // await workbook.xlsx.writeFile('我的Excel.xlsx');
// }
// module.exports = {
// exportExcel,
// }
...@@ -15,14 +15,12 @@ const config = require('../config'); ...@@ -15,14 +15,12 @@ const config = require('../config');
TODO:需要处理 多个server启动时,定时任务启动多次问题。 TODO:需要处理 多个server启动时,定时任务启动多次问题。
*/ */
const cron = () => { const cron = () => {
/*-----------------------------采集设备信息-------------------------------------*/ // if (sysConfig && sysConfig.cron && sysConfig.cron.excel) {
// 1 土壤温湿度、土壤氮磷钾, 2 土壤ph、土壤电导率, 3 气象站 // console.log("excel:", new Date());
// if (sysConfig && sysConfig.cron && sysConfig.cron.getDeviceList) {
// console.log("getDeviceList:", new Date()); // new nodeCron.schedule('1 */1 * * * *', async () => {
// // 每天10点30分 处理 1 30 10 * * * // console.log(new Date().getTime())
// // new nodeCron.schedule('1 30 10 * * *', async () => { // await excelCron.exportExcel();
// new nodeCron.schedule('1 * * * * *', async () => {
// await deviceCron.getDeviceList();
// }, { timezone: "Asia/Shanghai" }); // }, { timezone: "Asia/Shanghai" });
// } // }
......
// 模型初始化 // 模型初始化
const User = require("./model/user"); const User = require("./model/system/user");
const RequestLog = require("./model/requestLog"); const Role = require("./model/system/role");
const UserRole = require("./model/system/userRole");
const Menu = require("./model/system/menu");
const RoleMenu = require("./model/system/roleMenu");
const Depart = require("./model/system/depart");
const UserDepart = require("./model/system/userDepart");
const RequestLog = require("./model/system/requestLog");
const File = require("./model/system/file");
const Position = require("./model/system/position");
const Message = require("./model/system/message");
const FlowRecord = require("./model/system/flowRecord");
// 业务模型
const Project = require("./model/jt/project");
const Resources = require("./model/jt/resources");
const ResourcesInfo = require("./model/jt/resourcesInfo");
const ProjectBjtj = require("./model/jt/projectBjtj");
const ProjectCwpjzb = require("./model/jt/projectCwpjzb");
const ProjectFile = require("./model/jt/projectFile");
const ProjectFxgl = require("./model/jt/projectFxgl");
const ProjectGdxx = require("./model/jt/projectGdxx");
const ProjectJczt = require("./model/jt/projectJczt");
const ProjectJsgm = require("./model/jt/projectJsgm");
const ProjectLcbjd = require("./model/jt/projectLcbjd");
const ProjectSpyj = require("./model/jt/projectSpyj");
const ProjectTzzjll = require("./model/jt/projectTzzjll");
const ProjectTzzt = require("./model/jt/projectTzzt");
const ProjectXmtzze = require("./model/jt/projectXmtzze");
/**
* 业务表
*/
global.DB = { global.DB = {
User, User,
RequestLog RequestLog,
Role,
UserRole,
Menu,
RoleMenu,
Depart,
UserDepart,
File,
Position,
Project,
Resources,
ResourcesInfo,
ProjectBjtj,
ProjectFile,
ProjectGdxx,
ProjectJsgm,
ProjectSpyj,
ProjectCwpjzb,
ProjectJczt,
ProjectFxgl,
ProjectLcbjd,
ProjectTzzjll,
ProjectTzzt,
ProjectXmtzze,
Message,
FlowRecord,
} }
...@@ -16,6 +73,112 @@ global.DB = { ...@@ -16,6 +73,112 @@ global.DB = {
/** /**
* 关联关系定义 * 关联关系定义
*/ */
/**用户-请求日志 1:n */
User.hasMany(RequestLog, { foreignKey: 'userId' }); User.hasMany(RequestLog, { foreignKey: 'userId' });
RequestLog.belongsTo(User, { foreignKey: 'userId' }); RequestLog.belongsTo(User, { foreignKey: 'userId' });
/**用户-角色 n:n */
User.belongsToMany(Role, {
through: 'system_user_role', // 中间表名
foreignKey: 'userId', // 用户ID外键
otherKey: 'roleId', // 角色ID外键
as: 'roles',
});
Role.belongsToMany(User, {
through: 'system_user_role',
foreignKey: 'roleId',
otherKey: 'userId',
as: 'users'
});
/**角色-菜单 n:n */
Role.belongsToMany(Menu, {
through: 'system_role_menu',
foreignKey: 'roleId',
otherKey: 'menuId',
as: 'menus'
});
Menu.belongsToMany(Role, {
through: 'system_role_menu',
foreignKey: 'menuId',
otherKey: 'roleId'
});
/**用户-部门 n:n */
User.belongsToMany(Depart, {
through: 'system_user_depart', // 中间表名
foreignKey: 'userId', // 用户ID外键
otherKey: 'departId', // 角色ID外键
as: 'departs',
});
Depart.belongsToMany(User, {
through: 'system_user_depart',
foreignKey: 'departId',
otherKey: 'userId',
as: 'users'
});
/**用户-职位 n:n */
User.belongsToMany(Position, {
through: 'system_user_position', // 中间表名
foreignKey: 'userId', // 用户ID外键
otherKey: 'posiId', // 角色ID外键
as: 'positions',
});
Position.belongsToMany(User, {
through: 'system_user_position',
foreignKey: 'posiId',
otherKey: 'userId',
as: 'users'
});
/**用户-项目 1:n */
User.hasMany(Project, { foreignKey: 'projectCreator', as: 'createdProjects' });
Project.belongsTo(User, { foreignKey: 'projectCreator', as: 'creator' });
/**项目-资源信息 1:n */
Resources.hasMany(ResourcesInfo, { foreignKey: 'resourceId', as: 'resourcesInfos' });
ResourcesInfo.belongsTo(Resources, { foreignKey: 'resourceId' });
/**项目-核心边界条件 1:n */
Project.hasMany(ProjectBjtj, { foreignKey: 'projectId', as: 'projectBjtjs' });
ProjectBjtj.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-财务评价指标 1:n */
Project.hasMany(ProjectCwpjzb, { foreignKey: 'projectId', as: 'projectCwpjzbs' });
ProjectCwpjzb.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-项目附件 1:n */
Project.belongsToMany(File, { through: 'jt_project_file', foreignKey: 'projectId', as: 'files', otherKey: 'fileId' });
File.belongsToMany(Project, { through: 'jt_project_file', foreignKey: 'fileId', otherKey: 'projectId', as: 'pros' });
/**项目-风险管理 1:n */
Project.hasMany(ProjectFxgl, { foreignKey: 'projectId', as: 'projectFxgls' });
ProjectFxgl.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-股东信息 1:n */
Project.hasMany(ProjectGdxx, { foreignKey: 'projectId', as: 'projectGdxxs' });
ProjectGdxx.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-决策主体审核情况 1:n */
Project.hasMany(ProjectJczt, { foreignKey: 'projectId', as: 'projectJczts' });
ProjectJczt.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-建设规模 1:n */
Project.hasMany(ProjectJsgm, { foreignKey: 'projectId', as: 'projectJsgms' });
ProjectJsgm.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-里程碑节点 1:n */
Project.hasMany(ProjectLcbjd, { foreignKey: 'projectId', as: 'projectLcbjds' });
ProjectLcbjd.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-审批意见 1:n */
Project.hasMany(ProjectSpyj, { foreignKey: 'projectId', as: 'projectSpyjs' });
ProjectSpyj.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-项目投资资金流量 1:n */
Project.hasMany(ProjectTzzjll, { foreignKey: 'projectId', as: 'projectTzzjlls' });
ProjectTzzjll.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-投资主体审核情况 1:n */
Project.hasMany(ProjectTzzt, { foreignKey: 'projectId', as: 'projectTzzts' });
ProjectTzzt.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-项目投资总额 1:n */
Project.hasMany(ProjectXmtzze, { foreignKey: 'projectId', as: 'projectXmtzzes' });
ProjectXmtzze.belongsTo(Project, { foreignKey: 'projectId' });
/**项目-项目流转记录 */
Project.hasMany(FlowRecord, { foreignKey: 'projectId', as: 'flowRecords' });
FlowRecord.belongsTo(Project, { foreignKey: 'projectId' });
\ No newline at end of file
// db.js // db.js
const { Sequelize } = require('sequelize'); const { Sequelize } = require('sequelize');
const config = require('config');
const mysqlConfig = config.get('mysql');
const { database, username, password, host } = mysqlConfig
// 创建 Sequelize 实例,连接数据库 // 创建 Sequelize 实例,连接数据库
const sequelize = new Sequelize(database, username, password || '123456', { const sequelize = new Sequelize(sysConfig.mysql.database || 'gzbjt', sysConfig.mysql.username || 'root', sysConfig.mysql.password ||'123456', {
host: host || '127.0.0.1', host: sysConfig.mysql.host || 'localhost',
dialect: 'mysql', dialect: 'mysql',
logging: console.log, // 显示日志(可选) logging: false, // 显示日志(可选)
pool: { pool: {
max: 5, // 连接池最大连接数 max: 5, // 连接池最大连接数
min: 0, min: 0,
......
This diff is collapsed.
This diff is collapsed.
1. 项目提交(项目公司、投管) 只能靠角色
1.1 项目公司新建项目人员---项目公司项目审批人员 --- 投管项目审批人员
项目公司人员 -- 看见本公司所有项目
投管项目审批人员 -- 看见所有项目公司人员
1.2 投管新建项目 --- 投管
同步发起 一个startFlow 流程记录 发起人 发起时间 项目状态(待审批-已审批)
\ No newline at end of file
This diff is collapsed.
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
const Project = require('./project');
// 核心边界条件
const projectBjtj = sequelize.define('projectBjtj', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
type: {
type: DataTypes.STRING,
comment: "业务类型"
},
dwgczjSz: {
type: DataTypes.DECIMAL(20, 4),
comment: "单位工程造价数值"
},
dwgczjDw: {
type: DataTypes.STRING,
comment: "单位工程造价单位"
},
xsfwnlSz: {
type: DataTypes.DECIMAL(20, 4),
comment: "销售服务能力数值"
},
xsfwnlDw: {
type: DataTypes.STRING,
comment: "销售服务能力单位"
},
njfhlSz: {
type: DataTypes.DECIMAL(20, 4),
comment: "年均负荷率数值"
},
njfhlDw: {
type: DataTypes.STRING,
comment: "年均负荷率单位"
},
dwscfwzcbSz: {
type: DataTypes.DECIMAL(20, 4),
comment: "单位生产服务总成本数值"
},
dwscfwzcbDw: {
type: DataTypes.STRING,
comment: "单位生产服务总成本单位"
},
dwsjSz: {
type: DataTypes.DECIMAL(20, 4),
comment: "单位售价(含税)数值"
},
dwsjDw: {
type: DataTypes.STRING,
comment: "单位售价(含税)单位",
},
ykphdlx: {
type: DataTypes.STRING,
comment: "盈亏平衡点类型",
},
ykphdsz: {
type: DataTypes.DECIMAL(20, 4),
comment: "盈亏平衡点数值"
},
ykphddw: {
type: DataTypes.STRING,
comment: "盈亏平衡点单位"
},
bcsm: {
type: DataTypes.STRING,
comment: "核心边界条件补充说明"
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
references: {
model: Project, // 关联的表名
key: 'id', // 关联的字段
}
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_bjtj', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
projectBjtj.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('projectBjtj 表同步成功');
});
module.exports = projectBjtj;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
// 财务评价指标
const projectCwpjbjtj = sequelize.define('projectCwpjbjtj', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
bjtj: {
type: DataTypes.STRING,
comment: "指标名称"
},
jc: {
type: DataTypes.STRING,
comment: "决策"
},
xz: {
type: DataTypes.STRING,
comment: "现状"
},
zycysm: {
type: DataTypes.TEXT,
comment: "主要差异说明",
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
}, {
tableName: 'jt_project_cwpjbjtj', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
projectCwpjbjtj.sync({
// force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('projectCwpjbjtj 表同步成功');
});
module.exports = projectCwpjbjtj;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
// 财务评价指标
const projectCwpjzb = sequelize.define('projectCwpjzb', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
comment: "指标名称"
},
num: {
type: DataTypes.DECIMAL(20, 4),
comment: "数量"
},
unit: {
type: DataTypes.STRING,
comment: "单位"
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
}, {
tableName: 'jt_project_cwpjzb', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
projectCwpjzb.sync({
// force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('projectCwpjzb 表同步成功');
});
module.exports = projectCwpjzb;
\ No newline at end of file
// models/User.js
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
const File = require('../system/file');
const Project = require('./project');
const ProjectFile = sequelize.define('ProjectFile', {
// 定义字段
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
fileId: {
type: DataTypes.INTEGER,
references: { model: File, key: 'id' }
},
projectId: {
type: DataTypes.INTEGER,
references: { model: Project, key: 'id' }
},
proFieldKey: {
type: DataTypes.STRING, //项目表中文件字段key
}
}, {
tableName: 'jt_project_file', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectFile.sync({
force: false, //
// force: true //会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectFile 表同步成功');
});
module.exports = ProjectFile;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
// 风险管理
const ProjectFxgl = sequelize.define('ProjectFxgl', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
fxlb: {
type: DataTypes.STRING,
comment: "风险类别"
},
fxms: {
type: DataTypes.TEXT,
comment: "风险描述"
},
ydcs: {
type: DataTypes.TEXT,
comment: "应对措施"
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_fxgl', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectFxgl.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectFxgl 表同步成功');
});
module.exports = ProjectFxgl;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
// 股东信息
const ProjectGdxx = sequelize.define('ProjectGdxx', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
gdlx: {
type: DataTypes.STRING,
comment: "股东类型"
},
gdmc: {
type: DataTypes.STRING,
comment: "股东名称"
},
cgbl: {
type: DataTypes.DECIMAL(5, 2),
comment: "持股比例(%)"
},
cze: {
type: DataTypes.DECIMAL(20, 4),
comment: "出资额(万元)"
},
yjzczb: {
type: DataTypes.DECIMAL(20, 4),
comment: "应缴注册资本(万元)"
},
ycxmzbj: {
type: DataTypes.DECIMAL(20, 4),
comment: "应出项目资本金(万元)"
},
hzfqk: {
type: DataTypes.TEXT,
comment: "合作方情况"
},
bz: {
type: DataTypes.TEXT,
comment: "备注"
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_gdxx', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectGdxx.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectGdxx 表同步成功');
});
module.exports = ProjectGdxx;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
//决策主体审核情况
const ProjectJczt = sequelize.define('ProjectJczt', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
hylx: { type: DataTypes.STRING, allowNull: true, comment: "会议类型" },
hylx: { type: DataTypes.STRING, allowNull: true, comment: "会议名称" },
jc: { type: DataTypes.STRING, allowNull: true, comment: "届次" },
zkrq: { type: DataTypes.DATE, allowNull: true, comment: "召开日期" },
jl: { type: DataTypes.STRING, allowNull: true, comment: "结论" },
qtsm: { type: DataTypes.TEXT, allowNull: true, comment: "决策结论" },
qtsm: { type: DataTypes.TEXT, allowNull: true, comment: "其他说明" },
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_jczt', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectJczt.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectJczt 表同步成功');
});
module.exports = ProjectJczt;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
// 建设规模
const ProjectJsgm = sequelize.define('ProjectJsgm', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
comment: "指标名称"
},
num: {
type: DataTypes.DECIMAL(20, 4),
comment: "数量"
},
unit: {
type: DataTypes.STRING,
comment: "单位"
},
bcsm: {
type: DataTypes.STRING,
comment: "补充说明"
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_jsgm', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectJsgm.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectJsgm 表同步成功');
});
module.exports = ProjectJsgm;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
const File = require('../system/file');
// yjlx: { type: DataTypes.STRING, allowNull: true, comment: "意见类型" },
// pfyj: { type: DataTypes.STRING, allowNull: true, comment: "批复意见" },
// pfyjsj: { type: DataTypes.DATE, allowNull: true, comment: "批复意见时间" },
// zxhf: { type: DataTypes.STRING, allowNull: true, comment: "执行回复" },
// zxhfsj: { type: DataTypes.DATE, allowNull: true, comment: "执行回复时间" },
// zxhffj: { type: DataTypes.STRING, allowNull: true, comment: "执行回复附件" },
// wlsqksm: { type: DataTypes.STRING, allowNull: true, comment: "未落实情况说明" },
//里程碑节点
const ProjectLcbjd = sequelize.define('ProjectLcbjd', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
lcbjdmc: {
type: DataTypes.STRING,
comment: "里程碑节点名称"
},
jdwcms: {
type: DataTypes.TEXT,
comment: "节点完成描述"
},
yjwcsj: {
type: DataTypes.DATE,
comment: "预计完成时间"
},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_lcbjd', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectLcbjd.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectLcbjd 表同步成功');
});
module.exports = ProjectLcbjd;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
const File = require('../system/file');
// yjlx: { type: DataTypes.STRING, allowNull: true, comment: "意见类型" },
// pfyj: { type: DataTypes.STRING, allowNull: true, comment: "批复意见" },
// pfyjsj: { type: DataTypes.DATE, allowNull: true, comment: "批复意见时间" },
// zxhf: { type: DataTypes.STRING, allowNull: true, comment: "执行回复" },
// zxhfsj: { type: DataTypes.DATE, allowNull: true, comment: "执行回复时间" },
// zxhffj: { type: DataTypes.STRING, allowNull: true, comment: "执行回复附件" },
// wlsqksm: { type: DataTypes.STRING, allowNull: true, comment: "未落实情况说明" },
// 审批意见
const ProjectSpyj = sequelize.define('ProjectSpyj', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
lx: {
type: DataTypes.STRING,
comment: "指标名称"
},
pfyj: {
type: DataTypes.TEXT,
comment: "批复意见"
},
pfyjsj: {
type: DataTypes.DATE,
comment: "批复意见时间"
},
zxhf: { type: DataTypes.TEXT, allowNull: true, comment: "执行回复" },
zxhfsj: { type: DataTypes.DATE, allowNull: true, comment: "执行回复时间" },
zxhffj: { type: DataTypes.INTEGER, references: {
model: File,
key: 'id'
}, allowNull: true, comment: "执行回复附件" },
wlsqksm: { type: DataTypes.TEXT, allowNull: true, comment: "未落实情况说明" },
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_spyj', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectSpyj.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectSpyj 表同步成功');
});
module.exports = ProjectSpyj;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
//投资收益指标变化对比表
const ProjectTzsyzb = sequelize.define('ProjectTzsyzb', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
pjzb:{ type: DataTypes.STRING, allowNull: true, comment: "评价指标" },
jczb:{ type: DataTypes.STRING, comment: '决策指标'},
xzzb:{ type: DataTypes.STRING, comment: '现状指标'},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_tzsyzb', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectTzsyzb.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectTzsyzb 表同步成功');
});
module.exports = ProjectTzsyzb;
\ No newline at end of file
const { DataTypes } = require('sequelize');
const sequelize = require('../index');
//项目投资资金流量表-excel
const ProjectTzzjll = sequelize.define('ProjectTzzjll', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
xjlr: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "现金流入" },
xjlc: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "现金流出" },
sdsqjxjll: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "所得税前净现金流量" },
tzsds: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "调整所得税" },
sdshjxjll: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "所得税后净现金流量" },
year: { type: DataTypes.STRING, allowNull: true, comment: "年份"},
projectId: {
type: DataTypes.INTEGER,
comment: "所属项目ID",
},
del: {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: "0 正常 1 删除"
},
}, {
tableName: 'jt_project_tzzjll', // 指定表名(如果与模型名不同)
timestamps: true, // 是否自动添加 createdAt 和 updatedAt 字段(覆盖全局设置)
});
// 同步模型到数据库(创建表)
ProjectTzzjll.sync({
force: false,
// force: true ,//会删除已存在表并重新创建
// alter: true
})
.then(() => {
console.log('ProjectTzzjll 表同步成功');
});
module.exports = ProjectTzzjll;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -5,7 +5,7 @@ async function createRequestLog(params) { ...@@ -5,7 +5,7 @@ async function createRequestLog(params) {
return DB.RequestLog.create(params); return DB.RequestLog.create(params);
} }
async function updateRequestLog(params) { async function updateRequestLog(params) {
return DB.RequestLog.update(params, {where: {reqId: params.reqId}}); return DB.RequestLog.update(params, {where: {reqid: params.reqid}});
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment