From a5aa469a8844511f0d918d819fd76dfc418119dd Mon Sep 17 00:00:00 2001 From: xiaojin Date: Fri, 2 Jul 2021 16:35:34 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B3=20chore(=E5=B7=A5=E5=85=B7):=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E5=AF=BC=E8=A1=A8=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/dns-server/README.md | 9 - docker/dns-server/docker-compose.yml | 14 - docker/dns-server/etc/dnsmasq.conf | 2 - docker/dns-server/etc/dnsmasqhosts | 1 - docker/dns-server/etc/resolv.dnsmasq | 3 - docs/README.md | 13 +- framework/service/group.lua | 1 + framework/service/guild_generator.lua | 52 --- framework/service/{zlogd.lua => logger.lua} | 43 +- tools/excel_exporter/.gitignore | 109 +++++ tools/excel_exporter/README.md | 4 + tools/excel_exporter/build.sh | 2 + tools/excel_exporter/lua2json.js | 239 ++++++++++ tools/excel_exporter/lua2xlsx.js | 180 ++++++++ tools/excel_exporter/pack.js | 83 ++++ tools/excel_exporter/package-lock.json | 459 ++++++++++++++++++++ tools/excel_exporter/package.json | 28 ++ tools/excel_exporter/xlsx2lua.js | 335 ++++++++++++++ 18 files changed, 1490 insertions(+), 87 deletions(-) delete mode 100644 docker/dns-server/README.md delete mode 100644 docker/dns-server/docker-compose.yml delete mode 100644 docker/dns-server/etc/dnsmasq.conf delete mode 100644 docker/dns-server/etc/dnsmasqhosts delete mode 100644 docker/dns-server/etc/resolv.dnsmasq create mode 100644 framework/service/group.lua delete mode 100644 framework/service/guild_generator.lua rename framework/service/{zlogd.lua => logger.lua} (76%) create mode 100644 tools/excel_exporter/.gitignore create mode 100644 tools/excel_exporter/README.md create mode 100644 tools/excel_exporter/build.sh create mode 100644 tools/excel_exporter/lua2json.js create mode 100644 tools/excel_exporter/lua2xlsx.js create mode 100644 tools/excel_exporter/pack.js create mode 100644 tools/excel_exporter/package-lock.json create mode 100644 tools/excel_exporter/package.json create mode 100644 tools/excel_exporter/xlsx2lua.js diff --git a/docker/dns-server/README.md b/docker/dns-server/README.md deleted file mode 100644 index e0ab7a6..0000000 --- a/docker/dns-server/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# dns 服务 - -用于开发中区分测试环境、预生产、显示环境的域名解析 - -镜像使用 [https://hub.docker.com/r/andyshinn/dnsmasq](https://hub.docker.com/r/andyshinn/dnsmasq) - -## 优点 -1. 可以省去频繁的修改本地hosts文件 -2. 可统一公司内部人员的域名解析一致 diff --git a/docker/dns-server/docker-compose.yml b/docker/dns-server/docker-compose.yml deleted file mode 100644 index f5c351b..0000000 --- a/docker/dns-server/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: '3' - -services: - dnsmasq: - image: andyshinn/dnsmasq:2.75 - cap_add: - - NET_ADMIN - ports: - - "53:53/tcp" - - "53:53/udp" - volumes: - - ./etc/resolv.dnsmasq:/etc/resolv.dnsmasq - - ./etc/dnsmasq.conf:/etc/dnsmasq.conf - - ./etc/dnsmasqhosts:/etc/dnsmasqhosts diff --git a/docker/dns-server/etc/dnsmasq.conf b/docker/dns-server/etc/dnsmasq.conf deleted file mode 100644 index eb95baa..0000000 --- a/docker/dns-server/etc/dnsmasq.conf +++ /dev/null @@ -1,2 +0,0 @@ -resolv-file=/etc/resolv.dnsmasq -addn-hosts=/etc/dnsmasqhosts diff --git a/docker/dns-server/etc/dnsmasqhosts b/docker/dns-server/etc/dnsmasqhosts deleted file mode 100644 index 603591a..0000000 --- a/docker/dns-server/etc/dnsmasqhosts +++ /dev/null @@ -1 +0,0 @@ -192.168.9.9 hehe.my.com diff --git a/docker/dns-server/etc/resolv.dnsmasq b/docker/dns-server/etc/resolv.dnsmasq deleted file mode 100644 index 832d22e..0000000 --- a/docker/dns-server/etc/resolv.dnsmasq +++ /dev/null @@ -1,3 +0,0 @@ -nameserver 114.114.114.114 -nameserver 223.6.6.6 -nameserver 8.8.8.8 diff --git a/docs/README.md b/docs/README.md index cf4c18e..ba8920a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,7 +21,9 @@ aoe 技能的拾取是 一帧内的下一tick 处理 以引用计数来统计 是否已经达到下一步的要求 数据库操作 key 都以 crc16 算法确定链路 而且都是 encode 完再 -发到 对应的db 服 这样会减少2次 打包 table的 开销 +发到 对应的db 服 这样会减少2次 打包 table的 cpu 开销 +玩家以 hash 类型 存储 可以 按 核心 活动 或者其他的 分为 多个 hash 值 +这样能保证 key 太多的问题 在 加载的时候 可以 利用 redis pipe 加快访问 并且 数据缓存 需要 按 只查询 和 可读写来划分隔离出来2部分通过 lru 来管理 要不然会把 老数据残留的问题 @@ -50,4 +52,11 @@ https://blog.codingnow.com/2007/11/inertia_thinking.html - minor_multiplier 控制年轻对象收集倍率,对于一个倍率`X`, 新的`minor collection`将会在内存使用比上次`major collection`后增长`X%`时完成. 默认值是20,最大值200 - major_multiplier 控制年老对象收集倍率,对于一个倍率`X`, 新的`major collection`将会在内存使用比上次`major collection`后增长`X%`时完成. 默认值是100,最大值1000 - 分代GC 是用这两个参数控制 \ No newline at end of file + 分代GC 是用这两个参数控制 + + iptables -I INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT + + Filebeat+Kafka+Logstash+ElasticSearch+Kibana 日志采集方案 + +- skynet debug console 使用 + - https://blog.hanxi.cc/p/73/ \ No newline at end of file diff --git a/framework/service/group.lua b/framework/service/group.lua new file mode 100644 index 0000000..6bc4cce --- /dev/null +++ b/framework/service/group.lua @@ -0,0 +1 @@ +-- 服务组模版 \ No newline at end of file diff --git a/framework/service/guild_generator.lua b/framework/service/guild_generator.lua deleted file mode 100644 index 28a8d61..0000000 --- a/framework/service/guild_generator.lua +++ /dev/null @@ -1,52 +0,0 @@ -local skynet = require "skynet" -local time = skynet.time -local floor = math.floor -local ceil = math.ceil - ---[[ -sign | delta seconds | worker id | sequence -1bit | 30bits | 20bits | 13bits - -sign - 0为正数 1为负数 -delta seconds - 2020/01/01到当前时间时间差, 30bits可以用到2054-01-09 -worker id - 0~1048575 每个服务worker id都应该不一样,才能保证唯一性, worker_id需使用者自行规划 -sequence - 0~8191 当前时刻的id序列 -]] - -local DELTA_SECS_BITS = 30 -local WORKER_ID_BITS = 20 -local SEQ_BITS = 13 -local TIME_LEFT_SHIFT_BITS = WORKER_ID_BITS + SEQ_BITS - -local START_TIME = 1577808000 -- 2020/01/01 -local MAX_WORKER_ID = (1<= 0 and worker_id <= MAX_WORKER_ID) - -local seq = 0 -local last_delta_time = 0 -local gen_guid - -gen_guid = function() - local now = time() - local floor_now = floor(now) - local delta_time = floor_now - START_TIME - if last_delta_time ~= delta_time then - last_delta_time = delta_time - seq = 0 - elseif seq < MAX_SEQ then - seq = seq + 1 - else - skynet.sleep(100 - ceil(now - floor_now)*100) - return gen_guid() - end - return (delta_time< max) { + max = id; + } + count++; + } + //console.log(count, max, count==(firstNumber==0?1+max:max)); + return count > 1 && count == (firstNumber == 0 ? 1 + max : max); +} + +function runCompact(obj) { + var objName = Object.keys(obj)[0]; + if (compactMap.hasOwnProperty(objName)) { + var tagId = 0; + var objKeysName = compactMap[objName]; + var tagMap = {}; + var objMap = {}; + + var oldMap = obj[objName]; + for (var key in oldMap) { + objMap[key] = []; + for (var tagKey in oldMap[key]) { + var id = tagId; + if (tagMap.hasOwnProperty(tagKey)) { + id = tagMap[tagKey]; + } else { + tagMap[tagKey] = tagId; + tagId++; + } + objMap[key][id] = oldMap[key][tagKey]; + } + } + + var newObj = {}; + newObj[objKeysName] = tagMap; + newObj[objName] = objMap; + return newObj; + /*/ + } + else if(shouldBeArray(obj)) { + var oldMap = obj[objName]; + var objMap = {}; + + for (var key in oldMap) { + objMap[key] = []; + for(var id in oldMap[key]) { + objMap[key][id - 1] = oldMap[key][id]; + } + } + + var newObj = {}; + newObj[objName] = objMap; + return newObj; + //*/ + } else { + return obj; + } +} + +function mkdirs(dirname, callback) { + if (fs.existsSync(dirname)) { + if (callback != undefined) { + callback(); + } + } else { + mkdirs(path.dirname(dirname), function () { + fs.mkdirSync(dirname); + if (callback != undefined) { + callback(); + } + }); + } +} + +function insertStr(soure, start, newStr) { + return soure.slice(0, start) + newStr + soure.slice(start); +} + +function encodeQuote(str) { + if (str[0] != '"' || str[str.length - 1] != '"') { + return str; + } + var i = 1; + var f; + while ((f = str.indexOf('"', i)) != -1 && f < str.length - 1) { + str = insertStr(str, f, "\\"); + //console.log(f, str); + i = f + 2; + } + return str; +} + +var countExport = 0; +function handleFile(fileDir) { + var content = fs.readFileSync(fileDir, "utf8"); + content = content.replace(/(LAN.\w+.\w+)/g, function ($0, $1) { + var str = $1; + //console.log(str); + str = `"${lang[str]}"`; + str = encodeQuote(str); + //console.log($1, str); + return str; + }); + //return; + //console.log(content); + //var exportFile1 = 'out_test/' + countExport + '.lua'; + //mkdirs(path.dirname(exportFile1)); + //fs.writeFileSync(exportFile1, content, 'utf-8'); + + var obj = lua2json.parse(`return {${content}}`); + obj = runCompact(obj); + + var outStr = JSON.stringify(obj); + countExport++; + var exportFile = outDir + "/" + countExport + ".json"; + console.log(fileDir, "->", exportFile); + mkdirs(path.dirname(exportFile)); + fs.writeFileSync(exportFile, outStr, "utf-8"); +} + +function handleLanguage(fileDir) { + console.log("lang:" + fileDir); + var content = fs.readFileSync(fileDir, "utf8"); + //console.log(content); + var obj = lua2json.parse(`return {${content}}`); + //console.log(obj); + for (var key in obj) { + //console.log(key); + for (var key2 in obj[key]) { + lang[`LAN.${key}.${key2}`] = obj[key][key2].replace(/\n/g, "\\n"); + } + } + //console.log(Object.keys(lang).length); +} + +function handleDir(filePath, callback, except) { + //根据文件路径读取文件,返回文件列表 + try { + var files = fs.readdirSync(filePath); + //遍历读取到的文件列表 + files.forEach(function (filename) { + if (except != undefined && filename.includes(except)) { + return; + } + //获取当前文件的绝对路径 + var filedir = path.join(filePath, filename); + //根据文件路径获取文件信息,返回一个fs.Stats对象 + var stats = fs.statSync(filedir); + var isFile = stats.isFile(); //是文件 + var isDir = stats.isDirectory(); //是文件夹 + if (isFile) { + //console.log(filedir); + callback(filedir); + } + if (isDir) { + handleDir(filedir, callback, except); //递归,如果是文件夹,就继续遍历该文件夹下面的文件 + } + }); + } catch (e) { + //not found + console.warn(`Err occurs: ${e}`); + } +} + +function removeDir(p) { + if (!fs.existsSync(p)) { + return; + } + let statObj = fs.statSync(p); // fs.statSync同步读取文件状态,判断是文件目录还是文件。 + if (statObj.isDirectory()) { //如果是目录 + let dirs = fs.readdirSync(p); //fs.readdirSync()同步的读取目标下的文件 返回一个不包括 '.' 和 '..' 的文件名的数组['b','a'] + dirs = dirs.map((dir) => path.join(p, dir)); //拼上完整的路径 + for (let i = 0; i < dirs.length; i++) { + // 深度 先将儿子移除掉 再删除掉自己 + removeDir(dirs[i]); + } + fs.rmdirSync(p); //删除目录 + } else { + fs.unlinkSync(p); //删除文件 + } +} + +removeDir(outDir); + +var lang_dir = `${srcDir}/language/lang`; +if (fs.existsSync(lang_dir)) { + console.log("importing language"); + handleDir(lang_dir, handleLanguage); + console.log("imported language item:", Object.keys(lang).length); +} + +handleDir(srcDir, handleFile, "language"); diff --git a/tools/excel_exporter/lua2xlsx.js b/tools/excel_exporter/lua2xlsx.js new file mode 100644 index 0000000..7786083 --- /dev/null +++ b/tools/excel_exporter/lua2xlsx.js @@ -0,0 +1,180 @@ +"use strict"; +var XLSX = require("xlsx"); +var fs = require("fs"); +var path = require("path"); + +var options = process.argv; +if (options.length < 4) { + console.log("需要2个参数(src out)"); + process.exit(); +} + +var srcDir = options[2]; +var outDir = options[3]; + +function mkdirs(dirname, callback) { + if (fs.existsSync(dirname)) { + if (callback != undefined) { + callback(); + } + } else { + mkdirs(path.dirname(dirname), function () { + fs.mkdirSync(dirname); + if (callback != undefined) { + callback(); + } + }); + } +} + +function insertStr(soure, start, newStr) { + return soure.slice(0, start) + newStr + soure.slice(start); +} + +function encodeQuote(str) { + if (str[0] != '"' || str[str.length - 1] != '"') { + return str; + } + var i = 1; + var f; + while ((f = str.indexOf('"', i)) != -1 && f < str.length - 1) { + str = insertStr(str, f, "\\"); + //console.log(f, str); + i = f + 2; + } + return str; +} + +var countExport = 0; +function handleFile(fileDir) { + var content = fs.readFileSync(fileDir, "utf8"); + var contents = content.split("\n"); + + var exportHead = contents[0]; + var exportTail = contents[contents.length - 1]; + + var i = 1; + + var numKeys = 0; + while (true) { + var re = contents[i + numKeys].match(/\[\d+\] *= *\{/g); + if (re == null) { + break; + } + numKeys++; + //console.log(re); + } + console.log("keys", numKeys); + var exportType = (numKeys > 0 ? "base" : "tiny"); + + var fileName = fileDir.replace(/^.*[\\\/]/, ""); + var exportFile = outDir + "/" + fileName + ".xlsx"; + mkdirs(path.dirname(exportFile)); + var data = []; + data[0] = ["导出类型", exportType, "", "导出文件头", exportHead]; + data[1] = ["导出文件", fileDir, "", "导出文件尾", exportTail]; + data[2] = ["key数量", numKeys]; + data[3] = []; + if (numKeys > 0) { + var numAttr = 0; + while (true) { + var re = contents[i + numKeys + numAttr].match(/ \}\,/g); + //console.log(re); + if (re != null) { + break; + } + numAttr++; + } + console.log("attr", numAttr); + + data[4] = ["配置备注"]; + data[5] = ["导出参数"]; + data[6] = ["备注"]; + + for (var ai = 0; ai < numAttr; ai++) { + data[5][1 + ai] = "sc"; + var re = contents[i + numKeys + ai].match(/\t(\w+) *=/); + if (re != null) { + //console.log(re[1]); + var attrName = re[1]; + data[6][1 + ai] = attrName; + } + } + + for ( + var row = 7; + i + numKeys + numAttr < contents.length; + i += 2 * numKeys + numAttr + ) { + //console.log(i); + data[row] = []; + for (var ai = 0; ai < numAttr; ai++) { + var re = contents[i + numKeys + ai].match(/ *= *([^\n]+),/); + if (re != null) { + //console.log(re[1]); + data[row][1 + ai] = re[1]; + } + } + row++; + } + } else { + data[4] = ["配置备注", "导出参数", "字段名", "值", "备注"]; + for (var row = 5; row - 4 < contents.length - 1; row++) { + var re = contents[row - 4].match(/\t(\w+) *= *([^\n]+),/); + if (re != null) { + //console.log(re); + data[row] = ["", "sc", re[1], re[2]]; + } + } + } + + var ws = XLSX.utils.aoa_to_sheet(data); + var wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, fileName); + + console.log(fileDir, "->", exportFile); + XLSX.writeFile(wb, exportFile); + countExport++; +} + +function handleDir(filePath) { + //根据文件路径读取文件,返回文件列表 + var files = fs.readdirSync(filePath); + //遍历读取到的文件列表 + files.forEach(function (filename) { + //获取当前文件的绝对路径 + var filedir = path.join(filePath, filename); + //根据文件路径获取文件信息,返回一个fs.Stats对象 + var stats = fs.statSync(filedir); + var isFile = stats.isFile(); //是文件 + var isDir = stats.isDirectory(); //是文件夹 + if (isFile) { + //console.log(filedir); + handleFile(filedir); + } + if (isDir) { + handleDir(filedir); //递归,如果是文件夹,就继续遍历该文件夹下面的文件 + } + }); +} + +function removeDir(p) { + if (!fs.existsSync(p)) { + return; + } + let statObj = fs.statSync(p); // fs.statSync同步读取文件状态,判断是文件目录还是文件。 + if (statObj.isDirectory()) { //如果是目录 + let dirs = fs.readdirSync(p); //fs.readdirSync()同步的读取目标下的文件 返回一个不包括 '.' 和 '..' 的文件名的数组['b','a'] + dirs = dirs.map((dir) => path.join(p, dir)); //拼上完整的路径 + for (let i = 0; i < dirs.length; i++) { + // 深度 先将儿子移除掉 再删除掉自己 + removeDir(dirs[i]); + } + fs.rmdirSync(p); //删除目录 + } else { + fs.unlinkSync(p); //删除文件 + } +} + +removeDir(outDir); +handleDir(srcDir); diff --git a/tools/excel_exporter/pack.js b/tools/excel_exporter/pack.js new file mode 100644 index 0000000..f43278d --- /dev/null +++ b/tools/excel_exporter/pack.js @@ -0,0 +1,83 @@ +// require modules +var fs = require('fs'); +var archiver = require('archiver'); +var path = require('path'); + +var options = process.argv; +if(options.length < 4) +{ + console.log("需要2个参数(src out)"); + process.exit(); +} + +var srcDir = options[2]; +var outFile = options[3]; + +// create a file to stream archive data to. +var output = fs.createWriteStream(__dirname + '/' + outFile); +var archive = archiver('zip', { + zlib: { level: 9 } // Sets the compression level. +}); + +// listen for all archive data to be written +// 'close' event is fired only when a file descriptor is involved +output.on('close', function() { + console.log(archive.pointer() + ' total bytes'); + console.log('archiver has been finalized and the output file descriptor has closed.'); +}); + +// This event is fired when the data source is drained no matter what was the data source. +// It is not part of this library but rather from the NodeJS Stream API. +// @see: https://nodejs.org/api/stream.html#stream_event_end +output.on('end', function() { + console.log('Data has been drained'); +}); + +// good practice to catch warnings (ie stat failures and other non-blocking errors) +archive.on('warning', function(err) { + if (err.code === 'ENOENT') { + // log warning + } else { + // throw error + throw err; + } +}); + +// good practice to catch this error explicitly +archive.on('error', function(err) { + throw err; +}); + +// pipe archive data to the file +archive.pipe(output); + + +// append files from a glob pattern +//archive.glob(srcDir+'/*.json'); + +function handleFile(fileDir, filename) { + archive.file(fileDir, { name: filename }); +} + +function handleDir(filePath) { + //根据文件路径读取文件,返回文件列表 + var files = fs.readdirSync(filePath); + //遍历读取到的文件列表 + files.forEach(function(filename){ + //获取当前文件的绝对路径 + var filedir = path.join(filePath,filename); + //根据文件路径获取文件信息,返回一个fs.Stats对象 + var stats = fs.statSync(filedir); + var isFile = stats.isFile();//是文件 + var isDir = stats.isDirectory();//是文件夹 + if(isFile && filedir.endsWith(".json")){ + //console.log(filedir); + handleFile(filedir, filename); + } + }); +} + +handleDir(srcDir); +// finalize the archive (ie we are done appending files but streams have to finish yet) +// 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand +archive.finalize(); diff --git a/tools/excel_exporter/package-lock.json b/tools/excel_exporter/package-lock.json new file mode 100644 index 0000000..ec33848 --- /dev/null +++ b/tools/excel_exporter/package-lock.json @@ -0,0 +1,459 @@ +{ + "name": "xy-excel-exporter", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "adler-32": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/adler-32/download/adler-32-1.2.0.tgz", + "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "archiver": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/archiver/download/archiver-3.1.1.tgz", + "integrity": "sha1-nbeBnU2vYK7BD+hrFsuSWM7WbqA=", + "requires": { + "archiver-utils": "^2.1.0", + "async": "^2.6.3", + "buffer-crc32": "^0.2.1", + "glob": "^7.1.4", + "readable-stream": "^3.4.0", + "tar-stream": "^2.1.0", + "zip-stream": "^2.1.2" + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/archiver-utils/download/archiver-utils-2.1.0.tgz", + "integrity": "sha1-6KRg6UtpPD49oYKgmMpihbqSSeI=", + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz", + "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=", + "requires": { + "lodash": "^4.17.14" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz", + "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=" + }, + "bl": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/bl/download/bl-3.0.0.tgz", + "integrity": "sha1-NhHsAFef0YVhdUNgsh6feEUA/4g=", + "requires": { + "readable-stream": "^3.0.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.4.3", + "resolved": "https://registry.npm.taobao.org/buffer/download/buffer-5.4.3.tgz?cache=0&sync_timestamp=1573257183822&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbuffer%2Fdownload%2Fbuffer-5.4.3.tgz", + "integrity": "sha1-P7ycaetxPTI+P8Gole7gcQwHIRU=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npm.taobao.org/buffer-crc32/download/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "cfb": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/cfb/download/cfb-1.1.3.tgz", + "integrity": "sha1-Bd5oFiWcjovDJxOrqQVgjuOF32Y=", + "requires": { + "adler-32": "~1.2.0", + "commander": "^2.16.0", + "crc-32": "~1.2.0", + "printj": "~1.1.2" + } + }, + "codepage": { + "version": "1.14.0", + "resolved": "https://registry.npm.taobao.org/codepage/download/codepage-1.14.0.tgz", + "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", + "requires": { + "commander": "~2.14.1", + "exit-on-epipe": "~1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.14.1.tgz", + "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=" + } + } + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz", + "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=" + }, + "compress-commons": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/compress-commons/download/compress-commons-2.1.1.tgz?cache=0&sync_timestamp=1564787277684&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcompress-commons%2Fdownload%2Fcompress-commons-2.1.1.tgz", + "integrity": "sha1-lBDZpTTPhDXj+7t8bOSN4twvBhA=", + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^3.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npm.taobao.org/crc/download/crc-3.8.0.tgz", + "integrity": "sha1-rWAmnCyFb4wpnixMwN5FVpFAVsY=", + "requires": { + "buffer": "^5.1.0" + } + }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/crc-32/download/crc-32-1.2.0.tgz", + "integrity": "sha1-yy224puIUI4y2d0OwWk+e0Ghggg=", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "crc32-stream": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/crc32-stream/download/crc32-stream-3.0.1.tgz", + "integrity": "sha1-yubu7QA7DkTXOdJ53lrmOxcbToU=", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^3.4.0" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz?cache=0&sync_timestamp=1569416367473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fend-of-stream%2Fdownload%2Fend-of-stream-1.4.4.tgz", + "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", + "requires": { + "once": "^1.4.0" + } + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/exit-on-epipe/download/exit-on-epipe-1.0.1.tgz", + "integrity": "sha1-C92S6H1ShdJn2qgXHQ6wYVlolpI=" + }, + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/frac/download/frac-1.1.2.tgz", + "integrity": "sha1-PXT39keMiKG1AgMG10fcYxPHTQs=" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/fs-constants/download/fs-constants-1.0.0.tgz", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz?cache=0&sync_timestamp=1573078079496&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob%2Fdownload%2Fglob-7.1.6.tgz", + "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.3.tgz", + "integrity": "sha1-ShL/G2A3bvCYYsIJPt2Qgyi+hCM=" + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npm.taobao.org/ieee754/download/ieee754-1.1.13.tgz", + "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz?cache=0&sync_timestamp=1562592096220&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fisarray%2Fdownload%2Fisarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/lazystream/download/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz", + "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/lodash.defaults/download/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npm.taobao.org/lodash.difference/download/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npm.taobao.org/lodash.flatten/download/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npm.taobao.org/lodash.isplainobject/download/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npm.taobao.org/lodash.union/download/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "lua-json": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/lua-json/download/lua-json-1.0.0.tgz", + "integrity": "sha1-kVsycUJmdKSRem0+b5eYj26Rdzk=", + "requires": { + "lodash": "^4.17.11", + "luaparse": "^0.2.1" + } + }, + "luaparse": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/luaparse/download/luaparse-0.2.1.tgz", + "integrity": "sha1-qo9WEysN6X0388mRqd9C4OF/ZWw=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/printj/download/printj-1.1.2.tgz", + "integrity": "sha1-2Q3rKXWoufYA+zoclOP0xTx4oiI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" + }, + "readable-stream": { + "version": "3.5.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.5.0.tgz", + "integrity": "sha1-Rl1w5tEIf2Fi0HnNC123++v9FgY=", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + }, + "ssf": { + "version": "0.10.2", + "resolved": "https://registry.npm.taobao.org/ssf/download/ssf-0.10.2.tgz", + "integrity": "sha1-ZbK0/N/ZZ7yOg4OkE0kAmJMRWXY=", + "requires": { + "frac": "~1.1.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz?cache=0&sync_timestamp=1565170823020&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring_decoder%2Fdownload%2Fstring_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "tar-stream": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/tar-stream/download/tar-stream-2.1.0.tgz", + "integrity": "sha1-0aqjZh8Fs4tazJtwIO/cpReaLMM=", + "requires": { + "bl": "^3.0.0", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xlsx": { + "version": "0.15.5", + "resolved": "https://registry.npm.taobao.org/xlsx/download/xlsx-0.15.5.tgz", + "integrity": "sha1-N9W7gHbeczfluwdps61V0Y1o6uw=", + "requires": { + "adler-32": "~1.2.0", + "cfb": "^1.1.3", + "codepage": "~1.14.0", + "commander": "~2.17.1", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "ssf": "~0.10.2" + } + }, + "zip-stream": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/zip-stream/download/zip-stream-2.1.3.tgz", + "integrity": "sha1-JsxL25NkGoWQ3QcRLh93rxdYhls=", + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^2.1.1", + "readable-stream": "^3.4.0" + } + } + } +} diff --git a/tools/excel_exporter/package.json b/tools/excel_exporter/package.json new file mode 100644 index 0000000..13e3ad9 --- /dev/null +++ b/tools/excel_exporter/package.json @@ -0,0 +1,28 @@ +{ + "name": "xy-excel-exporter", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/cnwillz/XyExcelExporter.git" + }, + "keywords": [ + "excel", + "exporter" + ], + "author": "willz", + "license": "ISC", + "bugs": { + "url": "https://github.com/cnwillz/XyExcelExporter/issues" + }, + "homepage": "https://github.com/cnwillz/XyExcelExporter#readme", + "dependencies": { + "archiver": "^3.1.1", + "lua-json": "^1.0.0", + "xlsx": "^0.15.5" + } +} diff --git a/tools/excel_exporter/xlsx2lua.js b/tools/excel_exporter/xlsx2lua.js new file mode 100644 index 0000000..abd0b6c --- /dev/null +++ b/tools/excel_exporter/xlsx2lua.js @@ -0,0 +1,335 @@ +'use strict' +var XLSX = require('xlsx'); +var fs = require('fs'); +var path = require('path'); + +var options = process.argv; +if (options.length < 5) { + console.log("需要3个参数(side src out)"); + process.exit(); +} +//console.log(options[2], options[3], options[4]); +var side = options[2]; +var sideChar = ''; +if (side == 'server') + sideChar = 's'; +else if (side == 'client') + sideChar = 'c'; +else { + console.log("side should be server/client"); + process.exit(); +} + +var srcDir = options[3]; +var outDir = options[4]; + +console.log("Xy导表脚本 XyExcelExporter"); +console.log("作者: willz[qq3243309346]"); + +var keys = {}; +//var values = []; +var attrExport = []; +var currentSheet = null; + +function isJson(obj) { + var isJson = typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length; + return isJson; +} + +function insertKey(list, line) { + var obj = keys; + for (var i = 0; i < list.length; i++) { + if (!obj.hasOwnProperty(list[i])) { + obj[list[i]] = {}; + } + if (i == list.length - 1) + obj[list[i]] = line; + else + obj = obj[list[i]]; + } +} + +/* 给String原型链对象添加方法trim */ +if (!String.prototype.trim) { + String.prototype.trim = function () { + return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + }; +} + +function getCell(sheet, row, col) { + var ref = XLSX.utils.encode_cell({ c: col, r: row }); + var cell = sheet[ref]; + return (cell ? cell.v : undefined); +} + +function getMaxRow(sheet) { + var range = XLSX.utils.decode_range(sheet['!ref']); + //console.log(range); + return range.e.r; +} + +function getMaxCol(sheet) { + var range = XLSX.utils.decode_range(sheet['!ref']); + //console.log(range); + return range.e.c; +} + +function insertStr(soure, start, newStr) { + return soure.slice(0, start) + newStr + soure.slice(start); +} + +function encodeQuote(str) { + if (str[0] != '"' || str[str.length - 1] != '"') + return str; + var i = 1; + var f; + while ((f = str.indexOf('"', i)) != -1 && f < str.length - 1) { + str = insertStr(str, f, '\\'); + //console.log(f, str); + i = f + 2; + } + return str; +} + +function getCellContent(sheet, row, col) { + var cell = getCell(sheet, row, col); + if (cell == undefined) + return '""'; + var str = '' + cell; + str = str.replace(/\n/g, ' '); + if (str.trim().length == 0) + return '""'; + return str; +} + +function getCellNonEmpty(sheet, row, col) { + var cell = getCell(sheet, row, col); + if (cell == undefined) + return ''; + var str = '' + cell; + str = str.replace(/\n/g, ' '); + if (str.trim().length == 0) + return ''; + return str; +} + + +function handleValues(obj, numAttr, prefix) { + var str = ''; + for (var key in obj) { + str += prefix + '[' + key + '] = {\n'; + var val = obj[key]; + if (isJson(val)) { + str += handleValues(val, numAttr, prefix + '\t'); + } else { + for (var ai = 0; ai < numAttr; ai++) { + if (!attrExport[ai]) + continue; + var value = getCellContent(currentSheet, 7 + val, 1 + ai); + if (value != undefined) + str += '\t' + prefix + getCell(currentSheet, 6, 1 + ai) + ' = ' + value + ',\n'; + } + } + str += prefix + '},\n'; + } + return str; +} + + +function mkdirs(dirname, callback) { + if (fs.existsSync(dirname)) { + if (callback != undefined) + callback(); + } else { + mkdirs(path.dirname(dirname), function () { + fs.mkdirSync(dirname); + if (callback != undefined) + callback(); + }); + } +} + +function removeDir(p) { + if (!fs.existsSync(p)) + return; + let statObj = fs.statSync(p); // fs.statSync同步读取文件状态,判断是文件目录还是文件。 + if (statObj.isDirectory()) { //如果是目录 + let dirs = fs.readdirSync(p) //fs.readdirSync()同步的读取目标下的文件 返回一个不包括 '.' 和 '..' 的文件名的数组['b','a'] + dirs = dirs.map(dir => path.join(p, dir)) //拼上完整的路径 + for (let i = 0; i < dirs.length; i++) { + // 深度 先将儿子移除掉 再删除掉自己 + removeDir(dirs[i]); + } + fs.rmdirSync(p); //删除目录 + } else { + fs.unlinkSync(p); //删除文件 + } +} + +var countExport = 0; +function handleFile(filePath) { + var workbook = XLSX.readFile(filePath); + //console.log(workbook); + console.log("handle file: " + filePath + " with " + workbook.SheetNames.length + " sheets"); + for (var s = 0; s < workbook.SheetNames.length; s++) { + var sname = workbook.SheetNames[s]; + + var sheet = workbook.Sheets[sname]; + //console.log(sheet); + + var exportType = getCell(sheet, 0, 1); + if (exportType == 'base') { + var exportFile = outDir + '/' + getCell(sheet, 1, 1); + + var fileHead = getCell(sheet, 0, 4); + var fileTail = getCell(sheet, 1, 4); + var numKeys = getCell(sheet, 2, 1); + //console.log(exportFile, fileHead, fileTail, numKeys); + + if (sideChar == 'c') { + var clientHead = getCellNonEmpty(sheet, 0, 6); + if (clientHead != '') + fileHead = clientHead; + + var clientFile = getCellNonEmpty(sheet, 1, 6); + if (clientFile != '') + exportFile = outDir + '/' + clientFile; + } + console.log("exporting sheet '" + sname + + "' with type " + exportType + + " to '" + exportFile + "'" + ); + + exportFile = exportFile.toLowerCase(); + mkdirs(path.dirname(exportFile)); + var outLua = fileHead + '\n'; + + + try { + var data = fs.readFileSync(exportFile, 'utf-8'); + var contents = data.split("\n"); + contents[contents.length - 1] = ''; + outLua = contents.join("\n"); + } catch (err) { + // 出错了 + } + + var lines = getMaxRow(sheet) - 6; + //console.log("line:" + lines); + //if(lines == 0) + // continue; + + keys = null; + keys = {}; + var isBreak = false; + for (var li = 0; li < lines; li++) { + var list = []; + for (var ki = 0; ki < numKeys; ki++) { + var str = getCell(sheet, 7 + li, 1 + ki); + str = str == undefined ? '' : '' + str; + if (str.trim().length == 0) { + isBreak = true; + break; + } + list[ki] = str; + } + if (!isBreak) + insertKey(list, li); + else + isBreak = false; + } + //console.log(keys); + + attrExport = []; + var numAttr = getMaxCol(sheet); + var validAttr = 0; + for (var ai = 0; ai < numAttr; ai++) { + var exportParam = getCell(sheet, 5, 1 + ai); + if (exportParam != undefined && exportParam.includes(sideChar)) { + attrExport[ai] = true; + validAttr++; + } + else + attrExport[ai] = false; + } + //console.log(attrExport); + //console.log("attr:" + numAttr); + + currentSheet = sheet; + + if (validAttr > 0) + outLua += handleValues(keys, numAttr, '');; + + outLua += fileTail; + fs.writeFileSync(exportFile, outLua, 'utf-8'); + countExport++; + } + else if (exportType == 'tiny') { + var exportFile = outDir + '/' + getCell(sheet, 1, 1); + exportFile = exportFile.toLowerCase(); + console.log("exporting sheet '" + sname + + "' with type " + exportType + + " to '" + exportFile + "'" + ); + + var fileHead = getCell(sheet, 0, 4); + var fileTail = getCell(sheet, 1, 4); + mkdirs(path.dirname(exportFile)); + var outLua = fileHead + '\n'; + + var lines = 0; + for (var lines = 0; true;) { + if (getCell(sheet, 5 + lines, 1) == undefined) + break; + lines++; + } + //console.log("line:" + lines); + //if(lines == 0) + // continue; + + for (var li = 0; li < lines; li++) { + var exportParam = getCell(sheet, 5 + li, 1); + if (!exportParam.includes(sideChar)) + continue; + var attr = getCell(sheet, 5 + li, 2); + var value = getCellContent(sheet, 5 + li, 3); + value = encodeQuote(value); + if (value.startsWith('--#include')) + outLua += value + '\n'; + else if (attr != undefined) + outLua += '\t' + attr + ' = ' + value + ',\n'; + } + + + outLua += fileTail; + fs.writeFileSync(exportFile, outLua, 'utf-8'); + countExport++; + } + } +} + +function handleDir(filePath) { + //根据文件路径读取文件,返回文件列表 + var files = fs.readdirSync(filePath); + //遍历读取到的文件列表 + files.forEach(function (filename) { + //获取当前文件的绝对路径 + var filedir = path.join(filePath, filename); + //根据文件路径获取文件信息,返回一个fs.Stats对象 + var stats = fs.statSync(filedir); + var isFile = stats.isFile();//是文件 + var isDir = stats.isDirectory();//是文件夹 + if (isFile && filedir.endsWith(".xlsx")) { + //console.log(filedir); + handleFile(filedir); + } + if (isDir) { + handleDir(filedir);//递归,如果是文件夹,就继续遍历该文件夹下面的文件 + } + + }); +} + +removeDir(outDir); +handleDir(srcDir); +console.log("Total export: " + countExport); \ No newline at end of file