明树Git Lab

Commit 922a499d authored by Administrator's avatar Administrator

Merge branch 'master' into 'dev'

# Conflicts:
#   controller/userController.js
parents b4c13eba d8d782be
const _ = require('lodash'); function flattenTree(forest) {
let a = [ const result = [];
{
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];
}
}
/**
* 递归处理节点
* @param {Object} node - 当前节点
* @param {string|null} parentId - 父节点ID
*/
function traverse(node, parentId) {
// 创建节点副本避免修改原数据
const nodeCopy = { ...node };
function reverseTransform(transformedData) { // 添加parentId属性
// 获取第一个字段的数组长度作为对象数量 nodeCopy.parentId = parentId;
const field = Object.keys(transformedData)[0];
const itemCount = transformedData[field].length;
const result = []; // 移除children属性(使用正确拼写)
delete nodeCopy.children;
// 遍历每个索引位置构建对象 // 添加当前节点到结果集
for (let i = 0; i < itemCount; i++) { result.push(nodeCopy);
const item = {};
// 为每个字段赋值 // 处理子节点(兼容chilrden拼写错误)
for (const key in transformedData) { const children = node.chilrden || node.children || [];
if (transformedData.hasOwnProperty(key)) { for (const child of children) {
item[key] = transformedData[key][i]; traverse(child, node.id);
} }
} }
result.push(item); // 遍历森林中的每棵树
for (const tree of forest) {
traverse(tree, null); // 根节点parentId为null
} }
return result; return result;
} }
// 使用示例 // 扩展测试:包含额外字段和标准children字段
const transformed = { const complexForest = [
xjlr: [100, 100, 101, 1003, 1004], {
xjlc: [200, 200, 201, 2003, 2004], id: 'A',
sdsqjxjll: [300, 300, 301, 3003, 3004], name: 'Root A',
tzsds: [400, 400, 401, 4003, 4004], chilrden: [
sdshjxjll: [500, 500, 501, 5003, 5004] { id: 'A1', value: 100 },
}; { id: 'A2', value: 200, children: [{ id: 'A2a' }] }
]
// console.log(reverseTransform(transformed)); },
{
// console.log(thvc(a)); id: 'B',
name: 'Root B',
children: [{ id: 'B1' }]
// { }
// xh: String, ];
// sjx: String,
console.log(flattenTree(complexForest));
// } /* 输出:
// { [
// year: [] { id: 'A', name: 'Root A', parentId: null },
// } { id: 'A1', value: 100, parentId: 'A' },
\ No newline at end of file { id: 'A2', value: 200, parentId: 'A' },
{ id: 'A2a', parentId: 'A2' },
{ id: 'B', name: 'Root B', parentId: null },
{ id: 'B1', parentId: 'B' }
]
*/
\ No newline at end of file
...@@ -13,6 +13,7 @@ async function createResource(req, res, next) { ...@@ -13,6 +13,7 @@ async function createResource(req, res, next) {
ret = ret.toJSON(); ret = ret.toJSON();
console.log(ret); console.log(ret);
if (body.resourceInfos && body.resourceInfos.length && ret.id) { if (body.resourceInfos && body.resourceInfos.length && ret.id) {
if(type == 1){
let ris = []; let ris = [];
for (let index = 0; index < body.resourceInfos.length; index++) { for (let index = 0; index < body.resourceInfos.length; index++) {
const element = body.resourceInfos[index]; const element = body.resourceInfos[index];
...@@ -21,6 +22,17 @@ async function createResource(req, res, next) { ...@@ -21,6 +22,17 @@ async function createResource(req, res, next) {
} }
console.log(ris, "===") console.log(ris, "===")
await DB.ResourcesInfo.bulkCreate(ris); await DB.ResourcesInfo.bulkCreate(ris);
} else if(type == 2) {
//树结构
let ris = [];
let data = utils.flattenTreeIterative(body.resourceInfos);
for (let index = 0; index < data.length; index++) {
const element = data[index];
element.resourceId = ret.id;
ris.push(element);
}
await DB.ResourcesInfo.bulkCreate(ris);
}
} }
return res.sendData(ret); return res.sendData(ret);
} catch (error) { } catch (error) {
...@@ -158,7 +170,13 @@ async function listResourceInfo(req, res, next) { ...@@ -158,7 +170,13 @@ async function listResourceInfo(req, res, next) {
} }
}; };
/**
* 这个接口有点问题,只能处理平行数据,数据
* @param {*} req
* @param {*} res
* @param {*} next
* @returns
*/
async function saveAllResourceInfo(req, res, next) { async function saveAllResourceInfo(req, res, next) {
try { try {
let { resourceId, data = [] } = req.body; let { resourceId, data = [] } = req.body;
...@@ -175,9 +193,6 @@ async function saveAllResourceInfo(req, res, next) { ...@@ -175,9 +193,6 @@ async function saveAllResourceInfo(req, res, next) {
if (!resource) { if (!resource) {
return res.sendError(errorMessage.resourceNotFound); return res.sendError(errorMessage.resourceNotFound);
} }
if (resource && resource.type == 2) {
data = utils.disTree(data)
}
let toCreate = [], toKeep = []; let toCreate = [], toKeep = [];
if (data.length) { if (data.length) {
for (let index = 0; index < data.length; index++) { for (let index = 0; index < data.length; index++) {
......
...@@ -202,26 +202,27 @@ async function updateUser(req, res, next) { ...@@ -202,26 +202,27 @@ async function updateUser(req, res, next) {
], ],
raw: true, raw: true,
}); });
console.log(user)
if (!(user && user.id)) { if (!(user && user.id)) {
return res.sendError(errorMessage.resourceNotFound); return res.sendError(errorMessage.resourceNotFound);
} }
if (body.departs && body.departs.length) { if (body.departs && body.departs.length) {
//跟现有情况对比 确定增删关系 //跟现有情况对比 确定增删关系
const departIds = body.departs.map(o => { return o && o.id || o }); const departIds = body.departs.map(o => { return o && o.id || o });
await userModule.setUserDepart(user.id, departIds, user.departs); await userModule.setUserDepart(user.id, departIds, user.departs || []);
console.log('user.departs',user.departs); console.log('user.departs',user.departs);
delete body.departs; delete body.departs;
} }
if (body.roles && body.roles.length) { if (body.roles && body.roles.length) {
//跟现有情况对比 确定增删关系 //跟现有情况对比 确定增删关系
const roleIds = body.roles.map(o => { return o && o.id || o }); const roleIds = body.roles.map(o => { return o && o.id || o });
await userModule.setUserRole(user.id, roleIds, user.roles); await userModule.setUserRole(user.id, roleIds, user.roles || []);
delete body.roles; delete body.roles;
} }
if (body.positions && body.positions.length) { if (body.positions && body.positions.length) {
//跟现有情况对比 确定增删关系 //跟现有情况对比 确定增删关系
const positionIds = body.positions.map(o => { return o && o.id || o }); const positionIds = body.positions.map(o => { return o && o.id || o });
await userModule.setUserPosition(user.id, positionIds, user.positions); await userModule.setUserPosition(user.id, positionIds, user.positions || []);
delete body.roles; delete body.roles;
} }
const ret = await DB.User.update(body, { where: { id: body.id } }); const ret = await DB.User.update(body, { where: { id: body.id } });
...@@ -265,6 +266,8 @@ async function listUser(req, res, next) { ...@@ -265,6 +266,8 @@ async function listUser(req, res, next) {
through: { attributes: [] }, through: { attributes: [] },
} }
]; ];
search.distinct = true, // ✅ 关键:去重
search.col = 'id'
search.attributes = req.body.attributes || { exclude: ['password', 'salt'] }; search.attributes = req.body.attributes || { exclude: ['password', 'salt'] };
let ret = await DB.User.findAndCountAll(search); let ret = await DB.User.findAndCountAll(search);
return res.sendData(ret); return res.sendData(ret);
......
...@@ -23,7 +23,7 @@ const Project = sequelize.define('Project', { ...@@ -23,7 +23,7 @@ const Project = sequelize.define('Project', {
}, },
projectLiuZhuanType: { projectLiuZhuanType: {
type: DataTypes.STRING, type: DataTypes.STRING,
comment: "项目流转状态 1. 草稿、3 待初审、1初审退回、5待终审、1终审退回、7待立项审批、立项审批退回、已立项、已暂停、已结束等", comment: "项目流转状态 1. 待初审、3 待初审、1初审退回、5待终审、1终审退回、7待立项审批、立项审批退回、已立项、已暂停、已结束等",
}, },
/** /**
* 项目基本信息 * 项目基本信息
...@@ -99,34 +99,34 @@ const Project = sequelize.define('Project', { ...@@ -99,34 +99,34 @@ const Project = sequelize.define('Project', {
projectName: { type: DataTypes.STRING, allowNull: true, comment: "项目名称" }, projectName: { type: DataTypes.STRING, allowNull: true, comment: "项目名称" },
projectCode: { type: DataTypes.STRING, allowNull: true, comment: "项目编号" }, projectCode: { type: DataTypes.STRING, allowNull: true, comment: "项目编号" },
cym: { type: DataTypes.STRING, allowNull: true, comment: "曾用名" }, cym: { type: DataTypes.STRING, allowNull: true, comment: "曾用名" },
sfzjc: { type: DataTypes.INTEGER, allowNull: true, comment: "是否再决策" }, // 1是 2 否 sfzjc: { type: DataTypes.INTEGER, allowNull: true, comment: "是否再决策", zjType: 'xiala', zjKey: 'sf' }, // 1是 2 否
projectForeignName: { type: DataTypes.STRING, allowNull: true, comment: "项目外文名称" }, projectForeignName: { type: DataTypes.STRING, allowNull: true, comment: "项目外文名称" },
sfnjlhtxm: { type: DataTypes.INTEGER, allowNull: true, comment: "是否能建联合体项目" }, // 1是 2 否 sfnjlhtxm: { type: DataTypes.INTEGER, allowNull: true, comment: "是否能建联合体项目" , zjType: 'xiala', zjKey: 'sf'}, // 1是 2 否
applicationUnit: { type: DataTypes.STRING, allowNull: true, comment: "申报单位" }, applicationUnit: { type: DataTypes.STRING, allowNull: true, comment: "申报单位" },
zyfzy: { type: DataTypes.STRING, allowNull: true, comment: "主业/非主业" }, //TODO:下拉 zyfzy: { type: DataTypes.STRING, allowNull: true, comment: "主业/非主业" , zjType: 'xiala'}, //TODO:下拉
zsqy: { type: DataTypes.STRING, allowNull: true, comment: "直属企业" }, zsqy: { type: DataTypes.STRING, allowNull: true, comment: "直属企业" },
sfnjzdhzytz: { type: DataTypes.INTEGER, allowNull: true, comment: "是否能建重大或重要投资" }, sfnjzdhzytz: { type: DataTypes.INTEGER, allowNull: true, comment: "是否能建重大或重要投资" , zjType: 'xiala', zjKey: 'sf'},
sfzzjc: { type: DataTypes.INTEGER, allowNull: true, comment: "是否自主决策" }, sfzzjc: { type: DataTypes.INTEGER, allowNull: true, comment: "是否自主决策" },
cwbblx: { type: DataTypes.STRING, allowNull: true, comment: "财务报表类型" }, //TODO:下拉 cwbblx: { type: DataTypes.STRING, allowNull: true, comment: "财务报表类型" , zjType: 'xiala'}, //TODO:下拉
zfsphzbajb: { type: DataTypes.STRING, allowNull: true, comment: "政府审批(核准、备案)级别" }, //TODO:下拉 zfsphzbajb: { type: DataTypes.STRING, allowNull: true, comment: "政府审批(核准、备案)级别" , zjType: 'xiala'}, //TODO:下拉
sflxbqyscx: { type: DataTypes.INTEGER, allowNull: true, comment: "是否履行标前预审程序" }, sflxbqyscx: { type: DataTypes.INTEGER, allowNull: true, comment: "是否履行标前预审程序" , zjType: 'xiala', zjKey: 'sf'},
xmztz: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "项目总投资" }, xmztz: { type: DataTypes.DECIMAL(19, 8), allowNull: true, comment: "项目总投资" },
glzt: { type: DataTypes.STRING, allowNull: true, comment: "管理主体" }, glzt: { type: DataTypes.STRING, allowNull: true, comment: "管理主体" },
tzms: { type: DataTypes.STRING, allowNull: true, comment: "投资模式" }, tzms: { type: DataTypes.STRING, allowNull: true, comment: "投资模式" },
dwqypp: { type: DataTypes.STRING, allowNull: true, comment: "对外签约品牌" }, dwqypp: { type: DataTypes.STRING, allowNull: true, comment: "对外签约品牌" },
xmzjly: { type: DataTypes.STRING, allowNull: true, comment: "项目资金来源" }, xmzjly: { type: DataTypes.STRING, allowNull: true, comment: "项目资金来源" },
swbxmlx: { type: DataTypes.STRING, allowNull: true, comment: "商务部项目类型" }, //TODO:下拉 swbxmlx: { type: DataTypes.STRING, allowNull: true, comment: "商务部项目类型" , zjType: 'xiala'}, //TODO:下拉
xmlx: { type: DataTypes.STRING, allowNull: true, comment: "项目类型" }, //TODO:下拉 xmlx: { type: DataTypes.STRING, allowNull: true, comment: "项目类型" , zjType: 'xiala'}, //TODO:下拉
sfpppxm: { type: DataTypes.INTEGER, allowNull: true, comment: "是否PPP项目" }, sfpppxm: { type: DataTypes.INTEGER, allowNull: true, comment: "是否PPP项目", zjType: 'xiala', zjKey: 'sf' },
//项目所在地 //项目所在地
jnw: { type: DataTypes.STRING, allowNull: true, comment: "境内/外" },//TODO:下拉 jnw: { type: DataTypes.STRING, allowNull: true, comment: "境内/外" , zjType: 'xiala'},//TODO:下拉
sjnzjjw: { type: DataTypes.STRING, allowNull: true, comment: "省(境内)/洲际(境外)" },//TODO:下拉 sjnzjjw: { type: DataTypes.STRING, allowNull: true, comment: "省(境内)/洲际(境外)" , zjType: 'xiala'},//TODO:下拉
cityOrCountry: { type: DataTypes.STRING, allowNull: true, comment: "地市(境内)/国家(境外)" },//TODO:下拉 dsjngjjw: { type: DataTypes.STRING, allowNull: true, comment: "地市(境内)/国家(境外)", zjType: 'xiala'},//TODO:下拉
qxjngjjw: { type: DataTypes.STRING, allowNull: true, comment: "区县(境内)/国家(境外)" },//TODO:下拉 qxjngjjw: { type: DataTypes.STRING, allowNull: true, comment: "区县(境内)/国家(境外)" , zjType: 'xiala'},//TODO:下拉
xmqy: { type: DataTypes.STRING, allowNull: true, comment: "项目区域" },//TODO:下拉 xmqy: { type: DataTypes.STRING, allowNull: true, comment: "项目区域" , zjType: 'xiala'},//TODO:下拉
sfydylyxgj: { type: DataTypes.INTEGER, allowNull: true, comment: "是否一带一路沿线国家" }, sfydylyxgj: { type: DataTypes.INTEGER, allowNull: true, comment: "是否一带一路沿线国家" , zjType: 'xiala', zjKey: 'sf'},
//计量币种 //计量币种
bizhong: { type: DataTypes.STRING, allowNull: true, comment: "币种" },//TODO:下拉 bizhong: { type: DataTypes.STRING, allowNull: true, comment: "币种" , zjType: 'xiala'},//TODO:下拉
huilv: { type: DataTypes.DECIMAL(3, 2), allowNull: true, comment: "汇率" }, huilv: { type: DataTypes.DECIMAL(3, 2), allowNull: true, comment: "汇率" },
//实施时间 //实施时间
xmjsqy: { type: DataTypes.STRING, allowNull: true, comment: "项目建设期(月)" }, xmjsqy: { type: DataTypes.STRING, allowNull: true, comment: "项目建设期(月)" },
......
const { DataTypes } = require('sequelize'); const { DataTypes } = require('sequelize');
const sequelize = require('../index'); const sequelize = require('../index');
const moment = require('moment');
//资源库表 记录所有的资源库 //资源库表 记录所有的资源库
const Resources = sequelize.define('Resources', { const Resources = sequelize.define('Resources', {
// 定义字段 // 定义字段
...@@ -13,6 +13,10 @@ const Resources = sequelize.define('Resources', { ...@@ -13,6 +13,10 @@ const Resources = sequelize.define('Resources', {
type: DataTypes.STRING, type: DataTypes.STRING,
comment: "资源库key" comment: "资源库key"
}, },
parentkey: {
type: DataTypes.STRING,
comment: "资源库key"
},
name: { name: {
type: DataTypes.STRING, type: DataTypes.STRING,
comment: "资源库名称" comment: "资源库名称"
......
...@@ -13,7 +13,6 @@ const User = sequelize.define('User', { ...@@ -13,7 +13,6 @@ const User = sequelize.define('User', {
mobile: { mobile: {
type: DataTypes.STRING(11), type: DataTypes.STRING(11),
allowNull: false, allowNull: false,
unique: true,
}, },
password: { password: {
type: DataTypes.STRING(200), type: DataTypes.STRING(200),
......
...@@ -26,8 +26,8 @@ const UserPosition = sequelize.define('UserPosition', { ...@@ -26,8 +26,8 @@ const UserPosition = sequelize.define('UserPosition', {
// 同步模型到数据库(创建表) // 同步模型到数据库(创建表)
UserPosition.sync({ UserPosition.sync({
// force: false, force: false,
force: true //会删除已存在表并重新创建 // force: true //会删除已存在表并重新创建
// alter: true // alter: true
}) })
.then(() => { .then(() => {
......
...@@ -66,12 +66,24 @@ function disTree(tree) { ...@@ -66,12 +66,24 @@ function disTree(tree) {
return parallel return parallel
} }
function genTracSourceCode({EnterpriseCode, type, date, batchNum, logisticsNum}) { // 迭代替代递归(万级以上节点)
// 企业代码(9) MA4W271Y8 + 产品代码【种植、初加工、深加工】(6)+ 生产/出厂日期(8)) + 批次号(8)+ 物流码 + 校验码(8) function flattenTreeIterative(forest) {
//MA4W271Y8 const result = [];
date = date && moment().format('YYYYMMDD'); const stack = [...forest.map(node => ({ node, parentId: null }))];
return `${EnterpriseCode}${type}${date}${batchNum}${logisticsNum}`;
while (stack.length) {
const { node, parentId } = stack.pop();
const { chilrden, children, ...rest } = node;
result.push({ ...rest, parentId });
const kids = chilrden || children || [];
for (let i = kids.length - 1; i >= 0; i--) {
stack.push({ node: kids[i], parentId: node.id });
}
}
return result;
} }
...@@ -80,5 +92,6 @@ module.exports = { ...@@ -80,5 +92,6 @@ module.exports = {
checkUserPassword, checkUserPassword,
buildTree, buildTree,
disTree, disTree,
flattenTreeIterative
} }
\ No newline at end of file
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