diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/bootstrap.js b/bootstrap.js index f574971..c4ee125 100644 --- a/bootstrap.js +++ b/bootstrap.js @@ -19,6 +19,7 @@ import winston from "winston"; import {logger, colorizer} from "#common/logger/index.js"; import createDatabase from "#common/database/index.js"; import {createCatch} from "#cache/index.js"; +import initData from "#common/database/initData.js"; // | 获取ENV const ENV = process.env.NODE_ENV && process.env.NODE_ENV.toLowerCase().trim(); @@ -86,7 +87,10 @@ async function createApp(){ }); logger.info(`== 已成功与数据库建立连接。 ==`); - createCatch(sequelize) + await initData(sequelize) + + await createCatch(sequelize) + diff --git a/production.env.js b/production.env.js index a3aad51..501fa95 100644 --- a/production.env.js +++ b/production.env.js @@ -27,7 +27,7 @@ const prodConfig = { // 同设备(IP)限制登陆次数 status: true, duration: 60 * 1000, - max: 3, + max: 100, }, database:{ mysql:{ diff --git a/src/app.js b/src/app.js index 872b513..0ae2c7c 100644 --- a/src/app.js +++ b/src/app.js @@ -112,6 +112,17 @@ export default function startApp() { }, }), ); + app.use(async (ctx, next) => { + // 解析查询参数为空字符串的情况 + const query = ctx.request.query; + Object.keys(query).forEach(key => { + if (query[key] === '') { + query[key] = undefined; + } + }); + + await next(); + }); app.use(rootRouter.routes()); app.use(rootRouter.allowedMethods()); diff --git a/src/cache/index.js b/src/cache/index.js index 5972a5e..9cff8ce 100644 --- a/src/cache/index.js +++ b/src/cache/index.js @@ -10,34 +10,165 @@ // | -*-*-*- (时间--修改人--修改说明) -*-*-*- // | = // | ------------------------------------------------------------ -import {Op} from "sequelize"; +import { Op } from 'sequelize'; +import { makeTreeForList } from '#common/tools/makeTree.js'; +import makeObject from '#common/tools/makeObject.js'; -export async function createCatch(sequelize){ - global.resourceCache = {} +export async function createCatch(sequelize) { + global.resourceCache = {}; // atomModelCache - const atomModelPoolStartTime = performance.now() - const atomModelPool = await makeAtomModelCache(sequelize) - global.resourceCache.atomModelPool = atomModelPool - const atomModelPoolEndTime = performance.now() - logger.fatal(`元分类/模型缓存加载完毕: atomModelPool - ${atomModelPoolEndTime - atomModelPoolStartTime} ms`) + const atomModelPoolStartTime = performance.now(); + const atomModelPool = await makeAtomModelCache(sequelize); + global.resourceCache.atomModelPool = atomModelPool; + const atomModelPoolEndTime = performance.now(); + logger.fatal( + `元分类/模型缓存加载完毕: atomModelPool - ${ + atomModelPoolEndTime - atomModelPoolStartTime + } ms`, + ); + + // atomModelCache + const baseDictPoolStartTime = performance.now(); + const baseDictPool = await makeBaseDictCache(sequelize); + global.resourceCache.baseDictPool = baseDictPool; + const baseDictPoolEndTime = performance.now(); + logger.fatal( + `数据字典缓存加载完毕: baseDictPool - ${ + baseDictPoolEndTime - baseDictPoolStartTime + } ms`, + ); } -async function makeAtomModelCache(sequelize){ +async function makeAtomModelCache(sequelize) { const atomModelList = await sequelize.models.AtomModel.findAll({ - attributes:['*'], - where: { - isDelete:{ - [Op.is]: null, - } - }, + // attributes:['*'], + // where: { + // isDelete:{ + // [Op.is]: null, + // } + // }, raw: true, // 原始数据 mapToModel: true, // 将下划线变成驼峰 }); + const objectData = {}; + for (let i of atomModelList) { + objectData[i.atomModelId] = i; + } const atomModelPool = { length: atomModelList.length, createtime: new Date().getTime(), updatetime: new Date().getTime(), - data: atomModelList + allData: atomModelList, + normalData: atomModelList.filter((i) => !i.isDelete), + deleteData: atomModelList.filter((i) => i.isDelete), + objectData, + }; + return atomModelPool; +} + +async function makeBaseDictCache(sequelize) { + const baseDictList = await sequelize.models.BaseDict.findAll({ + // attributes:['*'], + // where: { + // isDelete:{ + // [Op.is]: null, + // } + // }, + raw: true, // 原始数据 + mapToModel: true, // 将下划线变成驼峰 + }); + const atomAllList = [], // 原始全量列表 + atomNormalList = [], // 原始正常数据列表 + atomDeleteList = [], // 原始删除数据列表 + atomObject = { + 0: { + children: [], + delChildren: [], + }, + }, // 包含根节点的原始字典关系对象 + reduceObject = { + 0: { + children: [], + delChildren: [], + }, + }, // 包含根节点的精简字典关系对象 + atomModelObject = { + 0: { + baseDictTree: [], + reduceBaseDictTree: [], + }, + }; // 元分类/模型分类下的树 + for (let i = 0; i < baseDictList.length; i++) { + const item = baseDictList[i]; + item.children = []; + item.delChildren = []; + atomObject[item.baseDictId] = item; + reduceObject[item.baseDictId] = { + atomModel: item.atomModel, + baseDictId: item.baseDictId, + baseDictName: item.baseDictName, + baseDictIdentify: item.baseDictIdentify, + baseDictDescribe: item.baseDictDescribe, + baseDictFather: item.baseDictFather, + children: [], + delChildren: [], + }; + // 以上建立精简数据和原始数据 + atomAllList.push(item); + if (item.isDelete) { + atomDeleteList.push(item); + } else { + atomNormalList.push(item); + } + // 以上将数据分类放入列表 + } + for (let i = 0; i < atomNormalList.length; i++) { + // 正常数据 + const dictId = atomNormalList[i].baseDictId; // 字典项ID + const fatherId = atomNormalList[i].baseDictFather; // 父ID + const aData = atomNormalList[i]; // 原始数据字典项 + const rData = reduceObject[dictId]; // 精简字典项 + atomObject[fatherId].children.push(aData); // 压入原始数据到原始对象 + reduceObject[fatherId].children.push(rData); // 压入精简数据到精简对象 + } + for (let i = 0; i < atomDeleteList.length; i++) { + // 已删除数据 + const dictId = atomDeleteList[i].baseDictId; // 字典项ID + const fatherId = atomDeleteList[i].baseDictFather; // 父ID + const aData = atomDeleteList[i]; // 原始数据字典项 + const rData = reduceObject[dictId]; // 精简字典项 + atomObject[fatherId].delChildren.push(aData); // 压入原始数据到原始对象 + reduceObject[fatherId].delChildren.push(rData); // 压入精简数据到精简对象 } - return atomModelPool + const atomModelList = resourceCache.atomModelPool.normalData; + for (let i = 0; i < atomModelList.length; i++) { + const atomModel = atomModelList[i]; + const atomModelId = atomModel.atomModelId; + atomModelObject[atomModelId] = { + baseDictTree: [], + reduceBaseDictTree: [], + }; + atomModelObject[atomModelId].baseDictTree = atomObject[ + '0' + ].children.filter( + (dict) => !(dict.atomModel && atomModelId != dict.atomModel), + ); + atomModelObject[atomModelId].reduceBaseDictTree = reduceObject[ + '0' + ].children.filter( + (dict) => !(dict.atomModel && atomModelId != dict.atomModel), + ); + } + const baseDictPool = { + length: baseDictList.length, + createtime: new Date().getTime(), + updatetime: new Date().getTime(), + atomAllList, + atomNormalList, + atomDeleteList, + atomObject, + reduceObject, + atomModelObject, + }; + return baseDictPool; } diff --git a/src/common/database/dataModels/baseDict.dataModel.js b/src/common/database/dataModels/baseDict.dataModel.js index bd346ce..db5e8d3 100644 --- a/src/common/database/dataModels/baseDict.dataModel.js +++ b/src/common/database/dataModels/baseDict.dataModel.js @@ -28,7 +28,6 @@ export function mountBaseDict(sequelize, DataTypes) { }, atomModel: { type: DataTypes.INTEGER, - allowNull: true, comment: '元分类/模型Id' }, baseDictIsBase: { @@ -48,6 +47,10 @@ export function mountBaseDict(sequelize, DataTypes) { allowNull: false, comment: "字典项名称" }, + baseDictIdentify:{ + type: DataTypes.STRING, + comment: "字典项标识" + }, baseDictDescribe:{ type: DataTypes.STRING(2048), comment: "字典项名描述" diff --git a/src/common/database/index.js b/src/common/database/index.js index 45b97f9..b3f82da 100644 --- a/src/common/database/index.js +++ b/src/common/database/index.js @@ -45,7 +45,8 @@ export default function createDatabase(logger) { // acquire: 30000, // idle: 10000 // }, - logging: logger.debug.bind(logger), + // logging: logger.debug.bind(logger), + logging: false }); mountAtomModel(sequelize, DataTypes); diff --git a/src/common/database/initData.js b/src/common/database/initData.js new file mode 100644 index 0000000..7526ddd --- /dev/null +++ b/src/common/database/initData.js @@ -0,0 +1,353 @@ +// | ------------------------------------------------------------ +// | @版本: version 0.1 +// | @创建人: 【Nie-x7129】 +// | @E-mail: x71291@outlook.com +// | @所在项目: graphResource2 +// | @文件描述: initData.js - +// | @创建时间: 2023-12-02 15:02 +// | @更新时间: 2023-12-02 15:02 +// | @修改记录: +// | -*-*-*- (时间--修改人--修改说明) -*-*-*- +// | = +// | ------------------------------------------------------------ + +// @ 运维资源类的类型字典 +const OMResourceType = [ + { + baseDictId: 1, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '运维资源类型', + baseDictDescribe: '在运维系统上使用的资源类用途定义,资源类和备件类', + baseDictFather: 0, + }, + { + baseDictId: 2, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '资源类型', + baseDictDescribe: '在广义上有ID区分自身的资源', + baseDictFather: 1, + }, + { + baseDictId: 3, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '备件类行', + baseDictDescribe: '在广义上没有ID进行区分的资源', + baseDictFather: 1, + } +] +// @ 单位 +const UnitType = [ + { + baseDictId: 11, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '数据单位', + baseDictDescribe: '对资源在物理上的统一衡量区分', + baseDictFather: 0, + }, + { + baseDictId: 12, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '长度单位', + baseDictDescribe: '对资源在长度上的统一衡量区分', + baseDictFather: 11, + }, + { + baseDictId: 13, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '米', + baseDictIdentify: 'm', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 14, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '厘米', + baseDictIdentify: 'cm', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 15, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '千米', + baseDictIdentify: 'km', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 16, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '毫米', + baseDictIdentify: 'mm', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 17, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '英寸', + baseDictIdentify: 'inch', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 18, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '英尺', + baseDictIdentify: 'ft', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 19, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '英里', + baseDictIdentify: 'mile', + baseDictDescribe: '', + baseDictFather: 12, + }, + { + baseDictId: 20, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '面积单位', + baseDictDescribe: '对资源在平面上的统一衡量区分', + baseDictFather: 11, + }, + { + baseDictId: 21, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '平方米', + baseDictIdentify: 'm²', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 22, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '平方厘米', + baseDictIdentify: 'cm²', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 23, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '平方毫米', + baseDictIdentify: 'mm²', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 24, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '平方千米', + baseDictIdentify: 'km²', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 26, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '英亩', + baseDictIdentify: 'acre', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 27, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '公顷', + baseDictIdentify: 'ha', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 28, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '亩', + baseDictIdentify: 'are', + baseDictDescribe: '', + baseDictFather: 20, + }, + { + baseDictId: 29, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '重量单位', + baseDictDescribe: '对资源在质量上的统一衡量区分', + baseDictFather: 11, + }, + { + baseDictId: 30, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '千克', + baseDictIdentify: 'kg', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 31, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '毫克', + baseDictIdentify: 'mg', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 32, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '克', + baseDictIdentify: 'g', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 33, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '盎司', + baseDictIdentify: 'oz', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 34, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '磅', + baseDictIdentify: 'lb', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 35, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '斤', + baseDictIdentify: '', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 36, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '公斤', + baseDictIdentify: 'kg', + baseDictDescribe: ' ', + baseDictFather: 29, + }, + { + baseDictId: 37, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '时间单位', + baseDictDescribe: '在时间上的统一衡量', + baseDictFather: 11, + }, + { + baseDictId: 38, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '秒', + baseDictIdentify: 's', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 39, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '分', + baseDictIdentify: 'min', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 40, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '时', + baseDictIdentify: 'h', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 41, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '天', + baseDictIdentify: 'd', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 42, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '周', + baseDictIdentify: 'week', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 43, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '月', + baseDictIdentify: 'month', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 44, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '年', + baseDictIdentify: 'year', + baseDictDescribe: ' ', + baseDictFather: 37, + }, + { + baseDictId: 45, + baseDictIsBase: 1, + baseDictOriginType: 0, + baseDictName: '毫秒', + baseDictIdentify: 'ms', + baseDictDescribe: ' ', + baseDictFather: 37, + }, +] + + + +export default function initData(sequelize){ + sequelize.models.BaseDict.bulkCreate(OMResourceType, { ignoreDuplicates: true }) + sequelize.models.BaseDict.bulkCreate(UnitType, { ignoreDuplicates: true }) +} + + diff --git a/src/common/tools/binarySearch.js b/src/common/tools/binarySearch.js new file mode 100644 index 0000000..5fc21bc --- /dev/null +++ b/src/common/tools/binarySearch.js @@ -0,0 +1,87 @@ +// | ------------------------------------------------------------ +// | @版本: version 0.1 +// | @创建人: 【Nie-x7129】 +// | @E-mail: x71291@outlook.com +// | @所在项目: graphResource2 +// | @文件描述: binarySearch.js - 二分法根据蓄力ID查找对象数组元素 +// | @创建时间: 2023-12-02 12:00 +// | @更新时间: 2023-12-02 12:00 +// | @修改记录: +// | -*-*-*- (时间--修改人--修改说明) -*-*-*- +// | = +// | ------------------------------------------------------------ + +export default function binarySearch(arr, id, att) { + let bi = 0, ai = arr.length -1; + if(!Object.keys(arr[0]).includes(att)){ + throw new Error('不存在属性', att) + } + while (bi <= ai){ + const mi = Math.floor((bi + ai)/2); + const miId = arr[mi][att] + if(miId === id){ + return mi + }else if(miId < id){ + bi = mi + 1 + }else{ + ai = mi -1 + } + } + return -1 +} + + +function getIndexForWhile(list, id, att){ + let i = 0 + while (i < list.length){ + if (list[i][att] == id) { + return i + } + i++ + } + return -1 +} + +function getIndexForFor(list, id, att){ + for(let i =0; i< list.length;i++){ + if (list[i][att] == id) { + return i + } + } + return -1 +} + + +function getIndexForForIn(list, id, att){ + for(let i in list){ + if (list[i][att] == id) { + return i + } + } + return -1 +} +// const list = []; +// +// let i = 300; +// +// for (let j = 0; j < 200000; j++) { +// list[j] = { id: j + i }; +// } +// console.time('binarySearch'); +// let id = 200000; +// const i1 = binarySearch(list, id, 'id'); +// console.timeEnd('binarySearch'); +// +// console.time('getIndexForWhile'); +// const i2 = getIndexForWhile(list,id, 'id') +// console.timeEnd('getIndexForWhile'); +// +// console.time('getIndexForFor') +// const i3 = getIndexForFor(list, id, 'id') +// console.timeEnd('getIndexForFor') +// +// console.time('getIndexForForIn') +// const i4 = getIndexForForIn(list, id, 'id') +// console.timeEnd('getIndexForForIn') +// +// console.log(i1, i2, i3, i4) diff --git a/src/common/tools/makeList.js b/src/common/tools/makeList.js new file mode 100644 index 0000000..813d0a6 --- /dev/null +++ b/src/common/tools/makeList.js @@ -0,0 +1,30 @@ +// | ------------------------------------------------------------ +// | @版本: version 0.1 +// | @创建人: 【Nie-x7129】 +// | @E-mail: x71291@outlook.com +// | @所在项目: graphResource2 +// | @文件描述: makeList.js - +// | @创建时间: 2023-12-02 17:00 +// | @更新时间: 2023-12-02 17:00 +// | @修改记录: +// | -*-*-*- (时间--修改人--修改说明) -*-*-*- +// | = +// | ------------------------------------------------------------ + +export default function makeList(tree, childrenField = 'children'){ + const arr = getChildren(list, childrenField) + const setObj = new Set(arr) + return Array.from(setObj) +} + +function getChildren(list, childrenField){ + let arr = [] + for(let i = 0; i < list.length; i++){ + if(list[i][childrenField] && list[i][childrenField].length > 0){ + arr = [...arr, ...getChildren(list[i][childrenField], childrenField)] + }else{ + arr.push(list[i]) + } + } + return arr +} diff --git a/src/common/tools/makeObject.js b/src/common/tools/makeObject.js new file mode 100644 index 0000000..6c7a05b --- /dev/null +++ b/src/common/tools/makeObject.js @@ -0,0 +1,23 @@ +// | ------------------------------------------------------------ +// | @版本: version 0.1 +// | @创建人: 【Nie-x7129】 +// | @E-mail: x71291@outlook.com +// | @所在项目: graphResource2 +// | @文件描述: makeObject.js - 制造对象 +// | @创建时间: 2023-12-02 16:41 +// | @更新时间: 2023-12-02 16:41 +// | @修改记录: +// | -*-*-*- (时间--修改人--修改说明) -*-*-*- +// | = +// | ------------------------------------------------------------ + +export default function makeObject(list, idField, hasChildren = false){ + const newObject = {}; + for(let i = 0; i < list.length; i++){ + if(hasChildren){ + list[i].children = []; + newObject[list[i][idField]] = list[i] + } + } + return newObject +} diff --git a/src/common/tools/makeTree.js b/src/common/tools/makeTree.js new file mode 100644 index 0000000..e552b51 --- /dev/null +++ b/src/common/tools/makeTree.js @@ -0,0 +1,37 @@ +// | ------------------------------------------------------------ +// | @版本: version 0.1 +// | @创建人: 【Nie-x7129】 +// | @E-mail: x71291@outlook.com +// | @所在项目: graphResource2 +// | @文件描述: makeTree.js - 生成树 +// | @创建时间: 2023-12-02 15:45 +// | @更新时间: 2023-12-02 15:45 +// | @修改记录: +// | -*-*-*- (时间--修改人--修改说明) -*-*-*- +// | = +// | ------------------------------------------------------------ + + +export function makeTreeForList(list, object, referField, fatherField, hasDelete = true){ + if(!Object.keys(object).includes('0')){ + object['0'] = { + children: [] + } + } + for(let i = 0; i < list.length; i++){ + const fatherId = list[i][fatherField]; + if(list[i].isDelete && !hasDelete){ + continue + } + if(!fatherId){ + object['0'].children.push(list[i]) + continue + } + if(!object[fatherId].children){ + object[fatherId].children = [] + } + object[fatherId].children.push(list[i]) + } + return object['0'].children +} + diff --git a/src/routes/graphResource2/atomModel/index.js b/src/routes/graphResource2/atomModel/index.js index 7f2d805..c1c26db 100644 --- a/src/routes/graphResource2/atomModel/index.js +++ b/src/routes/graphResource2/atomModel/index.js @@ -22,6 +22,7 @@ import { } from '#routes/graphResource2/atomModel/index.dto.js'; import getPage from '#common/tools/getArrayPage.js'; import getNoSpacesStr from '#common/tools/getNoSpacesStr.js'; +import binarySearch from "#common/tools/binarySearch.js"; const atomModel = new Router(); @@ -32,7 +33,7 @@ atomModel.get('/getAtomModelPage', async (ctx, next) => { ctx.throw(400, { e: verif.error.map((i) => i.message) }); return; } - let list = resourceCache.atomModelPool.data; + let list = resourceCache.atomModelPool.normalData; if (ctx.query.searchData) { const searchData = ctx.query.searchData; list = list.filter((i) => { @@ -49,10 +50,18 @@ atomModel.get('/getAtomModelPage', async (ctx, next) => { // @ 获取元分类列表 atomModel.get('/getAtomModelList', async (ctx, next) => { - ctx.body = resourceCache.atomModelPool.data.map((i) => ({ + const deleteData = resourceCache.atomModelPool.deleteData.map((i) => ({ atomModelId: i.atomModelId, atomModelName: i.atomModelName, })); + const narmalData = resourceCache.atomModelPool.normalData.map((i) => ({ + atomModelId: i.atomModelId, + atomModelName: i.atomModelName, + })); + ctx.body = { + deleteData, + narmalData, + }; }); // @ 新建元分类 @@ -64,12 +73,17 @@ atomModel.post('/createAtomModelItem', async (ctx, next) => { } let { atomModelName, atomModelDescribe } = ctx.request.body; atomModelName = getNoSpacesStr(atomModelName).toUpperCase(); + // 名称查重 if (checkName(atomModelName) == -1) { const newAtomModel = await ctx.sequelize.models.AtomModel.create({ atomModelName, atomModelDescribe, }); - resourceCache.atomModelPool.data.push(newAtomModel.dataValues); + resourceCache.atomModelPool.allData.push(newAtomModel.dataValues); + resourceCache.atomModelPool.normalData.push(newAtomModel.dataValues); + resourceCache.atomModelPool.objectData[ + newAtomModel.dataValues.atomModelId + ] = newAtomModel.dataValues; resourceCache.atomModelPool.length++; resourceCache.atomModelPool.updatetime = new Date().getTime(); ctx.body = { @@ -89,31 +103,44 @@ atomModel.post('/editAtomModelItem', async (ctx, next) => { return; } let { atomModelName, atomModelDescribe, atomModelId } = ctx.request.body; - console.log(atomModelName) - atomModelName = getNoSpacesStr(atomModelName).toUpperCase() - const index= checkName(atomModelName) - if([-1, atomModelId].includes(resourceCache.atomModelPool.data[index].atomModelId)){ - if(resourceCache.atomModelPool.data[index].atomModelDescribe == atomModelDescribe && resourceCache.atomModelPool.data[index].atomModelName == atomModelName){ - ctx.body = { - message: '编辑元分类/模型成功', - }; - return - } - resourceCache.atomModelPool.data[index].atomModelDescribe = atomModelDescribe; - resourceCache.atomModelPool.data[index].atomModelName = atomModelName - resourceCache.atomModelPool.updatetime = new Date().getTime(); + // 是否存在ID + const RAP = resourceCache.atomModelPool + const nowData = RAP.objectData[atomModelId] + if(!nowData || (nowData && nowData.isDelete)){ + ctx.throw(400, { e: '不存在元分类/模型记录' }); + return; + } + atomModelName = getNoSpacesStr(atomModelName).toUpperCase(); + // 名称查重 + const index = checkName(atomModelName); + if ( + index != -1 && + atomModelId != RAP.normalData[index].atomModelId + ) { + ctx.throw(400, { e: '元分类/模型名称重复' }); + return; + } + if ( + nowData.atomModelDescribe == atomModelDescribe && + nowData.atomModelName == atomModelName + ) { ctx.body = { message: '编辑元分类/模型成功', }; - await next(); - await ctx.sequelize.models.AtomModel.update( - { atomModelName, atomModelDescribe, }, - { where: { atomModelId } }, - ); - }else{ - ctx.throw(400, {e: '元分类/模型名称重复'}) + return; } - + nowData.atomModelName = atomModelName; + nowData.atomModelDescribe = + atomModelDescribe; + RAP.updatetime = new Date().getTime(); + ctx.body = { + message: '编辑元分类/模型成功', + }; + await next(); + await ctx.sequelize.models.AtomModel.update( + { atomModelName, atomModelDescribe }, + { where: { atomModelId } }, + ); }); // @ 查重元分类名称 @@ -140,20 +167,18 @@ atomModel.delete('/deleteAtomModelItem', async (ctx, next) => { return; } const { atomModelId } = ctx.query; - let index = -1; - for (let i in resourceCache.atomModelPool.data) { - if (resourceCache.atomModelPool.data[i].atomModelId == atomModelId) { - index = i; - break; - } - } - if (index == -1) { + const RAP = resourceCache.atomModelPool + const normalIndex = binarySearch(RAP.normalData, atomModelId, 'atomModelId') + if (normalIndex == -1) { ctx.throw(400, { e: '不存在此元分类/模型记录。' }); return; } - resourceCache.atomModelPool.data.splice(index, 1); - resourceCache.atomModelPool.length--; - resourceCache.atomModelPool.updatetime = new Date().getTime(); + const allIndex = binarySearch(RAP.allData, atomModelId, 'atomModelId') + RAP.normalData.splice(normalIndex, 1); + RAP.allData.splice(allIndex, 1); + RAP.deleteData.push(RAP.objectData[atomModelId]) + RAP.length--; + RAP.updatetime = new Date().getTime(); ctx.body = { message: '删除元分类/模型成功。' }; await next(); await ctx.sequelize.models.AtomModel.update( @@ -171,8 +196,8 @@ export default atomModel; // = 创建人: expressgy // = 创建时间: 2023-12-01 22:56:12 - function checkName(name) { - for (let i in resourceCache.atomModelPool.data) { - if (name == resourceCache.atomModelPool.data[i].atomModelName) { + for (let i = 0; i < resourceCache.atomModelPool.normalData.length; i++) { + if (name == resourceCache.atomModelPool.normalData[i].atomModelName) { return i; } } diff --git a/src/routes/graphResource2/baseDict/index.dto.js b/src/routes/graphResource2/baseDict/index.dto.js index aae3d25..29c9f18 100644 --- a/src/routes/graphResource2/baseDict/index.dto.js +++ b/src/routes/graphResource2/baseDict/index.dto.js @@ -18,13 +18,22 @@ export function GetBaseDictTreeDTO(data) { type: 'object', properties: { atomModelId: { - type: ['integer', 'null'], + type: ['integer'], minimum: 0, errorMessage: { type: '元分类/模型ID必须是整数', minimum: '元分类/模型ID是一个正整数', }, }, + reduce:{ + type: ['integer'], + minimum: 0, + default: 1, + errorMessage: { + type: '元分类/模型ID必须是整数', + minimum: '元分类/模型ID是一个正整数', + }, + } }, }; return makeDTO(data, schema); diff --git a/src/routes/graphResource2/baseDict/index.js b/src/routes/graphResource2/baseDict/index.js index ead3518..21ff437 100644 --- a/src/routes/graphResource2/baseDict/index.js +++ b/src/routes/graphResource2/baseDict/index.js @@ -19,42 +19,87 @@ import { GetBaseDictStructForBaseDictIdDTO, GetBaseDictTreeDTO } from '#routes/graphResource2/baseDict/index.dto.js'; -import {DeleteAtomModelItemDTO} from "#routes/graphResource2/atomModel/index.dto.js"; +import {makeTreeForList} from "#common/tools/makeTree.js"; const baseDict = new Router(); // @ 获取字典树 baseDict.get('/getBaseDictTree', async (ctx, next) => { - const data = ctx.query; - const verif = GetBaseDictTreeDTO(data); + const verif = GetBaseDictTreeDTO(ctx.query); if (!verif.status) { ctx.throw(400, { e: verif.error.map((i) => i.message) }); return; } - ctx.body = 1 + const {atomModelId, reduce} = ctx.query; + + const RBP = resourceCache.baseDictPool + const isReduce = !(reduce && reduce == 0) + if(atomModelId){ + if(Object.keys(RBP.atomModelObject).includes(atomModelId.toString())){ + ctx.body = isReduce ? RBP.atomModelObject[atomModelId].reduceBaseDictTree : RBP.atomModelObject[atomModelId].baseDictTree + }else{ + ctx.body = isReduce ? RBP.atomModelObject[0].reduceBaseDictTree : RBP.atomModelObject[0].baseDictTree + } + }else{ + ctx.body = isReduce ? RBP.reduceObject[0].children : RBP.atomObject[0].children + } }); // @ 获取字典名列表 baseDict.get('/getBaseDictList', async (ctx, next) => { - const data = ctx.query; - console.log(data) - const verif = GetBaseDictListDTO(data); - if (!verif.status) { - ctx.throw(400, { e: verif.error.map((i) => i.message) }); - return; + const verif = GetBaseDictListDTO(ctx.query); + if (!verif.status) return ctx.throw(400, { e: verif.error.map((i) => i.message) }); + const {searchData, atomModelId} = ctx.query; + const RBP = resourceCache.baseDictPool + if(atomModelId){ + if(Object.keys(RBP.atomModelObject).includes(atomModelId.toString())){ + ctx.body = RBP.atomModelObject[atomModelId].reduceBaseDictTree.map(item => ({ + atomModel: item.atomModel, + baseDictId: item.baseDictId, + baseDictName: item.baseDictName, + baseDictIdentify: item.baseDictIdentify, + baseDictDescribe: item.baseDictDescribe, + })) + }else{ + ctx.body = RBP.atomModelObject[0].reduceBaseDictTree.map(item => ({ + atomModel: item.atomModel, + baseDictId: item.baseDictId, + baseDictName: item.baseDictName, + baseDictIdentify: item.baseDictIdentify, + baseDictDescribe: item.baseDictDescribe, + })) + } + }else{ + ctx.body = RBP.reduceObject[0].children.map(item => ({ + atomModel: item.atomModel, + baseDictId: item.baseDictId, + baseDictName: item.baseDictName, + baseDictIdentify: item.baseDictIdentify, + baseDictDescribe: item.baseDictDescribe, + })) + } + if(searchData){ + ctx.body = ctx.body.filter(i => { + return (i.baseDictName + i.baseDictIdentify + i.baseDictDescribe).includes(searchData) + }) } - ctx.body = 2 }); // @ 通过字典ID获取完整字典结构 baseDict.get('/getBaseDictStructForBaseDictId', async (ctx, next) => { - const data = ctx.query; - const verif = GetBaseDictStructForBaseDictIdDTO(data); + const verif = GetBaseDictStructForBaseDictIdDTO(ctx.query); if (!verif.status) { ctx.throw(400, { e: verif.error.map((i) => i.message) }); return; } - ctx.body = 3 + const { baseDictId } = ctx.query; + const RBP = resourceCache.baseDictPool + if(Object.keys(RBP.reduceObject).includes(baseDictId.toString())){ + ctx.body = RBP.reduceObject[baseDictId] + }else{ + ctx.throw(400,{e: '未找到指定字典。'}) + } + }); // @ 删除字典项