diff --git a/src/utils/StringUtils.js b/src/utils/StringUtils.js index 40c71e3..a3b9ed1 100644 --- a/src/utils/StringUtils.js +++ b/src/utils/StringUtils.js @@ -31,6 +31,36 @@ String.prototype.format = function (args) { } } +// chatGPT的 2.0 改进建议 +// String.prototype.format = function (...args) { +// const pattern = /\{(\d*|\w*)\}/g; +// return this.replace(pattern, (match, p1) => { +// if (p1 === '') { +// throw new Error('占位符不能为空'); +// } +// +// if (isNaN(p1)) { +// if (!args[0] || typeof args[0] !== 'object') { +// throw new Error('需要传入一个对象作为参数'); +// } +// +// const value = args[0][p1]; +// if (value === undefined) { +// throw new Error(`对象中没有名为${p1}的属性`); +// } +// +// return value; +// } +// +// const index = parseInt(p1); +// if (index >= args.length) { +// throw new Error(`占位符{${p1}}没有对应的参数`); +// } +// +// return args[index]; +// }); +// }; + /** * 取出所有a到b中间的字符串 * diff --git a/src/utils/storageHelper.ts b/src/utils/storageHelper.ts new file mode 100644 index 0000000..c519019 --- /dev/null +++ b/src/utils/storageHelper.ts @@ -0,0 +1,201 @@ +/** + * chatGPT改进版 + */ +interface StorageItem { + value: any; + lostTime?: Date; +} + +const storageHelper = { + /** + * + * @param name 保存名称 + * @param key 保存的key + * @param value 保存的值 + * @param time 失活时间,默认无限 + */ + set: function (name: string, key: string, value: any, time?: Date): void { + const str = localStorage.getItem(name); + let storage: { [key: string]: StorageItem }; + try { + storage = JSON.parse(str || '{}') + } catch (e) { + console.error(`无法解析数据名称 "${name}" ,该数据可能已损坏。`) + console.error('目标数据:\n' + str) + return; + } + storage[key] = { + value, + lostTime: time, + } + localStorage.setItem(name, JSON.stringify(storage)) + }, + /** + * 读取数据 + * @param name + * @param key + */ + get: function (name: string, key: string): any { + const str = localStorage.getItem(name); + let storage: { [key: string]: StorageItem }; + try { + storage = JSON.parse(str) + } catch (e) { + console.error(`无法解析数据名称 "${name}" ,该数据可能已损坏。`) + console.error('目标数据:\n' + str) + return; + } + this.clearLostTimeData(name) + return storage[key]?.value; + }, + /** + * 删除目标数据 + * @param name + * @param key + */ + remove: function (name: string, key?: string | string[]) { + if (!name) return; + const str = localStorage.getItem(name); + let storage: { [key: string]: StorageItem }; + try { + storage = JSON.parse(str || '{}') + } catch (e) { + console.error(`无法解析数据名称 "${name}" ,该数据可能已损坏。`) + console.error('目标数据:\n' + str) + return; + } + if (!key) { + localStorage.removeItem(name); + return; + } + const keys = Array.isArray(key) ? key : [key]; + for (const k of keys) { + if (storage[k]) { + storage[k] = undefined; + } + } + localStorage.setItem(name, JSON.stringify(storage)); + }, + /** + * 清除失活的数据 + * @param name + */ + clearLostTimeData: function (name: string): boolean { + const str = localStorage.getItem(name); + let storage: { [key: string]: StorageItem }; + try { + storage = JSON.parse(str || '{}'); + } catch (e) { + return false; + } + const keys = Object.keys(storage); + const now = new Date().getTime(); + let changed = false; + for (const k of keys) { + if (storage[k].lostTime && storage[k].lostTime.getTime() < now) { + storage[k] = undefined; + changed = true; + } + } + if (changed) { + const remainingKeys = Object.keys(storage).filter(k => storage[k]); + if (remainingKeys.length > 0) { + localStorage.setItem(name, JSON.stringify(storage)); + } else { + localStorage.removeItem(name); + } + } + return changed; + }, +}; + +export default storageHelper; + + +/** + * 原始版本 + */ +// const storageHelper = { +// /** +// * +// * @param name 保存名称 +// * @param key 保存的key +// * @param value 保存的值 +// * @param time 失活时间,默认无限 +// */ +// set: function (name: string, key: string, value: any, time: Date = undefined) { +// const str = localStorage.getItem(name); +// let storage: object; +// try { +// storage = JSON.parse(str || '{}') +// } catch (e) { +// console.error(`无法解析数据名称 "${name}" ,该数据可能已损坏。`) +// console.error('目标数据:\n' + str) +// return; +// } +// storage[key] = { +// value, +// lostTime: time, +// } +// localStorage.setItem(name, JSON.stringify(storage)) +// }, +// get: function (name: string, key: string): any { +// const str = localStorage.getItem(name); +// let storage: object; +// try { +// storage = JSON.parse(str) +// } catch (e) { +// console.error(`无法解析数据名称 "${name}" ,该数据可能已损坏。`) +// console.error('目标数据:\n' + str) +// return; +// } +// this.clearLostTimeData(name) +// return storage[key].data +// }, +// remove: function (name: string, key: any) { +// if (name) { +// if (key) { +// const str = localStorage.getItem(name); +// let storage: object; +// try { +// storage = JSON.parse(str) +// } catch (e) { +// console.error(`无法解析数据名称 "${name}" ,该数据可能已损坏。`) +// console.error('目标数据:\n' + str) +// return; +// } +// if (Array.isArray(key)) { +// +// } +// } else { +// localStorage.removeItem(name) +// } +// } +// }, +// clearLostTimeData: function (name: string) { +// const str = localStorage.getItem(name); +// let storage: object; +// try { +// storage = JSON.parse(str); +// } catch (e) { +// return false; +// } +// let keys = Object.keys(storage) +// let now = new Date().getTime() +// keys.forEach((key, i) => { +// if (storage[key].lostTime && storage[key].lostTime.getTime() < now) { +// storage[key] = undefined +// } +// }) +// keys = Object.keys(storage) +// if (keys.length == 0) { +// localStorage.removeItem(name) +// return false; +// } else { +// return true; +// } +// }, +// } +// +// export default storageHelper + diff --git a/src/views/wc3word/dialog/SpellBuilder.vue b/src/views/wc3word/dialog/SpellBuilder.vue index b0c143d..11ee1d0 100644 --- a/src/views/wc3word/dialog/SpellBuilder.vue +++ b/src/views/wc3word/dialog/SpellBuilder.vue @@ -108,7 +108,7 @@ export default { handleSave() { }, dyeing(str, color) { - const prefix = '|cfff' + const prefix = '|cff' const suffix = '|r' return color ? (prefix + color.replace('#', "") + str + suffix) : str }, diff --git a/src/views/wc3word/dialog/load.vue b/src/views/wc3word/dialog/load.vue new file mode 100644 index 0000000..0ece342 --- /dev/null +++ b/src/views/wc3word/dialog/load.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/views/wc3word/dialog/updateRecord.vue b/src/views/wc3word/dialog/updateRecord.vue deleted file mode 100644 index 9a96ca8..0000000 --- a/src/views/wc3word/dialog/updateRecord.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/src/views/wc3word/dialog/version.js b/src/views/wc3word/dialog/version.js new file mode 100644 index 0000000..6ea05c7 --- /dev/null +++ b/src/views/wc3word/dialog/version.js @@ -0,0 +1,26 @@ +const version = { + '1.0': { + 7: [ + {type: '完成', value: '更新日志'}, + {type: '修复', value: '技能文本恢复默认时没有清空数值的bug'}, + ], + 6: [ + {type: '新', value: '导出导入技能'}, + ], + 5: [ + {type: '完成', value: '技能文本的保存能力'}, + {type: '修复', value: '新的技能数值输入方法'}, + ], + 3: [ + {type: '完成', value: '生成器文本实时同步'}, + {type: '完成', value: '色彩及生成器恢复默认按钮'}, + {type: '完成', value: '保存色彩方案'}, + ], + 2: [ + {type: '完成', value: '色彩'}, + {type: '完成', value: '编辑'}, + ], + } +} + +export default version diff --git a/src/views/wc3word/index.vue b/src/views/wc3word/index.vue index dfd49b0..62b8a82 100644 --- a/src/views/wc3word/index.vue +++ b/src/views/wc3word/index.vue @@ -14,6 +14,10 @@ + + 更新日志 + + @@ -22,15 +26,17 @@ import Color from "@/views/wc3word/color"; import Edit from "@/views/wc3word/edit"; import {defaultColorConfig} from '@/utils/tools' +import UpdateRecord from "@/views/wc3word/updateRecord"; +import version from '@/views/wc3word/dialog/version'; export default { name: 'Word', - components: {Edit, Color}, + components: {UpdateRecord, Edit, Color}, data() { return { colorConfig: Object.assign({}, defaultColorConfig), - version: '1.0.3' + version: '1.0.0' } }, computed: {}, @@ -38,6 +44,9 @@ export default { created() { }, mounted() { + const latestVersion = Object.entries(version).pop() // 获取最后一个版本号码 + const latestSubVersion = Object.keys(latestVersion[1]).pop() // 获取最后一个子版本号码 + this.version = `${latestVersion[0]}.${latestSubVersion}` const h = this.$createElement; this.$notify({ title: '来自Soul2的提示', diff --git a/src/views/wc3word/updateRecord.vue b/src/views/wc3word/updateRecord.vue new file mode 100644 index 0000000..8ad63a7 --- /dev/null +++ b/src/views/wc3word/updateRecord.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/views/word_builder/tools/tools.js b/src/views/word_builder/tools/tools.js new file mode 100644 index 0000000..8c595ca --- /dev/null +++ b/src/views/word_builder/tools/tools.js @@ -0,0 +1,8 @@ +const wwbTools = { + dyeing: (str, color) => { + const prefix = '|cfff' + const suffix = '|r' + return color ? (prefix + color.replace('#', "") + str + suffix) : str + }, +} +export default wwbTools diff --git a/src/views/word_builder/wc3data/json.js b/src/views/word_builder/wc3data/json.js new file mode 100644 index 0000000..c6eb239 --- /dev/null +++ b/src/views/word_builder/wc3data/json.js @@ -0,0 +1,153 @@ +import wwbTools from '@/views/word_builder/tools/tools' +/* Spell */ +const default_spell_module = { + name: null, // 技能名称 + hotKey: null, // 热键 + learn: { // 学习文本设置 + title: null, // 学习标题 + tip: { // 学习扩展文本 + effect: null, // 效果描述 + attr: () => this.attrData.filter(e => !Array.isArray(e)), // 属性 + lvEffect: [ // 每个等级的效果描述 + // { text: '造成{a}点伤害和{b}秒眩晕', data: [100,3] } + ], + }, + }, + attrData: [ + /** + * { name: '法力消耗', value: null } + * or + * { name: '法力消耗', value: [] } + */ + ], + normal: { // 普通技能文本 + attr: () => this.attrData.filter(e => e.name !== '法力消耗'), + title: null, // 标题 + tip: [ + /** { text: '造成{a}点伤害和{b}秒眩晕', data: [100,3] } */ + ] + }, + nature: null, // 特点 + toWord: (color, module, lv) => { + let result = '' + if (module) { + if (module === 'title') { + if (lv) { + result += `${this.name}(${wwbTools.dyeing(this.hotKey, color.hotKey)})` + result += ` - [${wwbTools.dyeing(lv + '级', color.level)}]` + } else { + lv = '%d' + result += `学习 ${wwbTools.dyeing(lv + '级', color.level)} ${this.name}(${wwbTools.dyeing(this.hotKey, color.hotKey)})` + } + } else if (module === 'uberTip') { + if (lv) { // 有lv,返回普通文本 + lv = Math.min(lv, this.normal.tip.length) + let d = this.normal.tip[lv] + result += d.text.format(...d.data) + result += this.nature ? ('\n\n' + wwbTools.dyeing(this.nature, color.nature)) : '' + if (this.normal.attr().length > 0) { + result += ('\n') + this.normal.attr().forEach((e) => { + result += ('\n' + wwbTools.dyeing(e.name, color.property) + ':') + try { + result += (Array.isArray(e.value) ? e.value[lv] : e.value) + } catch (e) { + result += e.value[e.value.length - 1] + } + }) + } + } else { // 无lv,返回学习文本 + result += (this.learn.tip.effect) + result += this.nature ? ('\n\n' + wwbTools.dyeing(this.nature, color.nature)) : '' + if (this.learn.tip.attr().length > 0) { + result += '\n' + this.learn.tip.attr().forEach((e) => { + result += ('\n' + wwbTools.dyeing(e.name, color.property) + ':') + try { + result += (Array.isArray(e.value) ? e.value[lv] : e.value) + } catch (e) { + result += e.value[e.value.length - 1] + } + }) + } + if (this.learn.tip.lvEffect?.length > 0) { + result += '\n' + this.learn.tip.lvEffect.forEach((e, i) => { + result += ('\n' + wwbTools.dyeing((i + 1) + '级 - ', color.learnUpdateLevel)) + result += (e.text.format(...e.data)) + }) + } + } + } + } + return result + }, +} + + +/* Unit */ +const default_unit_module = { + name: null, // 单位名称 + desc: null, // 单位描述,可填充数据项 + descValues: null, // 单位描述数据 + hotKey: null, // 热键 + spells: [ // 技能列表,可以是对象列表,也可以是字符串列表 + { + name: null, // 技能名称 + desc: null, // 技能简述,不可填充数据,可选项 + }, { + name: null, // 技能名称 + desc: null, // 技能简述,不可填充数据,可选项 + }, + ], + nature: null, // 特点 + attack: { // 攻击力设置 + max: null, // 攻击力上限 + min: null, // 攻击力下限 + dice: { // 骰子设置 + count: null, // 骰子个数 + sides: null, // 骰子面数 + }, + type: null, // 攻击力类型 + range: null, // 射程 + }, + hp: null, // 最大生命值 + mp: null, // 最大法力值 + armor: { // 护甲设置 + value: null, // 护甲值 + type: null // 护甲类型 + }, +} + +/* item */ +const default_item_module = { + overlapping: false, // 是否可叠加,默认否 + hotKey: null, // 热键 + uses: 0, // 使用次数,默认是0 + price: 125, // 价格,默认是125 + desc: { // 说明设置 + tip: null, // 放地上鼠标点击显示的文本提示 + title: null, // 标题 + uberTip: null, // 扩展 + }, + cd: { // 冷却时间,默认不显示 + show: false, + value: 0 + }, + beLost: true, // 可以被丢弃 + beSold: true, // 可卖给商店 + attributes: [ // 属性 + { + type: 'gain', // gain=增益;reduce=减损;spell=技能 + name: null, // 属性名称,类型为spell时为技能名 + tip: null, // 技能描述,类型是spell时显示 + value: null, // 属性值,类型是spell时不显示 + }, + /** + * example: { type: gain, name: 力量, value: 3} -> result: 力量+3 + * example: { type: reduce, name: 力量, value: 3} -> result: |cffff0000力量-3|r + * example: { type: spell, name: 能量冲击, tip: 召唤能量光柱攻击敌人,造成100点伤害和3秒眩晕。} -> + * result: |cff00ff00能量冲击|r|n召唤能量光柱攻击敌人,造成100点伤害和3秒眩晕。 + */ + ], +} diff --git a/src/views/word_builder/wc3data/temp.js b/src/views/word_builder/wc3data/temp.js new file mode 100644 index 0000000..139597f --- /dev/null +++ b/src/views/word_builder/wc3data/temp.js @@ -0,0 +1,2 @@ + +