index.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  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.emptyDirSync('./s_to_proto/shared/');
  1028. fse.copySync('../mergerpg_backend_kaifa/src/shared/', './s_to_proto/shared/');
  1029. fse.emptyDirSync('./s_to_proto/docs/');
  1030. fse.copySync('../mergerpg_backend_kaifa/docs/', './s_to_proto/docs/');
  1031. console.log('目录拷贝完成');
  1032. } catch (err) {
  1033. console.error('拷贝失败:', err);
  1034. }
  1035. }
  1036. //拷贝 proto
  1037. function copy_proto_to_c() {
  1038. outDir = path.sharedPath;
  1039. try {
  1040. // fse.emptyDirSync(outDir);
  1041. fse.copySync('./s_to_proto/shared/', outDir);
  1042. console.log('目录拷贝完成');
  1043. } catch (err) {
  1044. console.error('拷贝失败:', err);
  1045. }
  1046. }
  1047. /**
  1048. * 延迟多少毫秒
  1049. */
  1050. function sleep(ms) {
  1051. if (ms < 1) {
  1052. return;
  1053. }
  1054. return new Promise((reslove, reject) => {
  1055. setTimeout(() => {
  1056. reslove(1);
  1057. }, ms);
  1058. });
  1059. }
  1060. // 开始解析配置表
  1061. function doExe(res) {
  1062. // console.log(res);
  1063. if (res != 'c' && res != 's' && res != 'C' && res != 'S') {
  1064. console.log('非法输入');
  1065. return;
  1066. }
  1067. if (res == 'c' || res == 'C') {
  1068. hang = 3;
  1069. } else {
  1070. hang = 4;
  1071. }
  1072. if (hang == 3) {
  1073. outDir = path.configPath;
  1074. } else {
  1075. outDir = serverPath;
  1076. }
  1077. console.log('\x1b[37m'); // 控制台文字切为白色
  1078. if (hang == 4) {
  1079. fs.rm(serverPath + outJsonFolder, { recursive: true }, (err, data) => {
  1080. if (err) {
  1081. console.log('删除json文件失败' + err);
  1082. }
  1083. console.log('删除json文件成功');
  1084. let sendNum = 0
  1085. let overNum = 0
  1086. // 解析表格
  1087. fs.readdirSync(excelDir).forEach((excelName) => {
  1088. if ((excelName.substr(-4) == '.xls' || excelName.substr(-5) == '.xlsx') && excelName.substr(0, 1) != '~') {
  1089. excelFiles.push(excelName.split('_')[0]);
  1090. const worker = cluster.fork(excelName);
  1091. sendNum += 1
  1092. worker.send({ "hang": 4, "excelName": excelName })
  1093. worker.on('message', function (mes) {
  1094. let mesarr = JSON.parse(mes)
  1095. for (const ar of mesarr.excelFen) {
  1096. excelFen.push(ar)
  1097. }
  1098. for (const key in mesarr.excelAndSheets) {
  1099. excelAndSheets[key] = mesarr.excelAndSheets[key]
  1100. }
  1101. overNum += 1
  1102. console.log(`配置表解析 发送${sendNum}个,完成${overNum}个`)
  1103. })
  1104. }
  1105. });
  1106. const intervalId = setInterval(() => {
  1107. if (sendNum <= overNum) {
  1108. createGameCfg_s();
  1109. console.log('*******创建xls对应gameCfg完成*******');
  1110. copy_s_to_proto();
  1111. console.log('*******拷贝完成*******');
  1112. exeExcelConfig();
  1113. console.log('*******创建配置文件完成*******');
  1114. console.log("----全部完成----")
  1115. clearInterval(intervalId);
  1116. }
  1117. }, 1000);
  1118. });
  1119. }
  1120. if (hang == 3) {
  1121. fs.unlink(path.excelPath + outJsonFolder + '/excel.zip', (err, data) => {
  1122. if (err) {
  1123. console.log('删除zip文件失败' + err);
  1124. }
  1125. console.log('删除zip文件成功');
  1126. let sendNum = 0
  1127. let overNum = 0
  1128. let xls = {}
  1129. // 解析表格
  1130. fs.readdirSync(excelDir).forEach((excelName) => {
  1131. if ((excelName.substr(-4) == '.xls' || excelName.substr(-5) == '.xlsx') && excelName.substr(0, 1) != '~') {
  1132. excelFiles.push(excelName.split('_')[0]);
  1133. // doExcel(excelName);
  1134. xls[excelName] = 1
  1135. const worker = cluster.fork(excelName);
  1136. sendNum += 1
  1137. worker.send({ "hang": 3, "excelName": excelName })
  1138. worker.on('message', function (mes) {
  1139. let mesarr = JSON.parse(mes)
  1140. for (const ar of mesarr.excelFen) {
  1141. excelFen.push(ar)
  1142. }
  1143. for (const key in mesarr.excelAndSheets) {
  1144. excelAndSheets[key] = mesarr.excelAndSheets[key]
  1145. }
  1146. overNum += 1
  1147. delete xls[excelName]
  1148. console.log(`配置表解析 发送${sendNum}个,完成${overNum}个`)
  1149. worker.destroy();
  1150. })
  1151. }
  1152. });
  1153. const intervalId = setInterval(() => {
  1154. if (sendNum <= overNum) {
  1155. // 生成配置表读取文件(ts)
  1156. exeExcelConfig_c();
  1157. console.log('*******创建配置文件完成*******');
  1158. // createXyc();
  1159. // console.log('*******创建xyc完成*******');
  1160. createGameCfg_c();
  1161. console.log('*******创建xls对应gameCfg完成*******');
  1162. copy_proto_to_c();
  1163. console.log('*******拷贝完成*******');
  1164. console.log("----全部完成----")
  1165. clearInterval(intervalId);
  1166. }
  1167. }, 1000);
  1168. });
  1169. }
  1170. sleep(4000);
  1171. // if (hang == 3) {
  1172. //
  1173. // }
  1174. }
  1175. if (!cluster.isMaster) {
  1176. process.on("message", function (message) {
  1177. hang = message.hang
  1178. doExcel(message.excelName)
  1179. process.send(JSON.stringify({ "excelFen": excelFen, "excelAndSheets": excelAndSheets }))
  1180. if(hang == 4){
  1181. process.exit()
  1182. }
  1183. });
  1184. return
  1185. }
  1186. if (jiexiTarget == "s" || jiexiTarget == "c") {
  1187. doExe(jiexiTarget)
  1188. } else {
  1189. readSyncByRl('exe client->c or server->s:').then((res) => {
  1190. doExe(res)
  1191. });
  1192. }
  1193. // //---------------------end-------------------- 控制台人机交互