From 73715f015fe417d0a4e07f027f55b7fa9b798d07 Mon Sep 17 00:00:00 2001 From: bietiaop <1527109126@qq.com> Date: Sat, 1 Mar 2025 20:25:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=92=E8=89=B2=E5=91=BD=E5=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/help.js | 7 +++ apps/wiki.js | 21 +++++++ lib/assets/hakushurl.js | 2 + lib/download.js | 10 ++++ lib/download/const.js | 3 +- lib/download/download.js | 7 ++- model/hakush/character.js | 46 +++++++++++++-- resources/cinema/index.css | 86 ++++++++++++++++++++++++++++ resources/cinema/index.html | 43 ++++++++++++++ resources/cinema/index.scss | 95 +++++++++++++++++++++++++++++++ resources/common/style/index.css | 8 +-- resources/common/style/index.scss | 10 ++-- 12 files changed, 324 insertions(+), 14 deletions(-) create mode 100644 resources/cinema/index.css create mode 100644 resources/cinema/index.html create mode 100644 resources/cinema/index.scss diff --git a/apps/help.js b/apps/help.js index d22cdf1..102a6d2 100644 --- a/apps/help.js +++ b/apps/help.js @@ -208,6 +208,13 @@ const helpData = [ needSK: false, commands: ['角色名+天赋[+等级]'], }, + { + title: '角色意象影画图鉴', + desc: '查看角色命座图鉴', + needCK: false, + needSK: false, + commands: ['角色名+命座', '角色名+意象', '角色名+影画'], + }, ], }, { diff --git a/apps/wiki.js b/apps/wiki.js index 781a4cb..304bfbc 100644 --- a/apps/wiki.js +++ b/apps/wiki.js @@ -43,10 +43,15 @@ export class Wiki extends ZZZPlugin { reg: `${rulePrefix}(.*)天赋(.*)$`, fnc: 'skills', }, + { + reg: `${rulePrefix}(.*)(意象影画|意象|影画|命座)$`, + fnc: 'cinema', + }, ], }); } async skills() { + logger.debug('skills'); const reg = new RegExp(`${rulePrefix}(.*)天赋(.*)$`); const charname = this.e.msg.match(reg)[4]; if (!charname) return false; @@ -94,4 +99,20 @@ export class Wiki extends ZZZPlugin { }; await this.render('skills/index.html', finalData); } + async cinema() { + const reg = new RegExp(`${rulePrefix}(.*)(意象影画|意象|影画|命座)$`); + const charname = this.e.msg.match(reg)[4]; + if (!charname) return false; + const charData = await getHakushCharacterData(charname); + const cinemaData = charData?.Talent; + if (!cinemaData) { + await this.reply(`未找到${charname}的数据`); + return false; + } + await charData.get_assets(); + const finalData = { + charData, + }; + await this.render('cinema/index.html', finalData); + } } diff --git a/lib/assets/hakushurl.js b/lib/assets/hakushurl.js index 2c10701..4d26825 100644 --- a/lib/assets/hakushurl.js +++ b/lib/assets/hakushurl.js @@ -7,3 +7,5 @@ export const ZZZ_CHARACTER = HAKUSH_API + '/character', export const ZZZ_NEW = `${HAKUSH_BASE}/new.json`, ZZZ_ALL_CHAR = `${HAKUSH_BASE}/data/character.json`, ZZZ_ALL_WEAPON = `${HAKUSH_BASE}/data/weapon.json`; + +export const ZZZ_UI = `${HAKUSH_BASE}/UI`; diff --git a/lib/download.js b/lib/download.js index 5a12d23..9e0e7fa 100644 --- a/lib/download.js +++ b/lib/download.js @@ -165,3 +165,13 @@ export const getHakushWeapon = async weaponId => { ); return result; }; + +/** + * 获取Hakush UI + * @param {string} filename + * @returns {Promise} + */ +export const getHakushUI = async filename => { + const result = await downloadHakushFile('ZZZ_UI', 'HAKUSH_UI_PATH', filename); + return result; +}; diff --git a/lib/download/const.js b/lib/download/const.js index 84b667a..914c351 100644 --- a/lib/download/const.js +++ b/lib/download/const.js @@ -21,4 +21,5 @@ export const HAKUSH_CHARACTER_DATA_PATH = path.join( dataResourcesPath, 'hakush/data/character' ), - HAKUSH_WEAPON_DATA_PATH = path.join(dataResourcesPath, 'hakush/data/weapon'); + HAKUSH_WEAPON_DATA_PATH = path.join(dataResourcesPath, 'hakush/data/weapon'), + HAKUSH_UI_PATH = path.join(imageResourcesPath, 'hakush/ui'); diff --git a/lib/download/download.js b/lib/download/download.js index ee5e0c2..ad37a99 100644 --- a/lib/download/download.js +++ b/lib/download/download.js @@ -74,7 +74,12 @@ export const downloadHakushFile = async (base, localBase, filename = '') => { // 关闭文件 fs.closeSync(file); // 返回文件内容 - return JSON.parse(content.toString()); + // 如果是JSON文件,返回JSON对象 + if (filename.endsWith('.json')) { + return JSON.parse(content.toString()); + } else { + return filepath; + } } else { return null; } diff --git a/model/hakush/character.js b/model/hakush/character.js index d9f7ae3..e528166 100644 --- a/model/hakush/character.js +++ b/model/hakush/character.js @@ -1,4 +1,4 @@ -import { getSquareAvatar } from '../../lib/download.js'; +import { getHakushUI, getSquareAvatar } from '../../lib/download.js'; /** * @typedef {Object} StatsData * @property {number} Armor @@ -512,6 +512,38 @@ class TalentLevel { this.Name = data.Name; this.Desc = data.Desc; this.Desc2 = data.Desc2; + + /** @type {string} */ + this.description = this.Desc + ? '
' + + this.Desc.replace( + //g, + '' + ) + .replace( + /(.+?)<\/color>/g, + '$2' + ) + .split('\n') + .join('
') + + '
' + : ''; + + /** @type {string} */ + this.description2 = this.Desc2 + ? '
' + + this.Desc2.replace( + //g, + '' + ) + .replace( + /(.+?)<\/color>/g, + '$2' + ) + .split('\n') + .join('
') + + '
' + : ''; } } @@ -555,7 +587,7 @@ export class Character { this.Stats = new Stats(data.Stats); this.Level = {}; this.ExtraLevel = {}; - this.Talent = {}; + this.Talent = []; for (const [key, value] of Object.entries(data.Level)) { this.Level[key] = new Level(value); @@ -566,13 +598,19 @@ export class Character { this.Skill = new Skill(data.Skill); this.Passive = new Passive(data.Passive); - for (const [key, value] of Object.entries(data.Talent)) { - this.Talent[key] = new TalentLevel(value); + for (const [_, value] of Object.entries(data.Talent)) { + this.Talent.push(new TalentLevel(value)); } } async get_assets() { const result = await getSquareAvatar(this.Id); this.square_icon = result; + await this.get_cinema_assets(); + } + + async get_cinema_assets() { + const result = await getHakushUI(`Mindscape_${this.Id}_3.webp`); + this.cinema_image = result; } } diff --git a/resources/cinema/index.css b/resources/cinema/index.css new file mode 100644 index 0000000..47ce96a --- /dev/null +++ b/resources/cinema/index.css @@ -0,0 +1,86 @@ +.char-info { + display: flex; + align-items: flex-start; + padding: 1em; + gap: 1em; +} +.char-info .avatar { + width: 5em; + aspect-ratio: 1; + flex-grow: 0; + flex-shrink: 0; + background-color: white; + border-radius: 50%; + overflow: hidden; +} +.char-info .avatar img { + width: 100%; + height: 100%; + object-fit: cover; +} +.char-info .info { + display: flex; + flex-direction: column; + gap: 0.5em; +} +.char-info .info .name { + display: flex; + align-items: flex-end; + gap: 0.5em; +} +.char-info .info .name .simple { + font-size: 1.5em; +} +.char-info .info .description { + font-size: 0.8em; +} + +.cinema { + padding: 1em; +} +.cinema .header { + margin-bottom: 1rem; +} +.cinema .title { + color: white; + font-size: 2rem; + margin: 0; +} +.cinema .subtitle { + color: #6666ff; + font-size: 1.5rem; + margin: 0; +} +.cinema .content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; +} +.cinema .section { + margin-bottom: 1rem; +} +.cinema .section-title { + font-size: 1.5rem; + margin-bottom: 0.5rem; +} +.cinema .section-content { + font-size: 1.3rem; + line-height: 1.5; +} +.cinema .highlight { + color: #ffd700; +} +.cinema .skill-tag { + display: inline-block; + margin-right: 0.5rem; +} +.cinema .image-container { + text-align: center; + margin-top: 1rem; +} +.cinema .character-image { + max-width: 100%; + border-radius: 0.5rem; +} + +/*# sourceMappingURL=index.css.map */ diff --git a/resources/cinema/index.html b/resources/cinema/index.html new file mode 100644 index 0000000..14e703b --- /dev/null +++ b/resources/cinema/index.html @@ -0,0 +1,43 @@ +{{extend defaultLayout}} + +{{block 'css'}} + +{{/block}} + +{{block 'main'}} +
+
+ Avatar +
+
+
+
{{charData.PartnerInfo.Name}}
+
{{charData.PartnerInfo.FullName}}
+
+
+
{{@charData.PartnerInfo.ImpressionF}}
+
{{@charData.PartnerInfo.ImpressionM}}
+
+
+
+
+
+

意象影画

+

CINEMA

+
+ +
+ {{each charData.Talent talent}} +
+

{{talent.Level}}. {{talent.Name}}

+
+ {{@talent.description}} +
+
+ {{/each}} +
+
+ 角色插图 +
+
数据来源于Hakush
+ {{/block}} \ No newline at end of file diff --git a/resources/cinema/index.scss b/resources/cinema/index.scss new file mode 100644 index 0000000..8f78746 --- /dev/null +++ b/resources/cinema/index.scss @@ -0,0 +1,95 @@ +.char-info { + display: flex; + align-items: flex-start; + padding: 1em; + gap: 1em; + .avatar { + width: 5em; + aspect-ratio: 1; + flex-grow: 0; + flex-shrink: 0; + background-color: white; + border-radius: 50%; + overflow: hidden; + img { + width: 100%; + height: 100%; + object-fit: cover; + } + } + .info { + display: flex; + flex-direction: column; + gap: 0.5em; + .name { + display: flex; + align-items: flex-end; + gap: 0.5em; + .simple { + font-size: 1.5em; + } + } + .description { + font-size: 0.8em; + } + } +} + +.cinema { + padding: 1em; + + .header { + margin-bottom: 1rem; + } + + .title { + color: white; + font-size: 2rem; + margin: 0; + } + + .subtitle { + color: #6666ff; + font-size: 1.5rem; + margin: 0; + } + + .content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + } + + .section { + margin-bottom: 1rem; + } + + .section-title { + font-size: 1.5rem; + margin-bottom: 0.5rem; + } + + .section-content { + font-size: 1.3rem; + line-height: 1.5; + } + + .highlight { + color: #ffd700; + } + + .skill-tag { + display: inline-block; + margin-right: 0.5rem; + } + + .image-container { + text-align: center; + margin-top: 1rem; + } + + .character-image { + max-width: 100%; + border-radius: 0.5rem; + } +} diff --git a/resources/common/style/index.css b/resources/common/style/index.css index 91289e3..8196d14 100644 --- a/resources/common/style/index.css +++ b/resources/common/style/index.css @@ -5,14 +5,10 @@ @font-face { font-family: "tttgbnumber"; src: url("../../../../../genshin/resources/font/tttgbnumber.ttf"); - font-weight: normal; - font-style: normal; } @font-face { font-family: "HYWenHei-55W"; src: url("../../../../../genshin/resources/font/HYWenHei-55W.ttf"); - font-weight: normal; - font-style: normal; } .zzz-font { font-family: "zzz", "tttgbnumber", "HYWenHei-55W", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; @@ -21,6 +17,10 @@ .no-zzz-font { font-family: "tttgbnumber", "HYWenHei-55W", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; } +.no-zzz-font strong, +.no-zzz-font b { + font-family: "zzz", "tttgbnumber", "HYWenHei-55W", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; +} .rank-icon { aspect-ratio: 1; diff --git a/resources/common/style/index.scss b/resources/common/style/index.scss index 0c23fe1..28c3e52 100644 --- a/resources/common/style/index.scss +++ b/resources/common/style/index.scss @@ -8,15 +8,11 @@ @font-face { font-family: 'tttgbnumber'; src: url('../../../../../genshin/resources/font/tttgbnumber.ttf'); - font-weight: normal; - font-style: normal; } @font-face { font-family: 'HYWenHei-55W'; src: url('../../../../../genshin/resources/font/HYWenHei-55W.ttf'); - font-weight: normal; - font-style: normal; } .zzz-font { @@ -29,6 +25,12 @@ font-family: 'tttgbnumber', 'HYWenHei-55W', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + strong, + b { + font-family: 'zzz', 'tttgbnumber', 'HYWenHei-55W', system-ui, -apple-system, + BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, + 'Open Sans', 'Helvetica Neue', sans-serif; + } } .rank-icon {