index.js 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. let packageName = "excel-killer";
  2. let fs = require('fire-fs');
  3. let path = require('fire-path');
  4. let CfgUtil = Editor.require('packages://' + packageName + '/core/CfgUtil.js');
  5. let excelItem = Editor.require('packages://' + packageName + '/panel/item/excelItem.js');
  6. let nodeXlsx = Editor.require('packages://' + packageName + '/node_modules/node-xlsx');
  7. let Electron = require('electron');
  8. let uglifyJs = Editor.require('packages://' + packageName + '/node_modules/uglify-js');
  9. let fsExtra = Editor.require('packages://' + packageName + '/node_modules/fs-extra');
  10. let jsonBeautifully = Editor.require('packages://' + packageName + '/node_modules/json-beautifully');
  11. let chokidar = Editor.require('packages://' + packageName + '/node_modules/chokidar');
  12. const Globby = require('globby');
  13. let dirClientName = "client";
  14. let dirServerName = "server";
  15. let projectPath = Editor.Project.path;
  16. // 客户端存放配置表文件目录
  17. let clientJsPath = path.join(projectPath, "assets/script/data/config");
  18. // 配置表输出目录
  19. let excelOutPutPath = 'plugins-excel/excel-output';
  20. Editor.Panel.extend({
  21. style: fs.readFileSync(Editor.url('packages://' + packageName + '/panel/index.css', 'utf8')) + "",
  22. template: fs.readFileSync(Editor.url('packages://' + packageName + '/panel/index.html', 'utf8')) + "",
  23. $: {
  24. logTextArea: '#logTextArea',
  25. },
  26. ready() {
  27. let logCtrl = this.$logTextArea;
  28. let logListScrollToBottom = function () {
  29. setTimeout(function () {
  30. logCtrl.scrollTop = logCtrl.scrollHeight;
  31. }, 10);
  32. };
  33. excelItem.init();
  34. this.plugin = new window.Vue({
  35. el: this.shadowRoot,
  36. created() {
  37. this._initPluginCfg();
  38. },
  39. init() {
  40. },
  41. data: {
  42. logView: "",
  43. excelRootPath: null,
  44. isMergeJson: false,
  45. isMergeJavaScript: false,
  46. isExportJson: false,// 是否导出Json
  47. isExportJs: false,// 是否导出Js
  48. isFormatJson: false,// 是否格式化Json
  49. isExportClient: false,// 是否导出客户端
  50. isExportServer: false,// 是否导出服务端
  51. isJsonAllCfgFileExist: false,// 是否单一配置文件存在
  52. jsonSavePath: null,// json保存文件夹路径
  53. jsonAllCfgFileName: null,// json配置文件名
  54. jsSavePath: null,// 插件资源目录
  55. jsFileName: null,//js配置合并为一个文件的文件名
  56. isJsFileExist: false,
  57. isFormatJsCode: false,
  58. excelArray: [],
  59. excelFileArr: [],
  60. importProjectCfgPath: null,
  61. },
  62. methods: {
  63. ////////////////////////////导入到项目////////////////////////////////////////////
  64. onBtnClickSelectProjectJsonCfgPath() {
  65. let res = Editor.Dialog.openFile({
  66. title: "选择项目配置存放目录",
  67. defaultPath: path.join(projectPath, "assets"),
  68. properties: ['openDirectory'],
  69. });
  70. if (res !== -1) {
  71. let dir = res[0];
  72. if (dir !== this.importProjectCfgPath) {
  73. this.importProjectCfgPath = dir;
  74. this._saveConfig();
  75. }
  76. }
  77. },
  78. onBtnClickImportProjectJsonCfg_Server() {
  79. this._importJsonCfg("server");
  80. },
  81. onBtnClickImportProjectJsonCfg_Client() {
  82. this._importJsonCfg("client");
  83. },
  84. _importJsonCfg(typeDir) {
  85. if (!fs.existsSync(this.importProjectCfgPath)) {
  86. this._addLog("导入项目路径不存在:" + this.importProjectCfgPath);
  87. return;
  88. }
  89. if (!this.isExportJson) {
  90. this._addLog("[Warning] 您未勾选导出Json配置,可能导入的配置时上个版本的!");
  91. }
  92. let importPath = Editor.assetdb.remote.fspathToUrl(this.importProjectCfgPath);
  93. if (importPath.indexOf("db://assets") >= 0) {
  94. // 检索所有的json配置
  95. let clientDir = path.join(this.jsonSavePath, typeDir);
  96. if (!fs.existsSync(clientDir)) {
  97. this._addLog("配置目录不存在:" + clientDir);
  98. return;
  99. }
  100. let pattern = path.join(clientDir, '**/*.json');
  101. let files = Globby.sync(pattern)
  102. this._addLog("一共导入文件数量: " + files.length);
  103. for (let i = 0; i < files.length; i++) {
  104. }
  105. Editor.assetdb.import(files, importPath,
  106. function (err, results) {
  107. results.forEach(function (result) {
  108. console.log(result.path);
  109. // result.uuid
  110. // result.parentUuid
  111. // result.url
  112. // result.path
  113. // result.type
  114. });
  115. }.bind(this));
  116. } else {
  117. this._addLog("非项目路径,无法导入 : " + this.importProjectCfgPath);
  118. }
  119. },
  120. ////////////////////////////////////////////////////////////////////////
  121. _addLog(str) {
  122. let time = new Date();
  123. // this.logView = "[" + time.toLocaleString() + "]: " + str + "\n" + this.logView;
  124. this.logView += "[" + time.toLocaleString() + "]: " + str + "\n";
  125. logListScrollToBottom();
  126. },
  127. onBtnClickTellMe() {
  128. // let data = nodeXlsx.parse(path.join(this.excelRootPath, 'test2.xlsx'));
  129. // console.log(data);
  130. // return;
  131. let url = "http://wpa.qq.com/msgrd?v=3&uin=774177933&site=qq&menu=yes";
  132. Electron.shell.openExternal(url);
  133. },
  134. _saveConfig() {
  135. let data = {
  136. excelRootPath: this.excelRootPath,
  137. jsFileName: this.jsFileName,
  138. jsonAllFileName: this.jsonAllCfgFileName,
  139. isMergeJson: this.isMergeJson,
  140. isMergeJavaScript: this.isMergeJavaScript,
  141. isFormatJsCode: this.isFormatJsCode,
  142. isFormatJson: this.isFormatJson,
  143. isExportJson: this.isExportJson,
  144. isExportJs: this.isExportJs,
  145. isExportClient: this.isExportClient,
  146. isExportServer: this.isExportServer,
  147. importProjectCfgPath: this.importProjectCfgPath,
  148. };
  149. CfgUtil.saveCfgByData(data);
  150. },
  151. onBtnClickFreshExcel() {
  152. this._onAnalyzeExcelDirPath(this.excelRootPath);
  153. },
  154. _watchDir(event, filePath) {
  155. return;
  156. console.log("监控文件....");
  157. console.log(event, filePath);
  158. let ext = path.extname(filePath);
  159. if (ext === ".xlsx" || ext === ".xls") {
  160. this._onAnalyzeExcelDirPath(this.excelRootPath);
  161. }
  162. },
  163. onBtnClickHelpDoc() {
  164. let url = "https://github.com/tidys/CocosCreatorPlugins/tree/master/packages/excel-killer/README.md";
  165. Electron.shell.openExternal(url);
  166. },
  167. _initPluginCfg() {
  168. console.log("initCfg");
  169. CfgUtil.initCfg(function (data) {
  170. if (data) {
  171. this.excelRootPath = data.excelRootPath || "";
  172. if (fs.existsSync(this.excelRootPath)) {
  173. this._onAnalyzeExcelDirPath(this.excelRootPath);
  174. chokidar.watch(this.excelRootPath, {
  175. usePolling: true,
  176. // interval: 1000,
  177. // awaitWriteFinish: {
  178. // stabilityThreshold: 2000,
  179. // pollInterval: 100
  180. // },
  181. }).on('all', this._watchDir.bind(this));
  182. } else {
  183. }
  184. this.jsFileName = data.jsFileName || "GameJsCfg";
  185. this.jsonAllCfgFileName = data.jsonAllFileName || "GameJsonCfg";
  186. this.isMergeJson = data.isMergeJson || false;
  187. this.isMergeJavaScript = data.isMergeJavaScript || false;
  188. this.isFormatJsCode = data.isFormatJsCode || false;
  189. this.isFormatJson = data.isFormatJson || false;
  190. this.isExportJson = data.isExportJson || false;
  191. this.isExportJs = data.isExportJs || false;
  192. this.isExportClient = data.isExportClient || false;
  193. this.isExportServer = data.isExportServer || false;
  194. this.importProjectCfgPath = data.importProjectCfgPath || null;
  195. this.checkJsFileExist();
  196. this.checkJsonAllCfgFileExist();
  197. } else {
  198. this.jsFileName = "GameJsCfg";
  199. this.jsonAllCfgFileName = "GameJsonCfg";
  200. }
  201. }.bind(this));
  202. this._initCfgSavePath();// 默认json路径
  203. },
  204. _initCfgSavePath() {
  205. let pluginResPath = path.join(projectPath, excelOutPutPath);
  206. if (!fs.existsSync(pluginResPath)) {
  207. fs.mkdirSync(pluginResPath);
  208. }
  209. let pluginResPath1 = path.join(pluginResPath, "json");
  210. if (!fs.existsSync(pluginResPath1)) {
  211. fs.mkdirSync(pluginResPath1);
  212. }
  213. this.jsonSavePath = pluginResPath1;
  214. this._initCSDir(this.jsonSavePath);
  215. let pluginResPath2 = path.join(pluginResPath, "js");
  216. if (!fs.existsSync(pluginResPath2)) {
  217. fs.mkdirSync(pluginResPath2);
  218. }
  219. this.jsSavePath = pluginResPath2;
  220. this._initCSDir(this.jsSavePath);
  221. },
  222. // 初始化client-server目录
  223. _initCSDir(saveDir) {
  224. let clientDir = path.join(saveDir, dirClientName);
  225. if (!fs.existsSync(clientDir)) {
  226. fs.mkdirSync(clientDir);
  227. }
  228. let serverDir = path.join(saveDir, dirServerName);
  229. if (!fs.existsSync(serverDir)) {
  230. fs.mkdirSync(serverDir);
  231. }
  232. },
  233. onBtnClickFormatJson() {
  234. this.isFormatJson = !this.isFormatJson;
  235. this._saveConfig();
  236. },
  237. // 是否合并json
  238. onBtnClickMergeJson() {
  239. this.isMergeJson = !this.isMergeJson;
  240. this._saveConfig();
  241. },
  242. onBtnClickMergeJavaScript() {
  243. this.isMergeJavaScript = !this.isMergeJavaScript;
  244. this._saveConfig();
  245. },
  246. // 打开合并的json
  247. onBtnClickJsonAllCfgFile() {
  248. let saveFileFullPath1 = path.join(this.jsonSavePath, dirClientName, this.jsonAllCfgFileName + ".json");
  249. let saveFileFullPath2 = path.join(this.jsonSavePath, dirServerName, this.jsonAllCfgFileName + ".json");
  250. if (fs.existsSync(saveFileFullPath1)) {
  251. Electron.shell.openItem(saveFileFullPath1);
  252. Electron.shell.beep();
  253. } else if (fs.existsSync(saveFileFullPath2)) {
  254. Electron.shell.openItem(saveFileFullPath2);
  255. Electron.shell.beep();
  256. } else {
  257. // this._addLog("目录不存在:" + this.resourceRootDir);
  258. this._addLog("目录不存在:" + saveFileFullPath1 + ' or:' + saveFileFullPath2);
  259. return;
  260. }
  261. },
  262. checkJsonAllCfgFileExist() {
  263. let saveFileFullPath1 = path.join(this.jsonSavePath, dirClientName, this.jsonAllCfgFileName + ".json");
  264. let saveFileFullPath2 = path.join(this.jsonSavePath, dirServerName, this.jsonAllCfgFileName + ".json");
  265. if (fs.existsSync(saveFileFullPath1) || fs.existsSync(saveFileFullPath2)) {
  266. this.isJsonAllCfgFileExist = true;
  267. } else {
  268. this.isJsonAllCfgFileExist = false;
  269. }
  270. },
  271. onBtnClickFormatJsCode() {
  272. this.isFormatJsCode = !this.isFormatJsCode;
  273. this._saveConfig();
  274. },
  275. onBtnClickOpenExcelRootPath() {
  276. if (fs.existsSync(this.excelRootPath)) {
  277. Electron.shell.showItemInFolder(this.excelRootPath);
  278. Electron.shell.beep();
  279. } else {
  280. this._addLog("目录不存在:" + this.excelRootPath);
  281. }
  282. },
  283. onBtnClickSelectExcelRootPath() {
  284. let res = Editor.Dialog.openFile({
  285. title: "选择Excel的根目录",
  286. defaultPath: projectPath,
  287. properties: ['openDirectory'],
  288. });
  289. if (res !== -1) {
  290. let dir = res[0];
  291. if (dir !== this.excelRootPath) {
  292. this.excelRootPath = dir;
  293. chokidar.watch(this.excelRootPath).on('all', this._watchDir.bind(this));
  294. this._onAnalyzeExcelDirPath(dir);
  295. this._saveConfig();
  296. }
  297. }
  298. },
  299. // 修改js配置文件
  300. onJsFileNameChanged() {
  301. this._saveConfig();
  302. },
  303. // 修改json配置文件
  304. onJsonAllCfgFileChanged() {
  305. this._saveConfig();
  306. },
  307. onBtnClickIsExportJson() {
  308. this.isExportJson = !this.isExportJson;
  309. this._saveConfig();
  310. },
  311. onBtnClickIsExportJs() {
  312. this.isExportJs = !this.isExportJs;
  313. this._saveConfig();
  314. },
  315. onBtnClickExportClient() {
  316. this.isExportClient = !this.isExportClient;
  317. this._saveConfig();
  318. },
  319. onBtnClickExportServer() {
  320. this.isExportServer = !this.isExportServer;
  321. this._saveConfig();
  322. },
  323. // 查找出目录下的所有excel文件
  324. _onAnalyzeExcelDirPath(dir) {
  325. let self = this;
  326. // let dir = path.normalize("D:\\proj\\CocosCreatorPlugins\\doc\\excel-killer");
  327. if (dir) {
  328. // 查找json文件
  329. let allFileArr = [];
  330. let excelFileArr = [];
  331. // 获取目录下所有的文件
  332. readDirSync(dir);
  333. // 过滤出来.xlsx的文件
  334. for (let k in allFileArr) {
  335. let file = allFileArr[k];
  336. let extName = path.extname(file);
  337. if (extName === ".xlsx" || extName === ".xls") {
  338. excelFileArr.push(file);
  339. } else {
  340. this._addLog("不支持的文件类型: " + file);
  341. }
  342. }
  343. this.excelFileArr = excelFileArr;
  344. // 组装显示的数据
  345. let excelSheetArray = [];
  346. let sheetDuplicationChecker = {};//表单重名检测
  347. for (let k in excelFileArr) {
  348. let itemFullPath = excelFileArr[k];
  349. // this._addLog("excel : " + itemFullPath);
  350. let excelData = nodeXlsx.parse(itemFullPath);
  351. //todo 检测重名的sheet
  352. for (let j in excelData) {
  353. let itemData = {
  354. isUse: true,
  355. fullPath: itemFullPath,
  356. name: "name",
  357. sheet: excelData[j].name
  358. };
  359. itemData.name = itemFullPath.substr(dir.length + 1, itemFullPath.length - dir.length);
  360. if (excelData[j].data.length === 0) {
  361. this._addLog("[Error] 空Sheet: " + itemData.name + " - " + itemData.sheet);
  362. continue;
  363. }
  364. if (sheetDuplicationChecker[itemData.sheet]) {
  365. // 重名sheet问题
  366. this._addLog("[Error ] 出现了重名sheet: " + itemData.sheet);
  367. this._addLog("[Sheet1] " + sheetDuplicationChecker[itemData.sheet].fullPath);
  368. this._addLog("[Sheet2] " + itemFullPath);
  369. this._addLog("请仔细检查Excel-Sheet!");
  370. } else {
  371. sheetDuplicationChecker[itemData.sheet] = itemData;
  372. excelSheetArray.push(itemData);
  373. }
  374. }
  375. }
  376. this.excelArray = excelSheetArray;
  377. function readDirSync(dirPath) {
  378. let dirInfo = fs.readdirSync(dirPath);
  379. for (let i = 0; i < dirInfo.length; i++) {
  380. let item = dirInfo[i];
  381. let itemFullPath = path.join(dirPath, item);
  382. let info = fs.statSync(itemFullPath);
  383. if (info.isDirectory()) {
  384. // this._addLog('dir: ' + itemFullPath);
  385. readDirSync(itemFullPath);
  386. } else if (info.isFile()) {
  387. let headStr = item.substr(0, 2);
  388. if (headStr === "~$") {
  389. self._addLog("检索到excel产生的临时文件:" + itemFullPath);
  390. } else {
  391. allFileArr.push(itemFullPath);
  392. }
  393. // this._addLog('file: ' + itemFullPath);
  394. }
  395. }
  396. }
  397. }
  398. },
  399. onStopTouchEvent(event) {
  400. event.preventDefault();
  401. event.stopPropagation();
  402. // console.log("dragOver");
  403. },
  404. onBtnClickSelectSheet(event) {
  405. let b = event.currentTarget.value;
  406. for (let k in this.excelArray) {
  407. this.excelArray[k].isUse = b;
  408. }
  409. },
  410. onBtnClickOpenJsonSavePath() {
  411. let saveFileFullPath1 = path.join(this.jsonSavePath, dirClientName);
  412. let saveFileFullPath2 = path.join(this.jsonSavePath, dirServerName);
  413. if (fs.existsSync(saveFileFullPath1)) {
  414. Electron.shell.openItem(saveFileFullPath1);
  415. Electron.shell.beep();
  416. } else if (fs.existsSync(saveFileFullPath2)) {
  417. Electron.shell.openItem(saveFileFullPath2);
  418. Electron.shell.beep();
  419. } else {
  420. // this._addLog("目录不存在:" + this.resourceRootDir);
  421. this._addLog("目录不存在:" + saveFileFullPath1 + ' or:' + saveFileFullPath2);
  422. return;
  423. }
  424. },
  425. onBtnClickOpenJsSavePath() {
  426. let saveFileFullPath1 = path.join(this.jsSavePath, dirClientName);
  427. let saveFileFullPath2 = path.join(this.jsSavePath, dirServerName);
  428. if (fs.existsSync(saveFileFullPath1)) {
  429. Electron.shell.openItem(saveFileFullPath1);
  430. Electron.shell.beep();
  431. } else if (fs.existsSync(saveFileFullPath2)) {
  432. Electron.shell.openItem(saveFileFullPath2);
  433. Electron.shell.beep();
  434. } else {
  435. // this._addLog("目录不存在:" + this.resourceRootDir);
  436. this._addLog("目录不存在:" + saveFileFullPath1 + ' or:' + saveFileFullPath2);
  437. return;
  438. }
  439. },
  440. _getJavaScriptSaveData(excelData, itemSheet, isClient) {
  441. let title = excelData[0];
  442. let desc = excelData[1];
  443. let target = excelData[2];
  444. let sheetFormatData = {};
  445. for (let i = 3; i < excelData.length; i++) {
  446. let lineData = excelData[i];
  447. if (lineData.length === 0) {
  448. // 空行直接跳过
  449. continue;
  450. } else {
  451. if (lineData.length < title.length) {
  452. this._addLog("[Error] 发现第" + i + "行缺少字段,跳过该行数据配置.");
  453. continue;
  454. } else if (lineData.length > title.length) {
  455. this._addLog("[Error] 发现第" + i + "行多余字段,跳过该行数据配置.");
  456. continue;
  457. }
  458. }
  459. let saveLineData = {};
  460. let canExport = false;
  461. for (let j = 1; j < title.length; j++) {
  462. if (!title[j]) {
  463. // 遇到空列直接break,后续的数据不处理
  464. break;
  465. }
  466. canExport = false;
  467. if (isClient && target[j].indexOf('c') !== -1) {
  468. canExport = true;
  469. } else if (!isClient && target[j].indexOf('s') !== -1) {
  470. canExport = true;
  471. }
  472. if (canExport) {
  473. let key = title[j];
  474. let value = lineData[j];
  475. if (value === undefined) {
  476. value = "";
  477. this._addLog("[Error] 发现空单元格:" + itemSheet.name + "*" + itemSheet.sheet + " => (" + key + "," + (i + 1) + ")");
  478. }
  479. saveLineData[key] = value;
  480. }
  481. }
  482. canExport = false;
  483. if (isClient && target[0].indexOf('c') !== -1) {
  484. canExport = true;
  485. } else if (!isClient && target[0].indexOf('s') !== -1) {
  486. canExport = true;
  487. }
  488. if (canExport) {
  489. sheetFormatData[lineData[0].toString()] = saveLineData;
  490. }
  491. }
  492. return sheetFormatData;
  493. },
  494. _getJsonSaveData(excelData, itemSheet, isClient) {
  495. let title = excelData[0];
  496. let desc = excelData[1];
  497. let target = excelData[2];
  498. let ret = null;
  499. let useFormat1 = false;
  500. if (useFormat1) {
  501. let saveData1 = [];// 格式1:对应的为数组
  502. for (let i = 3; i < excelData.length; i++) {
  503. let lineData = excelData[i];
  504. if (lineData.length < title.length) {
  505. continue;
  506. } else if (lineData.length > title.length) {
  507. continue;
  508. }
  509. let saveLineData = {};
  510. let canExport = false;
  511. for (let j = 0; j < title.length; j++) {
  512. if (!title[j]) {
  513. // 遇到空列直接break,后续的数据不处理
  514. break;
  515. }
  516. canExport = false;
  517. if (isClient && target[j].indexOf('c') !== -1) {
  518. canExport = true;
  519. } else if (!isClient && target[j].indexOf('s') !== -1) {
  520. canExport = true;
  521. }
  522. if (canExport) {
  523. let key = title[j];
  524. let value = lineData[j];
  525. if (value === undefined) {
  526. value = "";
  527. }
  528. // this._addLog("" + value);
  529. saveLineData[key] = value;
  530. }
  531. }
  532. canExport = false;
  533. if (isClient && target[0].indexOf('c') !== -1) {
  534. canExport = true;
  535. } else if (!isClient && target[0].indexOf('s') !== -1) {
  536. canExport = true;
  537. }
  538. if (canExport) {
  539. saveData1.push(saveLineData);
  540. }
  541. }
  542. ret = saveData1;
  543. } else {
  544. let saveData2 = {};// 格式2:id作为索引
  545. for (let i = 3; i < excelData.length; i++) {
  546. let lineData = excelData[i];
  547. if (lineData.length !== title.length) {
  548. this._addLog(`配置表头和配置数据不匹配:${itemSheet.name} - ${itemSheet.sheet} : 第${i + 1}行`);
  549. this._addLog("跳过该行数据");
  550. continue;
  551. }
  552. let saveLineData = {};
  553. let canExport = false;
  554. // todo 将ID字段也加入到data中
  555. for (let j = 0; j < title.length; j++) {
  556. if (!title[j]) {
  557. // 遇到空列直接break,后续的数据不处理
  558. break;
  559. }
  560. canExport = false;
  561. if (isClient && target[j] && target[j].indexOf('c') !== -1) {
  562. canExport = true;
  563. } else if (!isClient && target[j] && target[j].indexOf('s') !== -1) {
  564. canExport = true;
  565. }
  566. if (canExport) {
  567. let key = title[j];
  568. let value = lineData[j];
  569. if (value === undefined) {
  570. value = "";
  571. }
  572. // this._addLog("" + value);
  573. saveLineData[key] = value;
  574. }
  575. }
  576. canExport = false;
  577. if (isClient && target[0] && target[0].indexOf('c') !== -1) {
  578. canExport = true;
  579. } else if (!isClient && target[0] && target[0].indexOf('s') !== -1) {
  580. canExport = true;
  581. }
  582. if (canExport) {
  583. saveData2[lineData[0].toString()] = saveLineData;
  584. }
  585. }
  586. ret = saveData2;
  587. }
  588. return ret;
  589. },
  590. // 打开生成的js配置文件
  591. onBtnClickOpenJsFile() {
  592. let saveFileFullPath1 = path.join(this.jsSavePath, dirClientName, this.jsFileName + ".js");
  593. let saveFileFullPath2 = path.join(this.jsSavePath, dirServerName, this.jsFileName + ".js");
  594. if (fs.existsSync(saveFileFullPath1)) {
  595. Electron.shell.openItem(saveFileFullPath1);
  596. Electron.shell.beep();
  597. } else if (fs.existsSync(saveFileFullPath2)) {
  598. Electron.shell.openItem(saveFileFullPath2);
  599. Electron.shell.beep();
  600. } else {
  601. // this._addLog("目录不存在:" + this.resourceRootDir);
  602. this._addLog("目录不存在:" + saveFileFullPath1 + ' or:' + saveFileFullPath2);
  603. }
  604. },
  605. // 检测js配置文件是否存在
  606. checkJsFileExist() {
  607. let saveFileFullPath1 = path.join(this.jsSavePath, dirClientName, this.jsFileName + ".js");
  608. let saveFileFullPath2 = path.join(this.jsSavePath, dirServerName, this.jsFileName + ".js");
  609. if (fs.existsSync(saveFileFullPath1) || fs.existsSync(saveFileFullPath2)) {
  610. this.isJsFileExist = true;
  611. } else {
  612. this.isJsFileExist = false;
  613. }
  614. },
  615. // 生成配置
  616. onBtnClickGen() {
  617. console.log("onBtnClickGen");
  618. // 参数校验
  619. if (this.excelArray.length <= 0) {
  620. this._addLog("未发现要生成的配置!");
  621. return;
  622. }
  623. if (this.isMergeJson) {
  624. if (!this.jsonAllCfgFileName || this.jsonAllCfgFileName.length <= 0) {
  625. this._addLog("请输入要保存的json文件名!");
  626. return;
  627. }
  628. }
  629. if (this.isMergeJavaScript) {
  630. if (!this.jsFileName || this.jsFileName.length <= 0) {
  631. this._addLog("请输入要保存的js文件名!");
  632. return;
  633. }
  634. }
  635. // TODO
  636. if (this.isExportServer === false && this.isExportClient === false) {
  637. this._addLog("请选择要导出的目标!");
  638. return;
  639. }
  640. if (this.isExportJson === false && this.isExportJs === false) {
  641. this._addLog("请选择要导出的类型!");
  642. return;
  643. }
  644. this.logView = "";
  645. // 删除老的配置
  646. let jsonSavePath1 = path.join(this.jsonSavePath, dirClientName);
  647. let jsonSavePath2 = path.join(this.jsonSavePath, dirServerName);
  648. fsExtra.emptyDirSync(jsonSavePath1);
  649. fsExtra.emptyDirSync(jsonSavePath2);
  650. let jsSavePath1 = path.join(this.jsSavePath, dirClientName);
  651. let jsSavePath2 = path.join(this.jsSavePath, dirServerName);
  652. fsExtra.emptyDirSync(jsSavePath1);
  653. fsExtra.emptyDirSync(jsSavePath2);
  654. let jsonAllSaveDataClient = {};// 保存客户端的json数据
  655. let jsonAllSaveDataServer = {};// 保存服务端的json数据
  656. let jsAllSaveDataClient = {};// 保存客户端的js数据
  657. let jsAllSaveDataServer = {};// 保存服务端的js数据
  658. for (let k in this.excelArray) {
  659. let itemSheet = this.excelArray[k];
  660. if (itemSheet.isUse) {
  661. let excelData = nodeXlsx.parse(itemSheet.fullPath);
  662. let sheetData = null;
  663. for (let j in excelData) {
  664. if (excelData[j].name === itemSheet.sheet) {
  665. sheetData = excelData[j].data;
  666. }
  667. }
  668. if (sheetData) {
  669. if (sheetData.length > 3) {
  670. if (this.isExportJson) {
  671. // 保存为json
  672. let writeFileJson = function (pathSave, isClient) {
  673. let jsonSaveData = this._getJsonSaveData(sheetData, itemSheet, isClient);
  674. if (Object.keys(jsonSaveData).length > 0) {
  675. if (this.isMergeJson) {
  676. if (isClient) {
  677. // 检测重复问题
  678. if (jsonAllSaveDataClient[itemSheet.sheet] === undefined) {
  679. jsonAllSaveDataClient[itemSheet.sheet] = jsonSaveData;
  680. } else {
  681. this._addLog("发现重名sheet:" + itemSheet.name + "(" + itemSheet.sheet + ")");
  682. }
  683. } else {
  684. // 检测重复问题
  685. if (jsonAllSaveDataServer[itemSheet.sheet] === undefined) {
  686. jsonAllSaveDataServer[itemSheet.sheet] = jsonSaveData;
  687. } else {
  688. this._addLog("发现重名sheet:" + itemSheet.name + "(" + itemSheet.sheet + ")");
  689. }
  690. }
  691. } else {
  692. let saveFileFullPath = path.join(pathSave, itemSheet.sheet + ".json");
  693. this._onSaveJsonCfgFile(jsonSaveData, saveFileFullPath);
  694. }
  695. }
  696. }.bind(this);
  697. if (this.isExportClient) writeFileJson(jsonSavePath1, true);
  698. if (this.isExportServer) writeFileJson(jsonSavePath2, false);
  699. }
  700. if (this.isExportJs) {
  701. // 保存为js
  702. let writeFileJs = function (savePath, isClient) {
  703. let sheetJsData = this._getJavaScriptSaveData(sheetData, itemSheet, isClient);
  704. if (Object.keys(sheetJsData).length > 0) {
  705. if (this.isMergeJavaScript) {
  706. if (isClient) {
  707. // 检测重复问题
  708. if (jsAllSaveDataClient[itemSheet.sheet] === undefined) {
  709. jsAllSaveDataClient[itemSheet.sheet] = sheetJsData;
  710. } else {
  711. this._addLog("发现重名sheet:" + itemSheet.name + "(" + itemSheet.sheet + ")");
  712. }
  713. } else {
  714. // 检测重复问题
  715. if (jsAllSaveDataServer[itemSheet.sheet] === undefined) {
  716. jsAllSaveDataServer[itemSheet.sheet] = sheetJsData;
  717. } else {
  718. this._addLog("发现重名sheet:" + itemSheet.name + "(" + itemSheet.sheet + ")");
  719. }
  720. }
  721. } else {
  722. // 保存js配置
  723. let fileNameFullPath = path.join(savePath, itemSheet.sheet + ".js");
  724. this._onSaveJavaScriptCfgFile(fileNameFullPath, sheetJsData, itemSheet.sheet);
  725. }
  726. }
  727. }.bind(this);
  728. if (this.isExportClient) writeFileJs(jsSavePath1, true);
  729. if (this.isExportServer) writeFileJs(jsSavePath2, false);
  730. }
  731. } else {
  732. this._addLog("行数低于3行,无效sheet:" + itemSheet.sheet);
  733. }
  734. } else {
  735. this._addLog("未发现数据");
  736. }
  737. } else {
  738. console.log("忽略配置: " + itemSheet.fullPath + ' - ' + itemSheet.sheet);
  739. }
  740. }
  741. // =====================>>>> 合并json文件 <<<=================================
  742. if (this.isExportJson && this.isMergeJson) {
  743. if (this.isExportClient) {
  744. let saveFileFullPath = path.join(jsonSavePath1, this.jsonAllCfgFileName + ".json");
  745. this._onSaveJsonCfgFile(jsonAllSaveDataClient, saveFileFullPath);
  746. }
  747. if (this.isExportServer) {
  748. let saveFileFullPath = path.join(jsonSavePath2, this.jsonAllCfgFileName + ".json");
  749. this._onSaveJsonCfgFile(jsonAllSaveDataServer, saveFileFullPath);
  750. }
  751. this.checkJsonAllCfgFileExist();
  752. }
  753. // =====================>>>> 合并js文件 <<<=================================
  754. if (this.isExportJs && this.isMergeJavaScript) {
  755. if (this.isExportClient) {
  756. this._onSaveJavaScriptCfgFile(path.join(jsSavePath1, this.jsFileName + ".js"), jsAllSaveDataClient, this.jsFileName);
  757. }
  758. if (this.isExportServer) {
  759. this._onSaveJavaScriptCfgFile(path.join(jsSavePath2, this.jsFileName + ".js"), jsAllSaveDataServer, this.jsFileName);
  760. }
  761. this.checkJsFileExist();
  762. }
  763. this._addLog("全部转换完成!");
  764. },
  765. // 处理数组和字典数据:使用node-xlsx parse后数组/字典都是字符串,"[]","{}",去除掉双引号即可
  766. _dealArrayAndMap(data) {
  767. let s = JSON.stringify(data);
  768. s = s.replace(/\:\"\[/g, ":[");
  769. s = s.replace(/\]\"/g, "]");
  770. s = s.replace(/\:\"\{/g, ":{");
  771. s = s.replace(/\}\"/g, "}");
  772. return s;
  773. },
  774. // 保存为json配置
  775. _onSaveJsonCfgFile(data, saveFileFullPath) {
  776. let str = this._dealArrayAndMap(data);
  777. if (this.isFormatJson) {
  778. str = jsonBeautifully(str);
  779. }
  780. fs.writeFileSync(saveFileFullPath, str);
  781. this._addLog("[Json]:" + saveFileFullPath);
  782. },
  783. // 保存为js配置
  784. _onSaveJavaScriptCfgFile(saveFileFullPath, jsSaveData, jsFileName) {
  785. let str = this._dealArrayAndMap(jsSaveData);
  786. // TODO 保证key的顺序一致性
  787. let saveStr = "module.exports = " + str + ";";
  788. if (this.isFormatJsCode) {// 保存为格式化代码
  789. let ast = uglifyJs.parse(saveStr);
  790. let ret = uglifyJs.minify(ast, {
  791. output: {
  792. beautify: true,//如果希望得到格式化的输出,传入true
  793. indent_start: 0,//(仅当beautify为true时有效) - 初始缩进空格
  794. indent_level: 4,//(仅当beautify为true时有效) - 缩进级别,空格数量
  795. }
  796. });
  797. if (ret.error) {
  798. this._addLog('error: ' + ret.error.message);
  799. } else if (ret.code) {
  800. fs.writeFileSync(saveFileFullPath, ret.code);
  801. this._addLog("[JavaScript]" + saveFileFullPath);
  802. } else {
  803. this._addLog(JSON.stringify(ret));
  804. }
  805. } else {// 保存为单行代码
  806. fs.writeFileSync(saveFileFullPath, saveStr);
  807. this._addLog("[JavaScript]" + saveFileFullPath);
  808. }
  809. // 移动到客户端目录
  810. if (!fs.existsSync(clientJsPath)) {
  811. fs.mkdirSync(clientJsPath);
  812. }
  813. this.copyFileSync(saveFileFullPath, path.join(clientJsPath, jsFileName + '.js'));
  814. },
  815. copyFileSync(srcFile, destFile) {
  816. var BUF_LENGTH = 64 * 1024
  817. var buff = new Buffer(BUF_LENGTH)
  818. var fdr = fs.openSync(srcFile, 'r')
  819. var fdw = fs.openSync(destFile, 'w')
  820. var bytesRead = 1
  821. var pos = 0
  822. while (bytesRead > 0) {
  823. bytesRead = fs.readSync(fdr, buff, 0, BUF_LENGTH, pos)
  824. fs.writeSync(fdw, buff, 0, bytesRead)
  825. pos += bytesRead
  826. }
  827. fs.closeSync(fdr);
  828. fs.closeSync(fdw);
  829. }
  830. },
  831. });
  832. },
  833. messages: {
  834. 'excel-killer:hello'(event) {
  835. }
  836. }
  837. });