Commit e220b10c by lixinming

no message

parents
.idea
/out
/node_modules
/test
*test*
*.log
\ No newline at end of file
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"program": "${workspaceFolder}/src/main.ts",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
}
]
}
\ No newline at end of file
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('data-server:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
{
"name": "gameserver",
"version": "1.0.0",
"description": "",
"main": "main.ts",
"dependencies": {
"@alicloud/sms-sdk": "^1.1.6",
"@types/node": "^10.12.18",
"compression": "^1.7.4",
"express": "^4.17.1",
"express-async-handler": "^1.1.4",
"formidable": "^1.2.1",
"lru-cache": "^4.1.5",
"md5": "^2.2.1",
"moment": "^2.24.0",
"mongoose": "^5.4.0",
"mysql": "^2.18.1",
"node-xlsx": "^0.16.1",
"nodemailer": "^6.1.1",
"request": "^2.88.0",
"svg-captcha": "^1.3.12",
"ws": "^5.2.2"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
//标准化exce输入
/**
* planarArrBecomeKeyValueData 二维数组转keyvalue需要的结构
* @param dataList 数据列表 格式 [[标题1,标题2],[key1,value1],[key2, value2]] or [[标题1, key1, key2],[标题2,value1, value2] ]
* @param titleInY 标题是否垂直排列 or key是否横向排列 or key在x轴上 and 即当为false时输入为(默认为false):[[标题1,标题2],[key1,value1],[key2, value2]]
* @returns {key:value}
*/
export function planarArrBecomeKeyValueData(dataList, titleInY = false) {
let result:any = {};
if (!titleInY) { //title 在x轴上
for (let y = 1; y < dataList.length; y++) {
let childList = dataList[y];
let key = childList[0];
let value = childList[1] || null;
result[key] = value;
}
} else {
let keyList = dataList[0];
let valueList = dataList[1];
for (let i = 1; i < keyList.length; i++) {
let key = keyList[i];
let value = valueList[i] || null;
result[key] = value;
}
}
return result;
}
/**
* planarArrBecomeChartData 二维数组转chart需要的结构
* @param dataList 数据列表 格式 [[标题说明占位符, key1, key2, key3],[数据名称a, a的value1, a的value2, a的value3],[数据名称b, b的value1, b的value2, b的value3]]
* or [[标题说明占位符, 数据名称a, 数据名称b ],[key1, a的value1, b的value1],[key2, a的value2, b的value2]]
* @param titleInY key是否在y轴上 默认为false时 [[标题说明占位符, 数据名称a, 数据名称b ],[key1, a的value1, b的value1],[key2, a的value2, b的value2]]
* @returns {"图表名称":{unit:"", dataInfo:[{key:"数据key", value:"数据值"}, {key:"数据key", value:"数据值"} ] } }
*/
export function planarArrBecomeChartData(dataList, titleInY = false) {
let result = {};
if (!titleInY) {
let keyList = dataList[0];
for (let y = 1; y < dataList.length; y++) {
let subList = dataList[y];
let dataName = subList[0];
let dataInfo = [];
for (let x = 1; x < subList.length; x++) {
let key = keyList[x] || `未知key${x}`;
let value = subList[x];
dataInfo.push({ key, value });
}
result[dataName] = {unit:'', dataInfo};
}
} else {
let dataIndexMap = {};
let dataNameList = dataList[0];
for (let x = 1; x < dataNameList.length; x++) {
let dataName = dataNameList[x];
dataIndexMap[x] = dataName;
result[dataName] = {unit:'', dataInfo:[]};
}
for (let y = 1; y < dataList.length; y++) {
let subList = dataList[y];
let key = subList[0];
for (let x = 1; x < subList.length; x++) {
let thisDataName = dataIndexMap[x];
let value = subList[x];
result[thisDataName].dataInfo.push( {key, value} );
}
}
}
return result;
}
/**
* planarArrBecomeStringListData 二维数组转字符列表需要的结构
* @param dataList dataList 数据列表 格式 [[标题1,标题2],[文本占位符,value1],[文本占位符, value2]] or [[标题1, 文本占位符, 文本占位符],[标题2,value1, value2] ]
* @param titleInY titleInY 标题是否垂直排列 or key是否横向排列 or key在x轴上 and 即当为false时输入为(默认为false):[[标题1,标题2],[key1,value1],[key2, value2]]
* @returns ["文本1", "文本2"]
*/
export function planarArrBecomeStringListData(dataList, titleInY = false) {
let result = [];
if (!titleInY) { //title 在x轴上
for (let y = 1; y < dataList.length; y++) {
let childList = dataList[y];
let value = childList[1] || '';
result.push(value);
}
} else {
let valueList = dataList[1];
for (let i = 1; i < valueList.length; i++) {
let value = valueList[i] || '';
result.push(value);
}
}
return result;
}
/**
* planarArrBecomeListData 二维数组转列表需要的结构
* @param dataList 数据列表 格式 [[标题1, 标题2, 标题3],[a的value1, a的value2, a的value3],[b的value1, b的value2, b的value3]] or
* [[标题1, 标题2, 标题3, 标题4],[a的value1, a的value2, a的value3],[b的value1, b的value2, b的value3]]
* @param headerInx
* @returns
*/
export function planarArrBecomeListData(dataList, headerInx?) {
//todo
}
//todo ====
/**
* analysisExcelDataOfMoreObject 将excel解出来的数据块按需求解析成可用数据
* @param dataList excel解出来的数据
* @param isJumpTitle 是否跳过解析表头
* @param headerInx 第一个表头数据是否横向排列
* @returns 返回 {"第一个表头数据":{"表头数据":值...} }
*/
export function analysisExcelDataOfMoreObject(dataList, headerInx?) {
let result = {};
let titleList = dataList[0];
if (!headerInx) {
for (let y =1; y < dataList.length; y++) {
let dataTitle = dataList[y][0];
let thisData = {};
for (let x = 1; x < dataList[y].length; x++) {
let key = titleList[x];
thisData[key] = dataList[y][x];
}
result[dataTitle] = thisData;
}
} else {
let indexKeyMap = {};
titleList.forEach((thisTitle, index) => {
if (!index) return;
indexKeyMap[index] = thisTitle;
result[thisTitle] = {};
});
for (let y =1; y < dataList.length; y++) {
let thisKey = dataList[y][0];
for (let x = 1; x < dataList[y].length; x++) {
let thisTitle = indexKeyMap[x];
result[thisTitle][thisKey] = dataList[y][x];
}
}
}
return result;
}
/**
* analysisExcelDataOfList 将excel解出来的数据块按需求解析成可用数据
* @param dataList excel解出来的数据
* @param keyObject 对应关系 {dataList表头名称: 英文}
* @param headerInx 第一个表头数据是否横向排列
* @returns 返回 {"第一个表头数据":{"表头数据":值...} }
*/
export function analysisExcelDataOfList(dataList, keyObject, headerInx?) {
let result = [];
if (!headerInx) {//在y轴上排列
let titleList = dataList[0];
let indexKeyNameMap = {};
titleList.forEach( (info, index) => {
indexKeyNameMap[index + 1] = info;
});
for (let i = 1; i < dataList.length; i++) {
let onceInfo = {};
let subList = dataList[i];
subList.forEach( (info, index) => {
let key = indexKeyNameMap[index + 1];
let checkKey = keyObject[key];
onceInfo[checkKey] = info;
});
result.push(onceInfo);
}
} else {//在x轴上排列
let indexKeyNameMap = {};
dataList.forEach( (info, index) => {
indexKeyNameMap[index + 1] = info[0];
});
let dataMap = {};
for(let y = 0; y < dataList.length; y++) {
let xList = dataList[y];
for (let x = 1; x < xList.length; x++) {
if (!dataMap[x]) dataMap[x] = {};
let key = indexKeyNameMap[y + 1];
let checkKey = keyObject[key];
dataMap[x][checkKey] = xList[x];
}
}
result = Object.values(dataMap);
}
return result;
}
export function analysisExcelDataOfStringList(dataList) {
let result = [];
for (let i = 0; i < dataList.length; i++) {
if (!i) continue;
let subList = dataList[i];
result.push(subList[1]);
}
return result;
}
//内部使用
/**
* planarArrayForEecomeStringList 二维数组转列表
* @param planarArray
*/
export function planarArrayForEecomeStringList(planarArray) {
}
\ No newline at end of file
import { getUnitMaxOccNum, separateDataAndUint, unifiedMaxAndMinValueAndStep } from "./privateTools";
//标准化输出 这里的东西禁止 乱改以及临时更改
/**
* getStringOutData 获取文字列表返回结果
* @param title 数据标题
* @param data 数据体 格式:["txt...", "str..."]
* @returns {title, dataList:[string...]}
*/
export function getStringOutData(title, data) {
let dataList = [];
data.forEach( (str, index) => {
dataList.push({ key:index+1, value:str});
});
return { title, dataList};
}
/**
* getChartData 获取图表返回结果
* @param title 数据标题
* @param data 数据体 格式:{"图表名称":{unit:"", dataInfo:[{key:"数据key", value:"数据值"}, {key:"数据key", value:"数据值"} ] } }
* @param haveMoreY 是否有多个y轴 默认false
* @returns {title:标题, dataList:[{unit:单位, total:总数, yMinValue:最小值, yMaxValue:最大值, yStepValue:间隔, dataList:[{key:value}] }]}
*/
export function getChartOutData(title, data) {
let dataList = [];
for (let chartName in data) {
let { unit, dataInfo } = data[chartName];
let addData:any = { title: chartName };
let max = 0;
let min = new Date().valueOf();
let total = 0;
let thisUnitStats = {};
let onceDataList = [];
for (let i = 0; i < dataInfo.length; i++) {
let { key, value } = dataInfo[i];
let { dataNum, dataUnit } = separateDataAndUint(value);
min = Math.min(min, dataNum);
max = Math.max(max, dataNum);
thisUnitStats[dataUnit] = thisUnitStats[dataUnit] ? thisUnitStats[dataUnit] + 1 : 1;
total += dataNum;
onceDataList.push({key, value:dataNum, unit:dataUnit});
}
let statsUnit = getUnitMaxOccNum(thisUnitStats);
let thisChartUnit = unit || statsUnit || "";
addData["unit"] = thisChartUnit;
addData["total"] = total;
let {maxNumber, minNumber, stepNumber} = unifiedMaxAndMinValueAndStep(max, min);
addData["yMinValue"] = minNumber;
addData["yMaxValue"] = maxNumber;
addData["yStepValue"] = stepNumber;
addData["dataList"] = onceDataList;
dataList.push(addData);
}
return {title, dataList};
}
/**
* getListOutData 获取列表返回结果
* @param title 数据标题
* @param data 数据体 格式:[{key:"key1", values:[data1value1, data2value1, data3value1] }, {key:"key2", values:[data1value2, data2value2, data3value2] }]
* @returns {title:数据标题, total:数据总条数, titleList:[表头...], valueList:[[数据列表...],[数据列表...]]}
*/
export function getListOutData(title, data) {
let titleList = [];
let valueList = [];
let maxLength = 0;
data.forEach( onceData => {
let { key, values } = onceData;
titleList.push(key);
for (let i = 0; i < values.length; i++) {
let value = values[i] || "";
valueList[i] ? valueList[i].push(value) : valueList[i] = [value];
Math.max(maxLength, i+1);
}
});
return {title, total:0, titleList, valueList};
}
/**
* getKeyNumberValueOutData 获取值为数值的键值返回结果
* @param title 数据标题
* @param data 数据体 格式:{key:value, key:value}
* @returns { title:数据标题, dataList:[{key:"数据key", "value":"数据value", unit:"数据单位"}], total:数据值总数, count:数据总条数 }
*/
export function getKeyNumberValueOutData(title, data) {
let dataList = [];
let total = 0;
let count = 0;
for (let key in data) {
let {dataNum, dataUnit} = separateDataAndUint(data[key]);
total += dataNum;
count += 1;
let addData = {key, value:dataNum, unit:dataUnit};
dataList.push(addData);
}
return { title, dataList, total, count };
}
/**
* getKeyStringValueOutData 获取值为字符串的键值返回结果
* @param title 数据标题
* @param data 数据体 格式:{key:value, key:value}
* @returns { title:数据标题, dataList:[{key:"数据key", "value":"数据value"}], count:数据总条数 }
*/
export function getKeyStringValueOutData(title, data) {
let dataList = [];
let count = 0;
for (let key in data) {
let addData = {key, value:data[key]};
dataList.push(addData);
count += 1;
}
return { title, dataList, count};
}
/**
* getScatterFigureOutData 获取撒点图的返回结果
* @param title 标题
* @param data 数据 格式 [{x, y, name}, {x, y, name}, {x, y, name}, {x, y, name}]
* @returns { title:标题, xMax:x轴最大值, xMin:x最小值, yMax:y最大值, yMin:y最小值, dataList:[{name:点的名称, value:[x坐标, y坐标]} ] };
*/
export function getScatterFigureOutData(title, data) {
let dataList = [];
let xMaxNumber = 0;
let xMinNumber = new Date().valueOf();
let yMaxNumber = 0;
let yMinNumber = new Date().valueOf();
data.forEach(item => {
let { x, y, name } = item;
let xCoordinateInfo = separateDataAndUint(x);
let yCoordinateInfo = separateDataAndUint(y);
const XNumber = xCoordinateInfo.dataNum;
const YNumber = yCoordinateInfo.dataNum;
yMaxNumber = Math.max(YNumber, yMaxNumber);
yMinNumber = Math.min(YNumber, yMinNumber);
xMaxNumber = Math.max(XNumber, xMaxNumber);
xMinNumber = Math.min(XNumber, xMinNumber);
let value = [XNumber, YNumber];
dataList.push({ value, name:name || "" });
});
let xMaxMinInfo = unifiedMaxAndMinValueAndStep(xMaxNumber, xMinNumber);
let yMaxMinInfo = unifiedMaxAndMinValueAndStep(yMaxNumber, yMinNumber);
return { title, xMax:xMaxMinInfo.maxNumber, xMin:xMaxMinInfo.minNumber, yMax:yMaxMinInfo.maxNumber, yMin:yMaxMinInfo.minNumber, dataList };
}
//仅限cal中使用的工具 禁止做任何修改
/**
* separateDataAndUint 截取字符串中的单位
* @param str 待处理字符串
* @returns {dataNumber:数据, dataUnit:单位}
*/
export function separateDataAndUint(str) {
str = `${str}`;
if (!str) return {dataNum:0, dataUnit:""};
let dataNum = parseFloat(str.replace(/[\u4E00-\u9FA5a-zA-Z]+/,""));
let dataUnit = str.replace(/^(-)?\d+(\.\d+)?/, "");
return {dataNum, dataUnit};
}
/**
* getUnitMaxOccNum 获取出现次数最多的单位
* @param unitMap 统计后的出现过的单位情况 结构{unit:出现次数}
* @returns 出现次数最多的单位
*/1
export function getUnitMaxOccNum(unitMap) {
let max = 0;
let maxUnit = "";
for (let unit in unitMap) {
let occNum = unitMap[unit];
if (occNum > max) {
max = occNum;
maxUnit = unit;
}
}
return maxUnit;
}
/**
* unifiedMaxAndMinValueAndStep 求最大最小值以及间隙 固定分10份
* @param max 最大
* @param min 最小
* @returns {maxNumber:向上留值最大, minNumber:向下留值最小, stepNumber:间隔};
*/
export function unifiedMaxAndMinValueAndStep(max, min) {
let maxNumber = Math.ceil(max);
let minNumber = Math.floor(min);
function getNumberInLength(length) {
let lengthCount = 1;
for (let i = 1; i < length; i++) {
lengthCount = lengthCount * 10;
}
return lengthCount;
}
let maxNumberLength = getNumberInLength(`${maxNumber}`.length);
let minNumberLength = getNumberInLength(`${minNumber}`.length);
if (maxNumber <= 10 && maxNumber > 0) maxNumber = 10;
else maxNumber = Math.ceil(maxNumber / maxNumberLength) * maxNumberLength;
minNumber = Math.floor(minNumber / minNumberLength) * minNumberLength;
let stepNumber = Math.ceil((maxNumber - minNumber) / 10);
return {maxNumber, minNumber, stepNumber};
}
\ No newline at end of file
export enum ERRORENUM {
参数错误=`参数错误`,
}
\ No newline at end of file
import mongoose = require('mongoose');
import mongoClient = require('mongodb');
let defaultOptions = {
// useNewUrlParser:true,
auto_reconnect:true,
reconnectTries:1000,
reconnectInterval:3000,
keepAlive: 1,
connectTimeoutMS: 30000
};
export async function createDbConnect(connectUrl:string, options?:object) {
if (!connectUrl) throw new Error(`wrong connect url ${connectUrl}`);
if (!options) options = defaultOptions;
console.log("connection mongo=> ",connectUrl);
return await mongoose.createConnection(connectUrl, options).catch((err)=>{throw err});
}
//初始化db
import { mongoServerConstVal } from '../../serverConfig';
import {createDbConnect} from './db_connect';
import { tableInit } from './table_init';
let db;
export async function init() {
console.log('connect to mongodb success');
db = await createDbConnect(mongoServerConstVal.dbUrl).catch((err)=>{throw err;});
process.stdin.emit('dbinit success');
tableInit();
}
export {db};
\ No newline at end of file
export function tableInit() {
console.log("tableinit success");
}
\ No newline at end of file
import * as mysql from 'mysql'
export function createMySqlConnect(host:string, port:number, user:string, password:string, database:string) {
return mysql.createConnection({ host, port, user, password, database });
}
import { mySqlConfig } from '../../serverConfig';
import { createMySqlConnect} from './mysql_connect';
let mysql_ddptDB;
export function initMysqlDB() {
const dataBase = 'ddpt';
mysql_ddptDB = createMySqlConnect(mySqlConfig.mysqlHost, mySqlConfig.mysqlPort, mySqlConfig.mysqlUser, mySqlConfig.mysqlPwd, dataBase);
mysql_ddptDB.connect(handleError);
mysql_ddptDB.on('error', handleError);
}
function handleError (err) {
if (err) {
// 如果是连接断开,自动重新连接
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
initMysqlDB();
} else {
console.error(err.stack || err);
}
}
}
export { mysql_ddptDB };
\ No newline at end of file
import { getPort } from "./serverConfig";
async function lanuch() {
//逻辑
test();
}
function test() {
// testMaxMin();
}
lanuch();
\ No newline at end of file
export async function encryptionReturn(req, res, next) {
res.on('end', function(){
console.log(res.body);
});
let resSend = res.send;
res.send = (obj)=>{
changeNumber(obj);
//递归修改number型
resSend.call(res, obj);
};
next();
}
function changeNumber(obj) {
if (Array.isArray(obj)) {
for (let i = 0; i < obj.length; i++) {
let arrItem = obj[i];
if (typeof arrItem == "number") {
obj[i] = getSameLenNumber(arrItem);
}
else if (typeof arrItem == "object") {
changeNumber(arrItem);
}
}
}
else {
for (let key in obj) {
let objItem = obj[key];
if (typeof objItem == "number") {
if (key == "x" || key == "y") continue;
obj[key] = getSameLenNumber(objItem);
}
else if (typeof objItem == "object") {
changeNumber(objItem);
}
}
}
}
function getSameLenNumber(num) {
let numStr = String(num);
//疑似年份的不做加密
if (numStr.length == 4 && (numStr.indexOf("19") == 0 || numStr.indexOf("20") == 0)) return num;
let str = "";
for (let i = 0; i < numStr.length; i++) {
if (numStr[i] == '.') str += numStr[i];
else str += "6";
}
return Number(str);
}
\ No newline at end of file
var formidable = require("formidable");
export async function parseFormParam(req, res, next) {
    var form = new formidable.IncomingForm();
    form.parse(req, (err, fields, files)=>{
        if (err) {
            next(err)
        }
        else {
            req.fields = fields;
            req.files = files;
            next();
        }
    })
}
\ No newline at end of file
import express = require('express');
import bodyParser = require('body-parser');
import sign = require('../middleware/sign');
import routers = require('../routers/router');
import compression = require('compression');
import { encryptionReturn } from '../middleware/encryptionReturn';
import { getEnv } from '../serverConfig';
export class httpServer {
static createServer(port:number) {
var httpServer = express();
httpServer.all('*',function (req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header('Access-Control-Allow-Credentials', true);
res.header("X-Powered-By", ' 3.2.1');
if(req.method === 'OPTIONS'){
res.statusCode = 200;
res.end();
}else{
next();
}
});
httpServer.use(express.static('public') );
httpServer.use(bodyParser.json({limit:"10kb"}));
httpServer.use(compression())
//演示环境加密数据
if (getEnv() == "dem") {
console.log("演示环境 开启数据加密");
httpServer.use(encryptionReturn);
}
routers.setRouter(httpServer);
httpServer.listen(port);
console.log('server listen on port:'+port);
return httpServer;
}
}
export function setRouter(httpServer) {
}
\ No newline at end of file
//端口
export function getPort() : number {
return Number(process.env.PORT) || Number(process.argv[3]) || 7536;
}
// sit 测试环境 prod 生产环境 dem 演示环境(测试数据,前端无密码访问)
export function getEnv() : string {
return process.argv[2] || "sit";
}
//mongo数据库连接字符
export const mongoServerConstVal = {
dbUrl:'mongodb://192.168.12.79:27017/zjsc?w=1&wtimeoutMS=30000'
}
//mysql数据库连接对象
export const mySqlConfig = {
mysqlHost: 'localhost',
mysqlPort: 3306,
mysqlUser: 'root',
mysqlPwd: '123456',
// mysqlHost:'10.96.240.55',
// mysqlPort:3306,
// mysqlUser:'ddtest',
// mysqlPwd:'ddtest123^',
};
export const interfaceConfig = {
企业信息数据列表: '/openapi/company/list',
创投机构数据列表: '/openapi/investorg/list',
科技金融产品: '/openapi/product/list'
}
\ No newline at end of file
//新的解析
const fs = require('fs');
const xlsx = require('node-xlsx');
const path = require('path');
const moment = require('moment');
/**
* getExcelDataBySheetName 将excel文件解析成数据块数据
* @param fileName 文件名称
* @param sheetName 表名称
* @returns thisBlockData 返回数据块集合 格式:blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
*/
export function getExcelDataBySheetName(fileName, sheetName) {
let {sheetMap, sheetList} = getExcel( path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", fileName ));
let thisBlockData = getBlockData(sheetMap[sheetName]);
return thisBlockData;
}
/**
* getBlockDataByData 将excel解析出来的二维数组解析成数据块模式
* @param dataList excel解出来的数据
* @returns thisBlockData 返回数据块集合 格式:blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
*/
export function getBlockDataByData(dataList) {
let thisBlockData = getBlockData(dataList);
return thisBlockData;
}
/**
* getBlockData 数据分块
* @param dataList 解析出来的excel二维数组
* @returns 返回数据块集合 格式:blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
*/
function getBlockData(dataList) {
let blockList = [];
for (let i = 0; i < 999; i++) {
let {blockData, blockTitle, notItem, delDataList} = checkBlock(dataList);
if (notItem) break;
dataList = delDataList;
if (blockTitle) blockList.push({blockData, blockTitle});
}
return blockList;
}
function getListFristNotNullItemIndex(list) { //获取起始坐标
if (!list.length) return null;
for (let i = 0; i < list.length; i++) {
if (list[i]) return i;
}
}
function getListFirstNullItemIndex(startX, list) { //获取第一个为空的坐标
if (!list.length) return null;
let checkItem = false;
let firstItemIndex = 0;
for (let i = startX; i <= list.length; i++) {
let item = list[i];
if (!checkItem && item) checkItem = true;
if (checkItem && !item) {
firstItemIndex = i;
break;
}
}
return firstItemIndex;
}
function listRegionIsNull(list, startX, endX) { //指定区间内数据是否未空
let isNull = true;
if ( !list.length ) return isNull;
for (let i = startX; i < endX; i++) {
let item = list[i];
if (item) {
isNull = false;
break;
}
}
return isNull;
}
function thisListNotItem(list) {
for (let i = 0; i < list.length; i++) {
if (list[i]) return false;
}
return true
}
function checkBlock(dataList) {
//纵向有效起始点
let startY = 0;
let startX = 0;
let isNotBlockTitle = false; //没有块标题
let isLook = false;
let endX = 0;//x轴最长结束下标 【包括下标】
let blockTitle = ''; //标题块名称
let notItem = true;
for (let i = 0; i < dataList.length; i++) {
let childList = dataList[i] || [];
if (!thisListNotItem(childList)) {
if ( !isLook ) {
let thisRoowStartX = getListFristNotNullItemIndex(childList);
let thisRoowLastItem = childList[thisRoowStartX + 1];
let LastList = dataList[i+1] || [];
// let lastRoowStartX = getListFristNotNullItemIndex(LastList);
let lastRoowHaveItem = LastList[thisRoowStartX];
if ( thisRoowLastItem || (LastList.length && lastRoowHaveItem) ) {
if (lastRoowHaveItem && thisRoowLastItem ) {
isNotBlockTitle = true; //不存在标题块
blockTitle = `${thisRoowStartX}_${i}`;
startY = i;
startX = thisRoowStartX;
}
else {
blockTitle = dataList[i][thisRoowStartX];
dataList[i][thisRoowStartX] = null;
if ( thisRoowLastItem ) { // 同行存在元素 标题在y轴上
startY = i;
startX = thisRoowStartX + 1;
} else { // 同行存在元素 标题在x轴上
startY = i + 1;
startX = thisRoowStartX;
}
}
isLook = true;
} else { //只有标题 无内容
console.log(dataList[i][thisRoowStartX]);
dataList[i][thisRoowStartX] = null;
}
} else {
//测量最大连续长度
let firstNullX = getListFirstNullItemIndex(startX, childList);
if (firstNullX) endX = Math.max(endX, firstNullX-1);
break;
}
notItem = false;
}
}
let endY = 0;//y轴连续下标 【包括下标】
let yInfoStart = false;
let yInfoEnd = false;
for (let y = startY; y < dataList.length; y++) {
//纵向找连续性
let thisRoow = dataList[y];
let regionIsNull = listRegionIsNull(thisRoow, startX, endX);
if (!regionIsNull) {
endY = y;
if (!yInfoStart) yInfoStart = true;
}
if (yInfoStart && regionIsNull) yInfoEnd = true;
if (yInfoEnd) break;
}
let blockData = [];
for (let y = startY; y <= endY; y++) {
let onceList = [];
for (let x = startX; x <= endX; x++) {
onceList.push(dataList[y][x]);
dataList[y][x] = null;
}
blockData.push(onceList);
}
return {blockData, blockTitle, delDataList:dataList,notItem};
}
//获取单个excel文件的数据
function getExcel(filePath) {
const workSheetsFromFile = xlsx.parse(filePath);
let sheetMap = {};
let sheetList = [];
for (let i = 0; i < workSheetsFromFile.length; i++) {
let sheetInfo = workSheetsFromFile[i];
sheetMap[sheetInfo.name] = sheetInfo.data;
sheetList.push(sheetInfo);
}
return {sheetMap, sheetList}
}
\ No newline at end of file
export class BizError extends Error {
}
\ No newline at end of file
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"sourceMap": true,
"rootDir":"./src",
"outDir":"./out"
},
"exclude": [
"node_modules"
]
}
\ 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