UNPKG

fy-convertor

Version:

Convert excel/xml/json/bin/protocl/ts/as ...

216 lines 8.9 kB
import fs from "fs-extra"; import path from "path"; import xlsx from 'xlsx'; import { JsonStructParser } from "./JsonStructParser.js"; import xml2js from "xml-js"; import { md5 } from "../tools/vendor.js"; import { CharLike, NumberLike, isComplexType } from "./def.js"; import _ from "lodash"; import { toolchain } from "../tools/toolchain.js"; import { SvnHolder } from "./SvnHolder.js"; export class Xls2Xml { static ins; static get Instance() { if (!Xls2Xml.ins) Xls2Xml.ins = new Xls2Xml(); return Xls2Xml.ins; } keyWordMap = {}; async execute() { if (!toolchain.options.input) return; const tmpFolder = toolchain.options.publish ? toolchain.options.project + '_publish' : toolchain.options.project; const temp = path.join(toolchain.options.workspace, tmpFolder); const xmlPath = path.join(temp, 'xml'); const xlsPath = path.join(temp, 'xls'); const structPath = path.join(temp, 'struct'); // 更新svn await SvnHolder.Instance.checkSVN(!toolchain.options.debug, structPath, this.adjustSVN(toolchain.projCfg.Svn.DesignerSvn, toolchain.options.publish) + 'xml'); await SvnHolder.Instance.checkSVN(!toolchain.options.debug, xmlPath, this.adjustSVN(toolchain.projCfg.Svn.DesignerSvn, toolchain.options.publish) + 'bin/Client'); await SvnHolder.Instance.checkSVN(!toolchain.options.debug, xlsPath, this.adjustSVN(toolchain.projCfg.Svn.DesignerSvn, toolchain.options.publish) + 'xls'); await JsonStructParser.Instance.readStructs(structPath, false); const macros = JsonStructParser.Instance.getMacrosOfFile('KeyWord.xml'); for (const macro of macros) { this.keyWordMap[macro._attributes.cname] = Number(macro._attributes.value); } const xlsFiles = toolchain.options.input.split(','); for (const x of xlsFiles) { const xls = path.join(xlsPath, x); const cinfos = JsonStructParser.Instance.getConvInfosByXls(xls); if (cinfos.length == 0) { console.error('no convert info:', xls); continue; } const xlsxBook = xlsx.readFile(xls); for (const info of cinfos) { // 由于不支持服务器bin文件生成,故只处理前台表格 if (!info.meta.endsWith('_Flash')) continue; const def = JsonStructParser.Instance.getStructDef(info.meta.replace('_Flash', 'M')); if (!def) { console.error('no struct def:', info.meta); continue; } const sheets = info.sheet.split(' '); const arr = []; for (const s of sheets) { const sheet = xlsxBook.Sheets[s]; const rows = xlsx.utils.sheet_to_json(sheet, { blankrows: true }); for (const row of rows) { if (this.isEmptyRow(row)) { break; } const o = this.readRow(row, def); arr.push(o); } } if (def._attributes.sortkey) { _.sortBy(arr, def._attributes.sortkey); } const doc = this.makeXmlDoc(info, arr); await fs.writeFile(path.join(xmlPath, path.basename(info.bin.replace('.bin', '.xml'))), doc, 'utf-8'); } } // 提交svn if (!toolchain.options.debug) { console.log("Committing..."); await SvnHolder.Instance.commitSVN('xls2xml@fy-convertor~', xmlPath); } else { console.log("Debug mode, committing skipped."); } } adjustSVN(raw, publish) { if (publish) { raw = raw.replace('trunk', 'branches/publish'); } return raw; } readRow(row, def, prefix = '') { const o = {}; if (def._attributes.rootflag) { o._attributes = { version: '1' }; } else { o._attributes = { type: def._attributes.__rawName__ }; } for (const entry of def.entries) { let arrSize = -1; if (entry._attributes.refer) { const referedEntry = def.entries.find(v => v._attributes.name == entry._attributes.refer); arrSize = Number(row[referedEntry._attributes.cname]) || 0; } else if (entry._attributes.count) { if (entry._attributes.count.match(/^\d+$/)) { arrSize = Number(entry._attributes.count); } else { const macro = JsonStructParser.Instance.getMacro(entry._attributes.count); if (!macro) { console.error('no macro definition:', entry._attributes.count); process.exit(1); } arrSize = Number(macro._attributes.value); } } if (isComplexType(entry._attributes.type)) { const entryDef = JsonStructParser.Instance.getStructDef(entry._attributes.type); if (!entryDef) { console.error('no struct def:', entry._attributes.type); process.exit(1); } if (arrSize >= 0) { const arr = []; for (let i = 0; i < arrSize; i++) { const e = this.readRow(row, entryDef, entry._attributes.cname + (i + 1)); arr.push(e); } o[entry._attributes.name] = arr; } else { o[entry._attributes.name] = this.readRow(row, entryDef); } } else { if (arrSize >= 0) { const arr = []; for (let i = 0; i < arrSize; i++) { const v = this.convertSimpleValue(row[entry._attributes.cname + (i + 1)], entry._attributes.type); arr.push(v); } o[entry._attributes.name] = { _text: arr.join('') }; } else { let v = this.convertSimpleValue(row[prefix + entry._attributes.cname], entry._attributes.type); o[entry._attributes.name] = { _text: v }; } } } return o; } convertSimpleValue(v, type) { if (v == undefined) { // xml里定了这个字段,但表格里没有对应的列 v = NumberLike.includes(type) ? 0 : ''; } if (NumberLike.includes(type)) { if (typeof (v) == 'string') { const kwv = this.keyWordMap[v]; if (kwv != null) { v = kwv; } else { v = Number(v) || 0; } } if (typeof (v) == 'number') { if (CharLike.includes(type)) { v = '0x' + v.toString(16) + ' '; } else { v = String(v) + ' '; } } } return v; } isEmptyRow(row) { for (const key in row) { if (row[key]) { return false; } } return true; } makeXmlDoc(info, arr) { // var json = '{"name":{"_text":"Ali"},"age":{"_text":"30"}}'; // var options = {compact: true}; // var content = xml2js.json2xml(json, options); const o = {}; o[info.meta] = arr; const content = xml2js.js2xml(o, { compact: true, spaces: 4 }); const hash = md5(content); const doc = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <${info.meta}_Tab> <TResHeadAll version="5"> <resHead type="TResHead"> <Magic>1397052237 </Magic> <Version>6 </Version> <Unit>0 </Unit> <Count>${arr.length} </Count> <MetalibHash>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</MetalibHash> <ResVersion>0 </ResVersion> <CreateTime> 0-00-00 00:00:00</CreateTime> <ResEncording>UTF-8</ResEncording> <ContentHash>${hash}</ContentHash> </resHead> <resHeadExt type="TResHeadExt"> <DataOffset>136 </DataOffset> </resHeadExt> </TResHeadAll> ${content} </${info.meta}_Tab>`; return doc; } } //# sourceMappingURL=Xls2Xml.js.map