index.js 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  1. const path = require('./path.json');
  2. const readline = require('readline');
  3. var archiver = require('archiver');
  4. const fs = require('fs');
  5. const fse = require('fs-extra');
  6. const xl = require('xlsx');
  7. let excelDir = './excel'; // excel配置表目录
  8. let outDir = './out'; // 导出目录
  9. let outJsonFolder = 'excel'; // 导出的json目录
  10. //前端需要在load界面加载的表
  11. let loadJson = ["audioInfo", "languageLang", "languageClientText", "mathInfo", "packageInfo"]
  12. const cluster = require('cluster');
  13. //后端配置
  14. let serverPath = "../mergerpg_backend_kaifa/common/"
  15. let apiurl = ""
  16. // 前后端解析索引的行
  17. let hang = 3; // 前端3 后端4
  18. // 表格列表 example: ["iconopen","mainTask"]
  19. let excelFiles = [];
  20. // 表名 +分表名
  21. let excelFen = [];
  22. // 表格与表单的数据类型 example:{iconopen:{id:string}}
  23. let excelAndSheets = {};
  24. var s_xls = require('./s_xls');
  25. const { exit } = require('process');
  26. // 检测传入的参数
  27. var args = process.argv.splice(2)
  28. var jiexiTarget = args[0] || "" // s:后端 c:前端
  29. function exeExcelConfig_c() {
  30. let str = '';
  31. str += `import GameController from "../GameController"\nimport { gameMethod } from "./gameMethod"\n`
  32. // 添加类型定义
  33. excelFiles.forEach((excelName) => {
  34. str += `// type for ${excelName}.excel\n`;
  35. for (const sheetName in excelAndSheets[excelName]) {
  36. str += `export type xls${toUpperCaseByStr(excelName)}${toUpperCaseByStr(sheetName)} = {`;
  37. //遍历索引存入类型定义
  38. let keyObjList = excelAndSheets[excelName][sheetName];
  39. for (const key in keyObjList) {
  40. str += `${key.split(',')[0]}:${keyObjList[key].value},`;
  41. }
  42. // 去掉最后一个逗号 ","
  43. if (str.charAt(str.length - 1) == ',') {
  44. str = str.substring(0, str.length - 1);
  45. }
  46. str += '}';
  47. str += '\n';
  48. }
  49. });
  50. str += '\n';
  51. //导出
  52. str += `export class XlsConfig {\n`;
  53. excelFen.forEach((element) => {
  54. str += ` xls${toUpperCaseByStr(element)}: xls${toUpperCaseByStr(element)}[]\n`;
  55. });
  56. // str += ` constructor(callback: Function) {\n`
  57. // let str111 = [];
  58. // excelFen.forEach((element) => {
  59. // str111.push('"' + element + '"');
  60. // });
  61. // str += ` }\n`
  62. str += `
  63. constructor(bundleName:string, callback: Function, progressCallback?: Function) {
  64. cc.assetManager.loadBundle(bundleName, (err, bundle) => {
  65. if (err) {
  66. GameController.clear()
  67. cc.game.restart()
  68. if (progressCallback) {
  69. progressCallback(0, 0.99);
  70. }
  71. return
  72. }
  73. if (gameMethod.isEmpty(bundle) && cc.sys.platform == cc.sys.WECHAT_GAME) {
  74. //小游戏平台,缓存过期,自动清理缓存,重启游戏
  75. console.error("加载配置表的bundle失败,清理缓存重新加载")
  76. cc.assetManager.cacheManager.clearCache()
  77. GameController.clear()
  78. cc.game.restart()
  79. if (progressCallback) {
  80. progressCallback(0, 0.99);
  81. }
  82. return
  83. }
  84. bundle.loadDir("",(finish: number, total: number, item: any)=>{
  85. if (progressCallback) {
  86. progressCallback(finish, total);
  87. }
  88. }, (err2, assets: cc.JsonAsset[]) => {
  89. if (err2) {
  90. GameController.clear()
  91. cc.game.restart()
  92. if (progressCallback) {
  93. progressCallback(0, 0.99);
  94. }
  95. return
  96. }
  97. let current = 0;
  98. assets.forEach(element => {
  99. this["xls" + this.firstUpCase(element.name)] = element.json;
  100. current++;
  101. });
  102. callback(this)
  103. })
  104. })
  105. }
  106. // 首字母大写
  107. private firstUpCase(str: string) {
  108. return str[0].toUpperCase() + str.substring(1)
  109. }
  110. }`;
  111. if (hang == 3) {
  112. outDir = path.configPath;
  113. } else {
  114. outDir = serverPath;
  115. }
  116. // 写入文件
  117. let outPath = `${outDir}xlsConfig.ts`;
  118. fs.writeFile(outPath, str, function (err) {
  119. if (err) {
  120. console.log('xlsConfig写入失败:', err);
  121. }
  122. });
  123. let pro = '';
  124. pro += `export default class ConfProxy<T> {
  125. static getKey(args: string[]): string {
  126. let out = ""
  127. args.forEach(element => {
  128. out += element
  129. out += "_"
  130. });
  131. return out
  132. }
  133. static setKey(target: any, args: string[]): string {
  134. let out = ""
  135. args.forEach(element => {
  136. out += target[element]
  137. out += "_"
  138. });
  139. return out
  140. }
  141. pool: { [key: string]: T } = {}
  142. name:string = ""
  143. constructor(xlsname:string,conf: T[], ...args: string[]) {
  144. this.name = xlsname
  145. conf.forEach(element => {
  146. this.pool[ConfProxy.setKey(element, args)] = element
  147. });
  148. }
  149. getItem(...args: string[]): T | null {
  150. return this.pool[ConfProxy.getKey(args)]
  151. }`;
  152. if (hang == 4) {
  153. pro += `
  154. getItemCtx(ctx:CTX,...args: string[]): T {
  155. let back = this.pool[ConfProxy.getKey(args)]
  156. if(back == null){
  157. console.error("配置错误"+args,this.name)
  158. ctx.throw("配置错误"+args)
  159. }
  160. return back
  161. }
  162. `;
  163. }
  164. pro += `
  165. }
  166. export class ConfListProxy<T> {
  167. pool: { [key: string]: T[] } = {}
  168. name:string = ""
  169. constructor(xlsname:string,conf: T[], ...args: string[]) {
  170. this.name = xlsname
  171. conf.forEach(element => {
  172. let key = ConfProxy.setKey(element, args)
  173. if (this.pool[key] == null) {
  174. this.pool[key] = []
  175. }
  176. this.pool[key].push(element)
  177. });
  178. }
  179. getItemList(...args: string[]): T[] | null {
  180. return this.pool[ConfProxy.getKey(args)]
  181. }
  182. }`;
  183. pro += '\n';
  184. // 写入文件
  185. let proPath = '';
  186. if (hang == 3) {
  187. proPath = `${path.configPath}confProxy.ts`;
  188. } else {
  189. proPath = serverPath + `confProxy.ts`;
  190. }
  191. fs.writeFile(proPath, pro, function (err) {
  192. if (err) {
  193. console.log('ConfProxy写入失败:', err);
  194. }
  195. });
  196. }
  197. function exeExcelConfig() {
  198. let str = '';
  199. // 引入ts文件
  200. excelFen.forEach((element) => {
  201. str += `const ${element} = require( "./excel/${element}.json")\n`;
  202. });
  203. str += '\n';
  204. // 添加类型定义
  205. excelFiles.forEach((excelName) => {
  206. str += `// type for ${excelName}.excel\n`;
  207. for (const sheetName in excelAndSheets[excelName]) {
  208. str += `export type xls${toUpperCaseByStr(excelName)}${toUpperCaseByStr(sheetName)} = {`;
  209. //遍历索引存入类型定义
  210. let keyObjList = excelAndSheets[excelName][sheetName];
  211. for (const key in keyObjList) {
  212. str += `${key.split(',')[0]}:${keyObjList[key].value},`;
  213. }
  214. // 去掉最后一个逗号 ","
  215. if (str.charAt(str.length - 1) == ',') {
  216. str = str.substring(0, str.length - 1);
  217. }
  218. str += '}';
  219. str += '\n';
  220. }
  221. });
  222. str += '\n';
  223. //导出
  224. str += `export class XlsConfig {\n`;
  225. excelFen.forEach((element) => {
  226. str += ` xls${toUpperCaseByStr(element)}: xls${toUpperCaseByStr(element)}[]\n`;
  227. });
  228. str += ` constructor() {\n`;
  229. excelFen.forEach((element) => {
  230. str += ` this.xls${toUpperCaseByStr(element)} = <xls${toUpperCaseByStr(element)}[]>${element}\n`;
  231. });
  232. str += ` }\n`;
  233. str += '}\n';
  234. if (hang == 3) {
  235. outDir = path.configPath;
  236. } else {
  237. outDir = serverPath
  238. }
  239. // 写入文件
  240. let outPath = `${outDir}xlsConfig.ts`;
  241. fs.writeFile(outPath, str, function (err) {
  242. if (err) {
  243. console.log('xlsConfig写入失败:', err);
  244. }
  245. });
  246. let pro = '';
  247. pro += `export default class ConfProxy<T> {
  248. static getKey(args: string[]): string {
  249. let out = ""
  250. args.forEach(element => {
  251. out += element
  252. out += "_"
  253. });
  254. return out
  255. }
  256. static setKey(target: any, args: string[]): string {
  257. let out = ""
  258. args.forEach(element => {
  259. out += target[element]
  260. out += "_"
  261. });
  262. return out
  263. }
  264. pool: { [key: string]: T } = {}
  265. name:string = ""
  266. constructor(xlsname:string,conf: T[], ...args: string[]) {
  267. this.name = xlsname
  268. conf.forEach(element => {
  269. this.pool[ConfProxy.setKey(element, args)] = this.deepFreeze(element)
  270. });
  271. }
  272. deepFreeze<T>(obj: T): T {
  273. Object.freeze(obj);
  274. Object.getOwnPropertyNames(obj).forEach(prop => {
  275. const value = (obj as Record<string, any>)[prop];
  276. if (value !== null
  277. && (typeof value === "object" || typeof value === "function")
  278. && !Object.isFrozen(value)) {
  279. this.deepFreeze(value);
  280. }
  281. });
  282. return obj as T;
  283. }
  284. getItem(...args: string[]): T | null {
  285. return this.pool[ConfProxy.getKey(args)]
  286. }`;
  287. // if (hang == 4) {
  288. // pro += `
  289. // getItemCtx(ctx:CTX,...args: string[]): T {
  290. // let back = this.pool[ConfProxy.getKey(args)]
  291. // if(back == null){
  292. // console.error("配置错误"+args,this.name)
  293. // ctx.throw("配置错误"+args)
  294. // }
  295. // return back
  296. // }
  297. // deepFreeze<T>(obj: T): T {
  298. // Object.freeze(obj);
  299. // Object.getOwnPropertyNames(obj).forEach(prop => {
  300. // const value = (obj as Record<string, any>)[prop];
  301. // if (value !== null
  302. // && (typeof value === "object" || typeof value === "function")
  303. // && !Object.isFrozen(value)) {
  304. // this.deepFreeze(value);
  305. // }
  306. // });
  307. // return obj as T;
  308. // }
  309. // `;
  310. // }
  311. pro += `
  312. }
  313. export class ConfListProxy<T> {
  314. pool: { [key: string]: T[] } = {}
  315. name:string = ""
  316. constructor(xlsname:string,conf: T[], ...args: string[]) {
  317. this.name = xlsname
  318. conf.forEach(element => {
  319. let key = ConfProxy.setKey(element, args)
  320. if (this.pool[key] == null) {
  321. this.pool[key] = []
  322. }
  323. this.pool[key].push(element)
  324. });
  325. }
  326. getItemList(...args: string[]): T[] | null {
  327. return this.pool[ConfProxy.getKey(args)]
  328. }`;
  329. // if (hang == 4) {
  330. // pro += `
  331. // getItemListCtx(ctx:CTX,...args: string[]): T[] {
  332. // let back = this.pool[ConfProxy.getKey(args)]
  333. // if(back == null){
  334. // console.error("list配置错误"+args,this.name)
  335. // ctx.throw("list配置错误"+args)
  336. // }
  337. // return back
  338. // }
  339. // `;
  340. // }
  341. pro += `
  342. }
  343. `
  344. pro += '\n';
  345. // 写入文件
  346. let proPath = '';
  347. if (hang == 3) {
  348. proPath = `${path.configPath}confProxy.ts`;
  349. } else {
  350. proPath = serverPath + `confProxy.ts`;
  351. }
  352. fs.writeFile(proPath, pro, function (err) {
  353. if (err) {
  354. console.log('ConfProxy写入失败:', err);
  355. }
  356. });
  357. }
  358. // 字符串开头变为大写
  359. function toUpperCaseByStr(txt) {
  360. return txt.slice(0, 1).toUpperCase() + txt.slice(1);
  361. }
  362. // 分析配置表
  363. function doExcel(excel) {
  364. let excelName = excel.split('_')[0];
  365. if (s_xls.XlsBack[excelName] == null) {
  366. return
  367. }
  368. let fileDir = `${excelDir}/${excel}`;
  369. let workbook = xl.readFile(fileDir);
  370. // 获取 Excel 中所有表名
  371. const sheetNames = workbook.SheetNames; // 返回 ['sheet1', 'sheet2']
  372. let _sheetNames = [];
  373. for (const element of sheetNames) {
  374. if (s_xls.XlsBack[excelName][element] == null) {
  375. continue
  376. }
  377. _sheetNames.push(element);
  378. }
  379. if (_sheetNames.length == 0) {
  380. return;
  381. }
  382. console.time("...start excel " + excel)
  383. // 加到【excelAndSheets】中
  384. let obj = {};
  385. excelAndSheets[excelName] = {};
  386. _sheetNames.forEach((sheetName) => {
  387. let sheet = workbook.Sheets[sheetName];
  388. excelAndSheets[excelName][sheetName] = {};
  389. doSheet(obj, excelName, sheetName, sheet);
  390. });
  391. let outDir1 = ""
  392. let outDir2 = ""
  393. if (hang == 3) {
  394. outDir1 = `${path.jsonPath}`;
  395. if (!fs.existsSync(outDir1)) {
  396. fs.mkdirSync(outDir1)
  397. }
  398. outDir2 = `${path.loadJsonPath}`;
  399. if (!fs.existsSync(outDir2)) {
  400. fs.mkdirSync(outDir2)
  401. }
  402. } else {
  403. outDir1 = serverPath + `${outJsonFolder}`;
  404. if (!fs.existsSync(outDir1)) {
  405. fs.mkdirSync(outDir1)
  406. }
  407. }
  408. for (const key in obj) {
  409. let jsonStr = `${geshihua(obj[key])}`;
  410. if (outDir2 != "" && loadJson.indexOf(key) >= 0) {
  411. fs.writeFileSync(`${outDir2}/${key}.json`, jsonStr, function (err) {
  412. if (err) {
  413. console.log(err);
  414. }
  415. });
  416. } else {
  417. fs.writeFileSync(`${outDir1}/${key}.json`, jsonStr, function (err) {
  418. if (err) {
  419. console.log(err);
  420. }
  421. });
  422. }
  423. }
  424. console.timeEnd("...start excel " + excel)
  425. }
  426. function geshihua(data) {
  427. let count = 1;
  428. let _data = '[\n';
  429. for (const val of data) {
  430. if (count == 1) {
  431. _data += ' ' + JSON.stringify(val);
  432. } else {
  433. _data += `,\n`;
  434. _data += ' ' + JSON.stringify(val);
  435. }
  436. count++;
  437. }
  438. _data += '\n]';
  439. return _data;
  440. }
  441. //分析表单 obj数据,表名,表单名,表单数据内容
  442. function doSheet(obj, excelName, sheetName, sheet) {
  443. let newKey = excelName + toUpperCaseByStr(sheetName);
  444. excelFen.push(newKey);
  445. if (obj[newKey] == null) {
  446. obj[newKey] = [];
  447. }
  448. // 索引列表 example:{A:"",B:"id",C:"hp",D:"attack"}
  449. let keyList = {};
  450. // 类型列表 example:{A:"number",B:"string",C:"boolean",D:"{}[]"}
  451. let typeList = {};
  452. //备注
  453. let psList = {};
  454. let _tempObj = {};
  455. for (const key in sheet) {
  456. // 单元格定位id example: A25
  457. const sheetKey = sheet[key];
  458. // A25->25
  459. let _hang = key.replace(/[^0-9]+/gi, '');
  460. // A25->A
  461. let _lie = key.replace(/[^A-Z]+/gi, '');
  462. if (_lie == 'A') {
  463. if (Object.keys(_tempObj).length > 0) {
  464. //这边检测是否有放空配置的。如果有 , 补上默认类型
  465. let _tempObj_1 = {};
  466. for (const key in keyList) {
  467. if (_tempObj[keyList[key]] == null) {
  468. if (typeList[key] == 'number') {
  469. _tempObj_1[keyList[key]] = 0;
  470. } else if (typeList[key] == 'string') {
  471. _tempObj_1[keyList[key]] = '';
  472. } else if (typeList[key] == 'boolean') {
  473. _tempObj_1[keyList[key]] = false;
  474. } else if (typeList[key].indexOf('[]') != -1) {
  475. _tempObj_1[keyList[key]] = null;
  476. } else if (typeList[key].substring(0, 0 + 1) == '{') {
  477. _tempObj_1[keyList[key]] = null;
  478. } else if (typeList[key][0] == "[" && typeList[key][typeList[key].length - 1] == "]") { // 元组
  479. _tempObj_1[keyList[key]] = null;
  480. } else {
  481. console.error('配置表有未知定义', excelName, sheetName, keyList[key], typeList[key]);
  482. }
  483. } else {
  484. _tempObj_1[keyList[key]] = _tempObj[keyList[key]];
  485. }
  486. }
  487. obj[newKey].push(_tempObj_1);
  488. _tempObj = {};
  489. }
  490. }
  491. if (sheet['A' + _hang] == null) {
  492. // 第一列没有配置参数,就跳过
  493. continue;
  494. }
  495. if (_hang == 1) {
  496. psList[_lie] = sheetKey.v;
  497. }
  498. // 储存类型
  499. if (_hang == 2) {
  500. typeList[_lie] = sheetKey.v;
  501. }
  502. // 储存索引
  503. if (_hang == hang && sheetKey.v && typeList[_lie]) {
  504. // 正则抽取真正的值(去掉所有的*)
  505. let realVal = sheetKey.v.replace(/[\*]/g, '');
  506. // 判断下作为key的字段
  507. let isKey = 0; // 0:不是key,1:单key,2:列表key
  508. if (sheetKey.v.slice(0, 2) == '**') {
  509. isKey = 2;
  510. } else if (sheetKey.v.slice(0, 1) == '*') {
  511. isKey = 1;
  512. }
  513. keyList[_lie] = realVal.split(',')[0].trim();
  514. // id:string
  515. excelAndSheets[excelName][sheetName][keyList[_lie]] = {
  516. ps: psList[_lie],
  517. isKey: isKey,
  518. value: typeList[_lie],
  519. keys: realVal
  520. };
  521. }
  522. // 储存数据
  523. if (_hang >= 5 && keyList[_lie] != null && typeList[_lie] != null) {
  524. // 根据类型转化数据内容,在做储存处理
  525. let _val;
  526. if (typeList[_lie] == 'number') {
  527. if (typeof sheetKey.v != 'number') {
  528. _val = Number(sheetKey.v);
  529. if (isNaN(_val)) {
  530. console.log(
  531. '\x1b[33m%s\x1b[0m',
  532. '警告,出现NaN数据类型,表名:' +
  533. excelName +
  534. ' 表单:' +
  535. sheetName +
  536. ' 索引:' +
  537. keyList[_lie] +
  538. ' 表格ID:' +
  539. key
  540. );
  541. }
  542. _val = 0;
  543. } else {
  544. _val = sheetKey.v;
  545. }
  546. } else if (typeList[_lie] == 'boolean') {
  547. if (sheetKey.v == 'true' || sheetKey.v == 'TRUE' || sheetKey.v == true) {
  548. _val = true;
  549. } else {
  550. _val = false;
  551. }
  552. } else if (typeList[_lie][0] == '{' || typeList[_lie].slice(-1) == ']') {
  553. try {
  554. _val = JSON.parse(sheetKey.v);
  555. } catch (error) {
  556. console.log(
  557. '\x1b[33m%s\x1b[0m',
  558. '警告:json格式错误,表名:' + excelName + ' 表单:' + sheetName + ' 索引:' + keyList[_lie] + ' 表格ID:' + key
  559. );
  560. }
  561. } else if (typeList[_lie] == 'string') {
  562. if (typeof sheetKey.v == 'number') {
  563. _val = Math.floor(sheetKey.v).toString();
  564. } else {
  565. _val = sheetKey.v;
  566. }
  567. } else {
  568. _val = sheetKey.v;
  569. }
  570. _tempObj[keyList[_lie].trim()] = _val;
  571. }
  572. }
  573. //这边检测是否有放空配置的。如果有 , 补上默认类型
  574. let _tempObj_1 = {};
  575. for (const key in keyList) {
  576. if (_tempObj[keyList[key]] == null) {
  577. if (typeList[key] == 'number') {
  578. _tempObj_1[keyList[key]] = 0;
  579. } else if (typeList[key] == 'string') {
  580. _tempObj_1[keyList[key]] = '';
  581. } else if (typeList[key] == 'boolean') {
  582. _tempObj_1[keyList[key]] = false;
  583. } else if (typeList[key].indexOf('[]') != -1) {
  584. _tempObj_1[keyList[key]] = null;
  585. } else if (typeList[key].substring(0, 0 + 1) == '{') {
  586. _tempObj_1[keyList[key]] = null;
  587. } else if (typeList[key][0] == "[" && typeList[key][typeList[key].length - 1] == "]") { // 元组
  588. _tempObj_1[keyList[key]] = null;
  589. } else {
  590. console.error('配置表有未知定义', excelName, sheetName, keyList[key], typeList[key]);
  591. }
  592. } else {
  593. _tempObj_1[keyList[key]] = _tempObj[keyList[key]];
  594. }
  595. }
  596. // 储存最后一个
  597. obj[newKey].push(_tempObj_1);
  598. }
  599. // //--------------------start------------------- 控制台人机交互
  600. function readSyncByRl(tips) {
  601. tips = tips || '> ';
  602. return new Promise((resolve) => {
  603. const rl = readline.createInterface({
  604. input: process.stdin,
  605. output: process.stdout
  606. });
  607. rl.question(tips, (answer) => {
  608. rl.close();
  609. resolve(answer.trim());
  610. });
  611. });
  612. }
  613. /**
  614. * 后端创建xls对应gameCfg完成脚本
  615. */
  616. function createGameCfg_s() {
  617. let strs = '';
  618. strs += `import ConfProxy, { ConfListProxy } from "./confProxy"\n`;
  619. let strHead = `XlsConfig`;
  620. let count = 2;
  621. for (const key1 in s_xls.XlsBack) {
  622. for (const key2 in s_xls.XlsBack[key1]) {
  623. if (s_xls.XlsBack[key1][key2].length <= 0) {
  624. continue;
  625. }
  626. strHead += `, xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)}`;
  627. count++;
  628. if (count % 9 == 0) {
  629. strHead += `\n`;
  630. }
  631. }
  632. }
  633. strs += `import { ${strHead} } from "./xlsConfig"\n\n`;
  634. strs += `export default class Gamecfg {\n`;
  635. strs += ` static init() {\n`;
  636. strs += ` let xls = new XlsConfig()\n`;
  637. for (const key1 in s_xls.XlsBack) {
  638. for (const key2 in s_xls.XlsBack[key1]) {
  639. if (s_xls.XlsBack[key1][key2].length <= 0) {
  640. continue;
  641. }
  642. for (const val of s_xls.XlsBack[key1][key2]) {
  643. let cs = ``;
  644. for (let index = 1; index < val.length; index++) {
  645. cs += `,"${val[index]}"`;
  646. }
  647. if (val[0] == 'ConfProxy') {
  648. strs += ` Gamecfg.${key1}${toUpperCaseByStr(key2)} = new ${val[0]}("${key1}${toUpperCaseByStr(key2)}",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs})\n`;
  649. continue;
  650. }
  651. if (val[0] == 'ConfListProxy') {
  652. strs += ` Gamecfg.${key1}${toUpperCaseByStr(key2)}List = new ${val[0]}("${key1}${toUpperCaseByStr(key2)}List",xls.xls${toUpperCaseByStr(
  653. key1
  654. )}${toUpperCaseByStr(key2)} ${cs})\n`;
  655. continue;
  656. }
  657. let cs1 = ``;
  658. for (let index = 2; index < val.length; index++) {
  659. cs1 += `,"${val[index]}"`;
  660. }
  661. //别名
  662. if (val[1] == 'ConfProxy') {
  663. strs += ` Gamecfg.${key1}${toUpperCaseByStr(val[0])} = new ${val[1]}("${key1}${toUpperCaseByStr(val[0])}",xls.xls${toUpperCaseByStr(
  664. key1
  665. )}${toUpperCaseByStr(key2)} ${cs1})\n`;
  666. continue;
  667. }
  668. if (val[1] == 'ConfListProxy') {
  669. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  670. val[0]
  671. )}List = new ${val[1]}("${key1}${toUpperCaseByStr(
  672. val[0]
  673. )}List",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs1})\n`;
  674. continue;
  675. }
  676. }
  677. }
  678. }
  679. strs += ` }\n`;
  680. for (const key1 in s_xls.XlsBack) {
  681. for (const key2 in s_xls.XlsBack[key1]) {
  682. if (s_xls.XlsBack[key1][key2].length <= 0) {
  683. continue;
  684. }
  685. for (const val of s_xls.XlsBack[key1][key2]) {
  686. if (val[0] == 'ConfProxy') {
  687. strs += ` static ${key1}${toUpperCaseByStr(key2)} : ${val[0]}<xls${toUpperCaseByStr(
  688. key1
  689. )}${toUpperCaseByStr(key2)} >\n`;
  690. continue;
  691. }
  692. if (val[0] == 'ConfListProxy') {
  693. strs += ` static ${key1}${toUpperCaseByStr(key2)}List : ${val[0]}<xls${toUpperCaseByStr(
  694. key1
  695. )}${toUpperCaseByStr(key2)}>\n`;
  696. continue;
  697. }
  698. //别名
  699. if (val[1] == 'ConfProxy') {
  700. strs += ` static ${key1}${toUpperCaseByStr(val[0])} : ${val[1]}<xls${toUpperCaseByStr(
  701. key1
  702. )}${toUpperCaseByStr(key2)}>\n`;
  703. continue;
  704. }
  705. if (val[1] == 'ConfListProxy') {
  706. strs += ` static ${key1}${toUpperCaseByStr(
  707. val[0]
  708. )}List : ${val[1]}<xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)}>\n`;
  709. continue;
  710. }
  711. }
  712. }
  713. }
  714. strs += `}\n`;
  715. // 写入文件
  716. let proPath = '';
  717. if (hang == 3) {
  718. proPath = `${path.configPath}gameCfg.ts`;
  719. } else {
  720. proPath = serverPath + `gameCfg.ts`;
  721. }
  722. fs.writeFile(proPath, strs, function (err) {
  723. if (err) {
  724. console.log('gameCfg写入失败:', err);
  725. }
  726. });
  727. }
  728. /**
  729. * 前端创建xls对应gameCfg完成脚本
  730. */
  731. function createGameCfg_c() {
  732. let strs = '';
  733. strs += `import ConfProxy, { ConfListProxy } from "./confProxy"\n`;
  734. let strHead = `XlsConfig`;
  735. let count = 2;
  736. for (const key1 in s_xls.XlsBack) {
  737. for (const key2 in s_xls.XlsBack[key1]) {
  738. if (s_xls.XlsBack[key1][key2].length <= 0) {
  739. continue;
  740. }
  741. strHead += `, xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)}`;
  742. count++;
  743. if (count % 9 == 0) {
  744. strHead += `\n`;
  745. }
  746. }
  747. }
  748. strs += `import { ${strHead} } from "./xlsConfig"\n\n`;
  749. strs += `export default class Gamecfg {\n`;
  750. for (const key1 in s_xls.XlsBack) {
  751. for (const key2 in s_xls.XlsBack[key1]) {
  752. if (s_xls.XlsBack[key1][key2].length <= 0) {
  753. continue;
  754. }
  755. for (const val of s_xls.XlsBack[key1][key2]) {
  756. if (val[0] == 'ConfProxy') {
  757. strs += ` static ${key1}${toUpperCaseByStr(key2)}:${val[0]}<xls${toUpperCaseByStr(
  758. key1
  759. )}${toUpperCaseByStr(key2)}>\n`;
  760. continue;
  761. }
  762. if (val[0] == 'ConfListProxy') {
  763. strs += ` static ${key1}${toUpperCaseByStr(key2)}List:${val[0]}<xls${toUpperCaseByStr(
  764. key1
  765. )}${toUpperCaseByStr(key2)}>\n`;
  766. continue;
  767. }
  768. //别名
  769. if (val[1] == 'ConfProxy') {
  770. strs += ` static ${key1}${toUpperCaseByStr(val[0])}:${val[1]}<xls${toUpperCaseByStr(
  771. key1
  772. )}${toUpperCaseByStr(key2)}>\n`;
  773. continue;
  774. }
  775. //别名
  776. if (val[1] == 'ConfListProxy') {
  777. strs += ` static ${key1}${toUpperCaseByStr(val[0])}List:${val[1]}<xls${toUpperCaseByStr(
  778. key1
  779. )}${toUpperCaseByStr(key2)}>\n`;
  780. continue;
  781. }
  782. }
  783. }
  784. }
  785. strs += `\n`;
  786. strs += ` static initLoading(loadSuccess: Function) {\n`;
  787. strs += ` try {\n`;
  788. strs += ` new XlsConfig("loadJson",(xls: XlsConfig) => {\n`;
  789. for (const key1 in s_xls.XlsBack) {
  790. for (const key2 in s_xls.XlsBack[key1]) {
  791. if (s_xls.XlsBack[key1][key2].length <= 0) {
  792. continue;
  793. }
  794. let jsonName = key1 + toUpperCaseByStr(key2)
  795. if (loadJson.indexOf(jsonName) < 0) {
  796. continue
  797. }
  798. for (const val of s_xls.XlsBack[key1][key2]) {
  799. let cs = ``;
  800. for (let index = 1; index < val.length; index++) {
  801. cs += `,"${val[index]}"`;
  802. }
  803. if (val[0] == 'ConfProxy') {
  804. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  805. key2
  806. )} = new ${val[0]}("${key1}${toUpperCaseByStr(
  807. key2
  808. )}",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs})\n`;
  809. continue;
  810. }
  811. if (val[0] == 'ConfListProxy') {
  812. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  813. key2
  814. )}List = new ${val[0]}("${key1}${toUpperCaseByStr(
  815. key2
  816. )}List",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs})\n`;
  817. continue;
  818. }
  819. let cs1 = ``;
  820. for (let index = 2; index < val.length; index++) {
  821. cs1 += `,"${val[index]}"`;
  822. }
  823. //别名
  824. if (val[1] == 'ConfProxy') {
  825. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  826. val[0]
  827. )} = new ${val[1]}("${key1}${toUpperCaseByStr(
  828. val[0]
  829. )}",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs1})\n`;
  830. continue;
  831. }
  832. if (val[1] == 'ConfListProxy') {
  833. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  834. val[0]
  835. )}List = new ${val[1]}("${key1}${toUpperCaseByStr(
  836. val[0]
  837. )}List",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs1})\n`;
  838. continue;
  839. }
  840. }
  841. }
  842. }
  843. strs += `
  844. loadSuccess(true)
  845. })
  846. } catch (error) {
  847. loadSuccess(false)
  848. }
  849. }`;
  850. strs += `\n`;
  851. strs += ` static init(loadSuccess: Function, progressCallback: Function) {\n`;
  852. strs += ` try {\n`;
  853. strs += ` new XlsConfig("pzwj",(xls: XlsConfig) => {\n`;
  854. for (const key1 in s_xls.XlsBack) {
  855. for (const key2 in s_xls.XlsBack[key1]) {
  856. if (s_xls.XlsBack[key1][key2].length <= 0) {
  857. continue;
  858. }
  859. let jsonName = key1 + toUpperCaseByStr(key2)
  860. if (loadJson.indexOf(jsonName) >= 0) {
  861. continue
  862. }
  863. for (const val of s_xls.XlsBack[key1][key2]) {
  864. let cs = ``;
  865. for (let index = 1; index < val.length; index++) {
  866. cs += `,"${val[index]}"`;
  867. }
  868. if (val[0] == 'ConfProxy') {
  869. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  870. key2
  871. )} = new ${val[0]}("${key1}${toUpperCaseByStr(
  872. key2
  873. )}",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs})\n`;
  874. continue;
  875. }
  876. if (val[0] == 'ConfListProxy') {
  877. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  878. key2
  879. )}List = new ${val[0]}("${key1}${toUpperCaseByStr(
  880. key2
  881. )}List",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs})\n`;
  882. continue;
  883. }
  884. let cs1 = ``;
  885. for (let index = 2; index < val.length; index++) {
  886. cs1 += `,"${val[index]}"`;
  887. }
  888. //别名
  889. if (val[1] == 'ConfProxy') {
  890. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  891. val[0]
  892. )} = new ${val[1]}("${key1}${toUpperCaseByStr(
  893. val[0]
  894. )}",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs1})\n`;
  895. continue;
  896. }
  897. if (val[1] == 'ConfListProxy') {
  898. strs += ` Gamecfg.${key1}${toUpperCaseByStr(
  899. val[0]
  900. )}List = new ${val[1]}("${key1}${toUpperCaseByStr(
  901. val[0]
  902. )}List",xls.xls${toUpperCaseByStr(key1)}${toUpperCaseByStr(key2)} ${cs1})\n`;
  903. continue;
  904. }
  905. }
  906. }
  907. }
  908. strs += `
  909. loadSuccess(true)
  910. }, progressCallback)
  911. } catch (error) {
  912. loadSuccess(false)
  913. }
  914. }
  915. }`;
  916. // 写入文件
  917. let proPath = '';
  918. if (hang == 3) {
  919. proPath = `${path.configPath}gameCfg.ts`;
  920. } else {
  921. proPath = serverPath + `gameCfg.ts`;
  922. }
  923. fs.writeFile(proPath, strs, function (err) {
  924. if (err) {
  925. console.log('gameCfg写入失败:', err);
  926. }
  927. });
  928. }
  929. function createXyc() {
  930. const body = fs.readFileSync(apiurl, "utf-8");
  931. let arr = body.split('/a/apidoc"}]},')
  932. arr[1] = '[' + arr[1]
  933. let arr1 = arr[1].split('}];const');
  934. let str2 = arr1[0].replace(/!1/g, '0') + '}]';
  935. let apidoc = `//所有接口定义\n`
  936. apidoc += `export let apidoc:{[key:string]: {name:string,parms: {[key:string]: {type: string, desc: string}}}} = {\n`
  937. try {
  938. let strc = '';
  939. var jsons = eval('(' + str2 + ')');
  940. for (const json of jsons) {
  941. let jsontitle = json.url.split('/');
  942. let title = toUpperCaseByStr(jsontitle[1]) + toUpperCaseByStr(jsontitle[2]);
  943. let jsonUrl = json.url.slice(1);
  944. strc += `//${json.name}\n`;
  945. strc += `export class ${title}\n`;
  946. strc += `{\n`;
  947. strc += ` static url:string = "${jsonUrl}"\n`;
  948. strc += `}\n`;
  949. strc += `export interface ${title}Pram{\n`;
  950. apidoc += ` "/${jsonUrl}":{name:"${json.name}",parms:{`
  951. let _Parameter = [];
  952. let hasUuid = 0;
  953. let hasToken = 0;
  954. if (json.parameter != null) {
  955. for (const Parameter of json.parameter.fields.Parameter) {
  956. let description = Parameter.description;
  957. let arr11 = description.split('<p>');
  958. let arr12 = arr11[1].split('</p>');
  959. let _type = Parameter.type;
  960. _Parameter.push({
  961. type: _type,
  962. field: Parameter.field,
  963. description: arr12[0]
  964. });
  965. if (Parameter.field == 'uuid') {
  966. hasUuid = 1;
  967. }
  968. if (Parameter.field == 'token') {
  969. hasToken = 1;
  970. }
  971. }
  972. }
  973. for (const _rameter of _Parameter) {
  974. if (hasUuid == 1 && hasToken == 1) {
  975. if (_rameter.field == 'uuid' || _rameter.field == 'token') {
  976. continue;
  977. }
  978. }
  979. strc += ` ${_rameter.field}:${_rameter.type} //${_rameter.description}\n`;
  980. apidoc += `"${_rameter.field}": {type: "${_rameter.type}", desc: "${_rameter.description}"},`
  981. }
  982. strc += `}\n\n`;
  983. apidoc += `}},\n\n`;
  984. }
  985. apidoc += `}`
  986. if (hang == 3) {
  987. outDir = path.configPath;
  988. } else {
  989. outDir = serverPath
  990. }
  991. strc += `
  992. //前端返回的特殊事件
  993. export interface keyValue{
  994. [key:string]:number
  995. }
  996. export interface keyValues{
  997. [key:string]:number[]
  998. }
  999. export interface keyValueString{
  1000. [key:string]:string
  1001. }
  1002. export type ZixuanSelectCs = [string,string,number];
  1003. export type Wxmspinzhi = [number,number]
  1004. export type Wxmskeys = [number,string,string];
  1005. export type Wxmslm = [number,string];
  1006. `
  1007. let proPath = `${outDir}Xyc.ts`;
  1008. fs.writeFileSync(proPath, strc, function (err) {
  1009. if (err) {
  1010. console.log('Xyc写入失败:', err);
  1011. }
  1012. });
  1013. let proPath1 = `${outDir}apidoc.ts`;
  1014. fs.writeFileSync(proPath1, apidoc, function (err) {
  1015. if (err) {
  1016. console.log('Xyc写入失败:', err);
  1017. }
  1018. });
  1019. } catch (error) {
  1020. console.log('===', error);
  1021. }
  1022. }
  1023. //拷贝 s_to_proto
  1024. function copy_s_to_proto() {
  1025. // 或者同步拷贝
  1026. try {
  1027. fse.copySync('../mergerpg_backend_kaifa/src/shared/', './s_to_proto/shared/');
  1028. console.log('目录拷贝完成');
  1029. } catch (err) {
  1030. console.error('拷贝失败:', err);
  1031. }
  1032. }
  1033. //拷贝 proto
  1034. function copy_proto_to_c() {
  1035. outDir = path.sharedPath;
  1036. try {
  1037. fse.copySync('./s_to_proto/shared/', outDir);
  1038. console.log('目录拷贝完成');
  1039. } catch (err) {
  1040. console.error('拷贝失败:', err);
  1041. }
  1042. }
  1043. /**
  1044. * 延迟多少毫秒
  1045. */
  1046. function sleep(ms) {
  1047. if (ms < 1) {
  1048. return;
  1049. }
  1050. return new Promise((reslove, reject) => {
  1051. setTimeout(() => {
  1052. reslove(1);
  1053. }, ms);
  1054. });
  1055. }
  1056. // 开始解析配置表
  1057. function doExe(res) {
  1058. // console.log(res);
  1059. if (res != 'c' && res != 's' && res != 'C' && res != 'S') {
  1060. console.log('非法输入');
  1061. return;
  1062. }
  1063. if (res == 'c' || res == 'C') {
  1064. hang = 3;
  1065. } else {
  1066. hang = 4;
  1067. }
  1068. if (hang == 3) {
  1069. outDir = path.configPath;
  1070. } else {
  1071. outDir = serverPath;
  1072. }
  1073. console.log('\x1b[37m'); // 控制台文字切为白色
  1074. if (hang == 4) {
  1075. fs.rm(serverPath + outJsonFolder, { recursive: true }, (err, data) => {
  1076. if (err) {
  1077. console.log('删除json文件失败' + err);
  1078. }
  1079. console.log('删除json文件成功');
  1080. let sendNum = 0
  1081. let overNum = 0
  1082. // 解析表格
  1083. fs.readdirSync(excelDir).forEach((excelName) => {
  1084. if ((excelName.substr(-4) == '.xls' || excelName.substr(-5) == '.xlsx') && excelName.substr(0, 1) != '~') {
  1085. excelFiles.push(excelName.split('_')[0]);
  1086. const worker = cluster.fork(excelName);
  1087. sendNum += 1
  1088. worker.send({ "hang": 4, "excelName": excelName })
  1089. worker.on('message', function (mes) {
  1090. let mesarr = JSON.parse(mes)
  1091. for (const ar of mesarr.excelFen) {
  1092. excelFen.push(ar)
  1093. }
  1094. for (const key in mesarr.excelAndSheets) {
  1095. excelAndSheets[key] = mesarr.excelAndSheets[key]
  1096. }
  1097. overNum += 1
  1098. console.log(`配置表解析 发送${sendNum}个,完成${overNum}个`)
  1099. })
  1100. }
  1101. });
  1102. const intervalId = setInterval(() => {
  1103. if (sendNum <= overNum) {
  1104. createGameCfg_s();
  1105. console.log('*******创建xls对应gameCfg完成*******');
  1106. copy_s_to_proto();
  1107. console.log('*******拷贝完成*******');
  1108. exeExcelConfig();
  1109. console.log('*******创建配置文件完成*******');
  1110. console.log("----全部完成----")
  1111. clearInterval(intervalId);
  1112. }
  1113. }, 1000);
  1114. });
  1115. }
  1116. if (hang == 3) {
  1117. fs.unlink(path.excelPath + outJsonFolder + '/excel.zip', (err, data) => {
  1118. if (err) {
  1119. console.log('删除zip文件失败' + err);
  1120. }
  1121. console.log('删除zip文件成功');
  1122. let sendNum = 0
  1123. let overNum = 0
  1124. let xls = {}
  1125. // 解析表格
  1126. fs.readdirSync(excelDir).forEach((excelName) => {
  1127. if ((excelName.substr(-4) == '.xls' || excelName.substr(-5) == '.xlsx') && excelName.substr(0, 1) != '~') {
  1128. excelFiles.push(excelName.split('_')[0]);
  1129. // doExcel(excelName);
  1130. xls[excelName] = 1
  1131. const worker = cluster.fork(excelName);
  1132. sendNum += 1
  1133. worker.send({ "hang": 3, "excelName": excelName })
  1134. worker.on('message', function (mes) {
  1135. let mesarr = JSON.parse(mes)
  1136. for (const ar of mesarr.excelFen) {
  1137. excelFen.push(ar)
  1138. }
  1139. for (const key in mesarr.excelAndSheets) {
  1140. excelAndSheets[key] = mesarr.excelAndSheets[key]
  1141. }
  1142. overNum += 1
  1143. delete xls[excelName]
  1144. console.log(`配置表解析 发送${sendNum}个,完成${overNum}个`)
  1145. worker.destroy();
  1146. })
  1147. }
  1148. });
  1149. const intervalId = setInterval(() => {
  1150. if (sendNum <= overNum) {
  1151. // 生成配置表读取文件(ts)
  1152. exeExcelConfig_c();
  1153. console.log('*******创建配置文件完成*******');
  1154. // createXyc();
  1155. // console.log('*******创建xyc完成*******');
  1156. createGameCfg_c();
  1157. console.log('*******创建xls对应gameCfg完成*******');
  1158. copy_proto_to_c();
  1159. console.log('*******拷贝完成*******');
  1160. console.log("----全部完成----")
  1161. clearInterval(intervalId);
  1162. }
  1163. }, 1000);
  1164. });
  1165. }
  1166. sleep(4000);
  1167. // if (hang == 3) {
  1168. //
  1169. // }
  1170. }
  1171. if (!cluster.isMaster) {
  1172. process.on("message", function (message) {
  1173. hang = message.hang
  1174. doExcel(message.excelName)
  1175. process.send(JSON.stringify({ "excelFen": excelFen, "excelAndSheets": excelAndSheets }))
  1176. if(hang == 4){
  1177. process.exit()
  1178. }
  1179. });
  1180. return
  1181. }
  1182. if (jiexiTarget == "s" || jiexiTarget == "c") {
  1183. doExe(jiexiTarget)
  1184. } else {
  1185. readSyncByRl('exe client->c or server->s:').then((res) => {
  1186. doExe(res)
  1187. });
  1188. }
  1189. // //---------------------end-------------------- 控制台人机交互