🐳 chore(工具): 增加 导表工具

develop
xiaojin 5 years ago
parent a5502e8aef
commit a5aa469a88

@ -1,9 +0,0 @@
# dns 服务
用于开发中区分测试环境、预生产、显示环境的域名解析
镜像使用 [https://hub.docker.com/r/andyshinn/dnsmasq](https://hub.docker.com/r/andyshinn/dnsmasq)
## 优点
1. 可以省去频繁的修改本地hosts文件
2. 可统一公司内部人员的域名解析一致

@ -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

@ -1,2 +0,0 @@
resolv-file=/etc/resolv.dnsmasq
addn-hosts=/etc/dnsmasqhosts

@ -1 +0,0 @@
192.168.9.9 hehe.my.com

@ -1,3 +0,0 @@
nameserver 114.114.114.114
nameserver 223.6.6.6
nameserver 8.8.8.8

@ -21,7 +21,9 @@ aoe 技能的拾取是 一帧内的下一tick 处理 以引用计数来统计
是否已经达到下一步的要求
数据库操作 key 都以 crc16 算法确定链路 而且都是 encode 完再
发到 对应的db 服 这样会减少2次 打包 table的 开销
发到 对应的db 服 这样会减少2次 打包 table的 cpu 开销
玩家以 hash 类型 存储 可以 按 核心 活动 或者其他的 分为 多个 hash 值
这样能保证 key 太多的问题 在 加载的时候 可以 利用 redis pipe 加快访问
并且 数据缓存 需要 按 只查询 和 可读写来划分隔离出来2部分通过
lru 来管理 要不然会把 老数据残留的问题
@ -51,3 +53,10 @@ https://blog.codingnow.com/2007/11/inertia_thinking.html
- major_multiplier 控制年老对象收集倍率,对于一个倍率`X`, 新的`major collection`将会在内存使用比上次`major collection`后增长`X%`时完成. 默认值是100最大值1000
分代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/

@ -0,0 +1 @@
-- 服务组模版

@ -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, 30bits2054-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<<WORKER_ID_BITS) - 1
local MAX_SEQ = (1<<SEQ_BITS) - 1
local worker_id = tonumber(...)
assert(worker_id >= 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<<TIME_LEFT_SHIFT_BITS) + (worker_id<<SEQ_BITS) + seq
end
skynet.start(function()
skynet.dispatch("lua", function()
skynet.retpack(gen_guid())
end)
end)

@ -124,7 +124,6 @@ function CMD.get_service(cate)
end
if is_master then
skynet.info_func(function()
return {
log_console = log_console,
@ -149,6 +148,29 @@ if is_master then
end,
}
local SIGHUP_CMD = {}
local function get_first_line(filename)
local f = io.open(filename, "r")
if not f then
return
end
local first_line = f:read("l")
f:close()
return first_line
end
local function get_sighup_cmd(sighup_file)
local cmd = get_first_line(sighup_file)
if not cmd then
return
end
return SIGHUP_CMD[cmd]
end
local sighup_file = "./.sighup_file"
-- 捕捉sighup信号(kill -1)
skynet.register_protocol {
name = "SYSTEM",
id = skynet.PTYPE_SYSTEM,
@ -156,9 +178,22 @@ if is_master then
return ...
end,
dispatch = function(_, addr)
local level = LOG_LEVEL.FATAL
local msg = log_format(addr, level, nil, "SIGHUP")
CMD.log(level, msg)
-- https://blog.hanxi.cc/p/75/
local cmd = get_sighup_cmd(sighup_file)
if cmd then
cmd = cmd:match("^%s*(.-)%s*$")
local func = SIGHUP_CMD[cmd]
if func then
func()
else
skynet.error(
string.format("unknow sighup cmd, need set sighup file. sighup_file: '%s'", sighup_file))
end
else
local level = LOG_LEVEL.FATAL
local msg = log_format(addr, level, nil, "SIGHUP")
CMD.log(level, msg)
end
end,
}

@ -0,0 +1,109 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
~*.xlsx
src*/
out*/
excel/
config.pack

@ -0,0 +1,4 @@
# XyExcelExporter
https://github.com/cnwillz/XyExcelExporter
为dslh编写的导表工具也部分适用于其他游戏

@ -0,0 +1,2 @@
#!/bin/bash
node xlsx2lua server excel out_s

@ -0,0 +1,239 @@
"use strict";
var lua2json = require("lua-json");
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];
var lang = {};
var compactMap = {
"MonstersConfig": "MonstersConfig_keys",
"Monsters2sConfig": "MonstersConfig_keys2",
"InstanceConfig": "InstanceConfig_keys",
"EffectsConfig": "EffectsConfig_keys",
"SkillsConfig": "SkillsConfig_keys",
"SkillsExeConfig": "SkillsExeConfig_keys",
};
function shouldBeArray(obj) {
var cv = Object.values(obj);
if (cv.length == 0) {
return false;
}
var cv2 = Object.values(cv[0]);
if (cv2.length == 0) {
return false;
}
var innerObj = cv2[0];
if (innerObj == undefined) {
return false;
}
var max = -2;
var count = 0;
var firstNumber = -999;
for (var key in innerObj) {
var id = parseInt(key);
//console.log(key, id);
if (isNaN(id)) {
return false;
}
if (firstNumber == -999) {
firstNumber = id;
}
if (id > 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");

@ -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);

@ -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();

@ -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"
}
}
}
}

@ -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"
}
}

@ -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);
Loading…
Cancel
Save