UNPKG

helena

Version:
379 lines (354 loc) 12.1 kB
const fs = require('fs'); const path = require('path'); let codes = {}; let codeLock = false; let codePath = '/data/systemdata/codes'; let code = {}; code.BEFORE = -1; code.AFTER = 1; code.SON = 0; code.init = function (basePath) { codePath = basePath; }; code.freshCodes = function () { codes = {}; codeLock = false; return true; }; code.onReady = function (type) { return new Promise(resolve => { if (codeLock) { sleep(100) .then(() => { code.onReady() .then(res => { resolve(res); }); }); } else { if (!codes[type]) { codeLock = true; fs.readFile(codePath + '/' + type + '/' + type + '.json', 'utf8', (err, data) => { if (err) { codes[type] = { 'label': type, 'id': 0, 'fid': -1, 'idcount': 0, 'disabled': false, 'children': [] }; codes[type + 'Arr'] = []; codes[type + 'Arr'].push(codes[type]); } else { codes[type] = JSON.parse(data); codes[type + 'Arr'] = []; mkArr(codes[type], codes[type + 'Arr']); } codeLock = false; resolve(true); }); } else { resolve(true); } } }); }; code.getCode = function (type) { return codes[type]; }; /** * 代码转标签 * @param type * @param nodeCode */ code.code2labels = function (type, nodeCode) { let result = codes[type + 'Arr'][nodeCode].label; while (codes[type + 'Arr'][nodeCode].fid > 0) { nodeCode = codes[type + 'Arr'][nodeCode].fid; result = codes[type + 'Arr'][nodeCode].label + '-' + result; } return result; }; code.code2label = function (type, nodeCode) { return codes[type + 'Arr'][nodeCode].label; }; /** * 单个标签快速转代码,仅找到最先找到的那个,一般用于标签不重复的代码表 * @param type * @param label */ code.label2code = function (type, label) { let nodeCode; for (let node of codes[type + 'Arr']) { if (node.label === label) { nodeCode = node.id; break; } } return nodeCode; }; /** * 标签组转代码,返回所有符合条件的结点代码 * @param type * @param labelList * @returns */ code.labels2code = function (type, labelList) { let result = []; let findElement = function (elements, sn) { for (let item of elements) { if (item.label.toLowerCase() === labelList[sn].toLowerCase()) { if (sn > labelList.length - 2) { result.push(code.code2codes(type, item.id)); } else { if (item.children) findElement(item.children, sn + 1); } } else { // 当sn不等于0时,不能进入下一层,而是回退到上层 if (sn === 0 && item.children) findElement(item.children, sn); } } }; findElement(codes[type].children, 0); return result; }; code.code2codes = function (type, nodeCode) { let item = codes[type + 'Arr'][nodeCode]; let single = [nodeCode]; let loop = true; let temp = item; while (loop) { if (temp.fid > 0) { temp = codes[type + 'Arr'][temp.fid]; single.unshift(temp.id); } else { loop = false; } } return single; }; code.sort = function (type, c1, c2) { let result = 0; let len1 = c1.length; let len2 = c2.length; let len = (len1 > len2) ? len2 : len1; let father = 0; for (let i = 0; i < len; i++) { if (c1[i] !== c2[i]) { let children = codes[type + 'Arr'][father].children; let site1 = -1; let site2 = -1; for (let j = 0; j < children.length; j++) { if (site1 < 0 && children[j].id === c1[i]) site1 = j; else if (site2 < 0 && children[j].id === c2[i]) site2 = j; } result = site1 - site2; break; } else { father = c1[i]; } } if (!result) result = len1 - len2; return result; }; code.save = function (type) { let result = false; if (codes[type]) { mkDirs(codePath + '/' + type); if (fs.existsSync(codePath + '/' + type + '/' + type + '.json')) { fs.renameSync(codePath + '/' + type + '/' + type + '.json', codePath + '/' + type + '/' + (new Date()).valueOf().toString() + '.json'); } fs.writeFile(codePath + '/' + type + '/' + type + '.json', JSON.stringify(codes[type]), () => { }); result = true; } return result; }; code.modifyLabel = function (type, nodeCode, label) { let result = false; if (nodeCode > 0 && codes[type + 'Arr'] && codes[type + 'Arr'][nodeCode]) { codes[type + 'Arr'][nodeCode].label = label; code.save(type); result = true; } if (result) result = codes[type]; return result; }; code.moveSubtree = function (type, nodeCode, toNodeCode, way) { let result = false; let codesType = codes[type + 'Arr']; //要做为某个节点的子节点移入,这个节点的子节点必须为空。如果不空,需要用节点前或后的方式 if (nodeCode > 0 && toNodeCode > 0 && codesType && codesType[nodeCode] && codesType[toNodeCode] && (way === code.SON || way === code.AFTER || way === code.BEFORE) && (way !== code.SON || codesType[toNodeCode].children.length < 1)) { //从原父节点断开 let fatherCode = codesType[nodeCode].fid; if (fatherCode > -1) { let site = -1; for (let i = 0; i < codesType[fatherCode].children.length; i++) { if (codesType[fatherCode].children[i].id === nodeCode) { site = i; break; } } if (site > -1) codesType[fatherCode].children.splice(site, 1); //连接新的父结点 if (way === code.SON) { codesType[nodeCode].fid = toNodeCode; codesType[toNodeCode].children.push(codesType[nodeCode]); } else { fatherCode = codesType[toNodeCode].fid; codesType[nodeCode].fid = fatherCode; site = -1; for (let i = 0; i < codesType[fatherCode].children.length; i++) { if (codesType[fatherCode].children[i].id === toNodeCode) { site = i; break; } } if (way === code.AFTER) site++; codesType[fatherCode].children.splice(site, 0, codesType[nodeCode]); } result = true; code.save(type); } } if (result) result = codes[type]; return result; }; code.copySubtree = function (type, nodeCode, toNodeCode, way) { let result = false; let codesType = codes[type + 'Arr']; //要做为某个节点的子节点移入,这个节点的子节点必须为空。如果不空,需要用节点前或后的方式 if (nodeCode > 0 && toNodeCode > 0 && codesType && codesType[nodeCode] && codesType[toNodeCode] && (way === code.SON || way === code.AFTER || way === code.BEFORE) && (way !== code.SON || codesType[toNodeCode].children.length < 1)) { let copy = function (from, fid) { codesType[0].idcount++; let to = {}; to.id = codesType[0].idcount; to.fid = fid; to.disabled = false; to.label = from.label; to.children = []; from.children.forEach(son => { let sonNode = copy(son, to.id); to.children.push(sonNode); }); codesType[to.id] = to; return to; }; let newNode = copy(codesType[nodeCode], 0); newNode.label = '<副本>' + newNode.label; if (way === code.SON) { newNode.fid = codesType[toNodeCode].id; codesType[toNodeCode].children.push(newNode); } else { newNode.fid = codesType[toNodeCode].fid; let children = codesType[newNode.fid].children; let site = -1; for (let i = 0; i < children.length; i++) { if (children[i].id === toNodeCode) { site = i; break; } } if (site > -1) { if (way === code.AFTER) site++; children.splice(site, 0, newNode); } } result = true; code.save(type); } if (result) result = codes[type]; return result; }; code.changeSubtreeDisabledValue = function (type, nodeCode, disabled) { let result = false; let codesType = codes[type + 'Arr']; let f = function (type, node, disabled) { node.disabled = disabled; node.children.forEach(sonNode => { f(type, sonNode, disabled); }); }; if (codesType && codesType[nodeCode]) { f(type, codesType[nodeCode], disabled); code.save(type); result = true; } if (result) result = codes[type]; return result; }; code.addSubtree = function (type, labelList, toNodeCode, way) { let result = false; if (codes[type + 'Arr'] && codes[type + 'Arr'][toNodeCode] && (way === code.SON || way === code.AFTER || way === code.BEFORE) && (way !== code.SON || codes[type + 'Arr'][toNodeCode].children.length < 1)) { let node = codes[type + 'Arr'][toNodeCode]; let newNodes = []; labelList.forEach(label => { newNodes.push({label: label, id: 0, fid: -1, disabled: false, children: []}); }); if (way === code.SON) { newNodes.forEach(newNode => { codes[type + 'Arr'][0].idcount++; newNode.id = codes[type + 'Arr'][0].idcount; newNode.fid = node.id; node.children.push(newNode); codes[type + 'Arr'][newNode.id] = newNode; }); code.save(type); result = true; } else { if (node.fid > -1) { let children = codes[type + 'Arr'][node.fid].children; let site = -1; for (let i = 0; i < children.length; i++) { if (children[i].id === toNodeCode) { site = i; break; } } if (site > -1) { if (way === code.AFTER) site++; newNodes.forEach(newNode => { codes[type + 'Arr'][0].idcount++; newNode.id = codes[type + 'Arr'][0].idcount; newNode.fid = node.fid; codes[type + 'Arr'][newNode.id] = newNode; }); children.splice(site, 0, ...newNodes); code.save(type); result = true; } } } } if (result) result = codes[type]; return result; }; module.exports = code; function sleep(time = 1000) { return new Promise(resolve => { setTimeout(() => { resolve(); }, time); }); } function mkDirs(dirPath) { if (!fs.existsSync(dirPath)) { mkDirs(path.dirname(dirPath)); fs.mkdirSync(dirPath); } } function mkArr(obj, arr) { arr[obj.id] = obj; for (let son of obj.children) { mkArr(son, arr); } }