From 08df765d2518913dfc7fa2fe6375faba296585eb Mon Sep 17 00:00:00 2001 From: AzenKain Date: Sun, 4 May 2025 19:26:14 +0700 Subject: [PATCH] fix ja language, instead fetch by axios --- bun.lock | 19 +++++ messages/cn.json | 108 ++++++++++++++++++++++++++ next.config.ts | 9 +-- package.json | 1 + src/components/actionbar/index.tsx | 22 ++++-- src/components/card/characterCard.tsx | 78 ++++++++----------- src/components/header/index.tsx | 2 +- src/components/lineupbar/index.tsx | 25 ++++-- src/components/nameAvatar/index.tsx | 16 ++++ src/helper/getNameChar.ts | 14 +++- src/lib/api.ts | 33 ++++---- tsconfig.json | 27 +++++-- 12 files changed, 263 insertions(+), 91 deletions(-) create mode 100644 messages/cn.json create mode 100644 src/components/nameAvatar/index.tsx diff --git a/bun.lock b/bun.lock index e138474..6ef5ba8 100644 --- a/bun.lock +++ b/bun.lock @@ -4,6 +4,7 @@ "": { "name": "firefly-analytics", "dependencies": { + "axios": "^1.9.0", "chart.js": "^4.4.9", "chartjs-plugin-datalabels": "^2.2.0", "framer-motion": "^12.7.4", @@ -316,10 +317,14 @@ "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], "axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="], + "axios": ["axios@1.9.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg=="], + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -360,6 +365,8 @@ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -386,6 +393,8 @@ "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], "diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="], @@ -476,8 +485,12 @@ "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + "form-data": ["form-data@4.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="], + "framer-motion": ["framer-motion@12.9.4", "", { "dependencies": { "motion-dom": "^12.9.4", "motion-utils": "^12.9.4", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-yaeGDmGQ3eCQEwZ95/pRQMaSh/Q4E2CK6JYOclG/PdjyQad0MULJ+JFVV8911Fl5a6tF6o0wgW8Dpl5Qx4Adjg=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], @@ -658,6 +671,10 @@ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], @@ -728,6 +745,8 @@ "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], diff --git a/messages/cn.json b/messages/cn.json new file mode 100644 index 0000000..9d41bd8 --- /dev/null +++ b/messages/cn.json @@ -0,0 +1,108 @@ +{ + "TabTitle": { + "title": "Firefly 分析器", + "description": "Veritas 分析工具" + }, + "DataAnalysisPage": { + "useSkill": "使用技能", + "totalDamage": "总伤害", + "damagePerAV": "每行动值伤害", + "totalAV": "总行动值", + "skillType": "技能类型", + "skillName": "技能名称", + "actionValue": "行动值", + "character": "角色", + "id": "ID", + "path": "命途", + "rarity": "稀有度", + "damageByActionValue": "此行动值的伤害", + "element": "属性", + "totalTurn": "总回合", + "technique": "密技", + "talent": "天赋", + "basic": "普攻", + "skill": "战技", + "ultimate": "终结技", + "servant": "忆灵", + "skillDamageBreakdown": "技能类别", + "skillUsageDistribution": "技能使用分布", + "damageOverTime": "累计伤害", + "damage": "伤害", + "cumulativeDamage": "累计伤害量", + "characterInformation": "角色信息", + "turnDetail": "轮次详情", + "damageDetails": "伤害详情", + "cycleCount": "轮次", + "chartInfo": "图表信息", + "actionBar": "行动轴", + "lineupInfo": "阵容信息", + "loadData": "加载战斗数据", + "exportData": "导出战斗数据", + "connectSetting": "连接设置", + "connected": "已连接", + "unconnected": "未连接", + "socketConnection": "socket连接", + "connectionType": "连接类型", + "status": "状态", + "connect": "连接", + "checkGameConnect": "检查游戏连接", + "other": "其他", + "host": "主机", + "port": "端口", + "hostPlaceHolder": "输入主机地址", + "portPlaceHolder": "输入端口号", + "noDamageDetail": "没有可用的伤害详情", + "noCharactersInLineup": "队伍中没有角色", + "noTurns": "尚未有回合", + "type": "类型 ", + "warrior": "毁灭", + "knight": "存护", + "mage": "智识", + "priest": "丰饶", + "rouge": "巡猎", + "shaman": "同协", + "warlock": "虚无", + "memory": "记忆", + "fire": "火", + "ice": "冰", + "imaginary": "虚数", + "physical": "物理", + "quantum": "量子", + "thunder": "雷", + "wind": "风", + "cycle": "回合", + "wave": "波次", + "hp": "生命值", + "atk": "攻击力", + "speed": "速度", + "critRate": "暴击率", + "critDmg": "暴击伤害", + "breakEffect": "击破特攻", + "effectRes": "效果抵抗", + "energyRegenerationRate": "能量回复效率", + "effectHitRate": "效果命中", + "outgoingHealingBoost": "治疗量加成", + "fireDmgBoost": "火属性伤害提高", + "iceDmgBoost": "冰属性伤害提高", + "imaginaryDmgBoost": "虚数属性伤害提高", + "physicalDmgBoost": "物理属性伤害提高", + "quantumDmgBoost": "量子属性伤害提高", + "thunderDmgBoost": "雷属性伤害提高", + "windDmgBoost": "风属性伤害提高", + "pursued": "附加伤害", + "true damage": "真实伤害", + "follow-up": "追加攻击", + "elemental damage": "击破与超击破伤害", + "dot": "持续伤害 ", + "damagePerCycle": "每轮伤害", + "damagePerCycleAndWave": "每轮/波伤害", + "damagePerWave": "每波伤害", + "lastTurn": "最后一回合", + "qte": "QTE技能", + "mazenormal": "普通迷宫", + "level": "等级", + "relics": "遗器", + "eidolons": "星魂", + "lightcones": "光锥" + } +} diff --git a/next.config.ts b/next.config.ts index 4fa91fb..a82fe09 100644 --- a/next.config.ts +++ b/next.config.ts @@ -29,14 +29,7 @@ const nextConfig: NextConfig = { eslint: { ignoreDuringBuilds: true, }, - async rewrites() { - return [ - { - source: '/api/hakushin', - destination: 'https://api.hakush.in/hsr/data/character.json', - }, - ]; - }, + }; export default withNextIntl(nextConfig); diff --git a/package.json b/package.json index 52dcfa7..4b683ba 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "axios": "^1.9.0", "chart.js": "^4.4.9", "chartjs-plugin-datalabels": "^2.2.0", "framer-motion": "^12.7.4", diff --git a/src/components/actionbar/index.tsx b/src/components/actionbar/index.tsx index 994ea02..4240307 100644 --- a/src/components/actionbar/index.tsx +++ b/src/components/actionbar/index.tsx @@ -9,6 +9,7 @@ import { useTranslations } from "next-intl"; import { motion } from "framer-motion"; import { getNameChar } from "@/helper"; import Image from "next/image"; +import NameAvatar from "../nameAvatar"; export default function ActionBar() { const [selectTurn, setSelectTurn] = useState(null); @@ -128,8 +129,11 @@ export default function ActionBar() { /> - -
{getNameChar(locale, data)}
+
@@ -180,14 +184,18 @@ export default function ActionBar() {

{transI18n("characterInformation")}

-

+

{transI18n("id")}: {selectAvatar.id} -

-

+

+
{transI18n("character")}: - {getNameChar(locale, selectAvatar)} -

+ +
{ - return `${kanji}${furigana}`; - }); -} export default function CharacterCard({ data }: CharacterCardProps) { @@ -20,47 +16,41 @@ export default function CharacterCard({ data }: CharacterCardProps) { const text = getNameChar(locale, data) return (
  • -
    - -
    - ALT - {data.damageType.toLowerCase()} - {data.baseType.toLowerCase()} -
    -
    - - {locale === "jp" ? (
    - ) : ( -
    - {text} + className={`w-[80px] rounded-md p-[2px] bg-gradient-to-br ${data.rank === "CombatPowerAvatarRarityType5" + ? "from-yellow-400 via-yellow-300 to-yellow-500" + : "from-purple-300 via-purple-200 to-purple-400" + }`} + > + +
    + ALT + {data.damageType.toLowerCase()} + {data.baseType.toLowerCase()} +
    - )} -
  • + + + ); } diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index c873d58..5719898 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -32,7 +32,7 @@ export default function Header() { useEffect(() => { - console.log(navigator.language.slice(0, 2)) + const cookieLocale = document.cookie.split("; ") .find((row) => row.startsWith("MYNEXTAPP_LOCALE")) ?.split("=")[1]; diff --git a/src/components/lineupbar/index.tsx b/src/components/lineupbar/index.tsx index de9b5b8..4b18267 100644 --- a/src/components/lineupbar/index.tsx +++ b/src/components/lineupbar/index.tsx @@ -14,10 +14,11 @@ import { DamageLineForOne } from "../chart/damageLineForOne"; import { DamagePerCycleForOne } from "../chart/damagePerCycleForOne"; import { useCalcTotalDmgAvatar, useCalcTotalTurnAvatar } from "@/hooks/useCalcAvatarData"; import Image from "next/image"; +import NameAvatar from "../nameAvatar"; // import ShowCaseInfo from "../card/showCaseCard"; export default function LineupBar() { - const [selectedCharacter, setSelectedCharacter] = useState(null); + const [selectedCharacter, setSelectedCharacter] = useState(undefined); const [isModalOpen, setIsModalOpen] = useState(false); const transI18n = useTranslations("DataAnalysisPage"); @@ -44,7 +45,7 @@ export default function LineupBar() { // Close modal handler const handleCloseModal = (modalId: string) => { setIsModalOpen(false); - setSelectedCharacter(null); + setSelectedCharacter(undefined); const modal = document.getElementById(modalId) as HTMLDialogElement | null; if (modal) { modal.close() @@ -80,7 +81,16 @@ export default function LineupBar() { - {transI18n("lastTurn")}: {getNameChar(locale, listAvatar.find(it => it.id === turnHistory.findLast(i => i?.avatarId)?.avatarId?.toString()))} + +
    + {transI18n("lastTurn")}: +
    + + it.id === turnHistory.findLast(i => i?.avatarId)?.avatarId?.toString()))} + /> +
    @@ -132,9 +142,12 @@ export default function LineupBar() {
    -

    - {selectedCharacter ? getNameChar(locale, selectedCharacter).toUpperCase() : ""} -

    + +
    {selectedCharacter && ( diff --git a/src/components/nameAvatar/index.tsx b/src/components/nameAvatar/index.tsx new file mode 100644 index 0000000..fb238c3 --- /dev/null +++ b/src/components/nameAvatar/index.tsx @@ -0,0 +1,16 @@ +import { parseRuby } from "@/helper"; + + + +interface TextProps { + text: string; + locale: string; + className?: string; +} + +export default function NameAvatar({ text, locale, className }: TextProps) { + if (locale === "ja") { + return
    ; + } + return
    {text}
    ; +} \ No newline at end of file diff --git a/src/helper/getNameChar.ts b/src/helper/getNameChar.ts index 42169f8..843038a 100644 --- a/src/helper/getNameChar.ts +++ b/src/helper/getNameChar.ts @@ -12,13 +12,19 @@ export function getNameChar(locale: string, data: AvatarHakushiType | undefined) let text = data.lang.get(listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase()) ?? ""; if (!text) { - text = data.lang.get("en") ?? ""; + text = data.lang.get("en") ?? ""; } if (Number(data.id) % 2 === 0 && Number(data.id) > 8000) { - text = `Female ${data.damageType} MC` + text = `Female ${data.damageType} MC` } else if (Number(data.id) > 8000) { - text = `Male ${data.damageType} MC` + text = `Male ${data.damageType} MC` } - return text } + +export function parseRuby(text: string): string { + const rubyRegex = /\{RUBY_B#(.*?)\}(.*?)\{RUBY_E#\}/gs; + return text.replace(rubyRegex, (_match, furigana, kanji) => { + return `${kanji}${furigana}`; + }); +} \ No newline at end of file diff --git a/src/lib/api.ts b/src/lib/api.ts index 03dc351..950a3d8 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,6 +1,6 @@ import useSocketStore from "@/stores/socketSettingStore"; import { AvatarHakushiType, AvatarHakushiRawType } from "@/types/avatar"; - +import axios from 'axios'; export async function checkConnectTcpApi(): Promise { const { host, port, connectionType } = useSocketStore.getState() @@ -23,22 +23,27 @@ export async function checkConnectTcpApi(): Promise { } export async function getCharacterListApi(): Promise { - const res = await fetch('/api/hakushin', { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }); + try { + const res = await axios.get>( + 'https://api.hakush.in/hsr/data/character.json', + { + headers: { + 'Content-Type': 'application/json', + }, + } + ); - if (!res.ok) { - console.log(`Error ${res.status}: ${res.statusText}`); + const data = new Map(Object.entries(res.data)); + + return Array.from(data.entries()).map(([id, it]) => convertAvatar(id, it)); + } catch (error: unknown) { + if (axios.isAxiosError(error)) { + console.log(`Error: ${error.response?.status} - ${error.message}`); + } else { + console.log(`Unexpected error: ${String(error)}`); + } return []; } - - const data: Map = new Map(Object.entries(await res.json())); - - - return Array.from(data.entries()).map(([id, it]) => convertAvatar(id, it)); } diff --git a/tsconfig.json b/tsconfig.json index c133409..eba91ff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,15 @@ { "compilerOptions": { - "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], + "target": "ES2018", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, - "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, @@ -19,9 +22,19 @@ } ], "paths": { - "@/*": ["./src/*"] - } + "@/*": [ + "./src/*" + ] + }, + "esModuleInterop": true }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }