From b0db3bb352fb39df2cea9bc4548aa9e6bc81a512 Mon Sep 17 00:00:00 2001 From: sharpobject Date: Sun, 8 Mar 2026 13:39:44 +0900 Subject: [PATCH 1/3] feat: add dream card support Dream cards use string IDs with a "D" prefix (e.g. "D11011"). Changes: - SortableCard: Fix image path to use String(card_id).slice(0,-1)+level instead of arithmetic (which produced NaN for D-prefix IDs). Show 5 stars for dream cards instead of 3. Add level clamping with does_not_exist check when switching cards. - Simulator buildTree: Add branch for D-prefix IDs that routes them to a "Fate Branches" category in the TreeSelect. - App.css: Add aspect-ratio on card images for consistent heights. --- src/App.css | 6 ++++ src/Simulator.jsx | 15 ++++++++- src/components/SortableCard.jsx | 59 ++++++++++++++++----------------- 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/App.css b/src/App.css index 35f077ac..d486bbd4 100644 --- a/src/App.css +++ b/src/App.css @@ -13,6 +13,12 @@ cursor: pointer; } +.card img { + width: 100%; + aspect-ratio: 425 / 685; + object-fit: contain; +} + .cardname, .cardlevel { margin-inline-end: 0 !important; diff --git a/src/Simulator.jsx b/src/Simulator.jsx index 84ae367d..fc10bf9f 100644 --- a/src/Simulator.jsx +++ b/src/Simulator.jsx @@ -61,10 +61,23 @@ function buildTree(items, l) { const tree = []; for (const item of items) { + const sid = String(item.id); + + // Dream cards: D-prefix → add under "Dream" category + if (sid.startsWith('D')) { + let dreamNode = tree.find(n => n.idPart === 'dream'); + if (!dreamNode) { + dreamNode = { idPart: 'dream', value: 'dream', title: l('Fate Branches'), disabled: true, children: [] }; + tree.push(dreamNode); + } + dreamNode.children.push({ value: item.id, title: l(item.name) }); + continue; + } + const ID_RE = /^(\d)(\d)(\d)(\d{2})(\d)$/; // 1. Extract levels - const s = String(item.id).padStart(6, "0"); + const s = sid.padStart(6, "0"); const m = s.match(ID_RE); if (!m) continue; const [, lv1, lv2, lv3] = m; diff --git a/src/components/SortableCard.jsx b/src/components/SortableCard.jsx index 1ff27dae..4f848fc9 100644 --- a/src/components/SortableCard.jsx +++ b/src/components/SortableCard.jsx @@ -1,9 +1,6 @@ // src/components/SortableCard.jsx import React from "react"; import { - UserOutlined, - QuestionOutlined, - PlayCircleOutlined, ClearOutlined, } from "@ant-design/icons"; import { useSortable } from "@dnd-kit/sortable"; @@ -34,8 +31,6 @@ export default function SortableCard({ // 将 transform 对象转换为行内样式字符串 const style = { transform: CSS.Transform.toString(transform), - // transition, - // 当正在拖拽时可以微调样式,比如将透明度降低 opacity: isDragging ? 0.5 : 1, height: "100%", display: "flex", @@ -46,9 +41,10 @@ export default function SortableCard({ // 从 Form 中获取当前的 cards 数组,找到第 index 个卡片 const cards = Form.useWatch([roleField, "cards"]) || []; const card = cards[index] || {}; + const isDream = String(card.card_id).startsWith('D'); const src = card.card_id - ? `yxp_images/${l.lang === "en" ? "en" : "zh"}/${card.card_id + card.level - 1}.png` - : `yxp_images/${l.lang === "en" ? "en" : "zh"}/Deviation Syndrome1.png`; + ? `yxp_images/${l.lang === "en" ? "en" : "zh"}/${String(card.card_id).slice(0, -1) + card.level}.png` + : null; return (
@@ -72,6 +68,18 @@ export default function SortableCard({ )} +
+ { + form.setFieldValue([roleField, "cards", field.name, "level"], newLevel); + }} + /> +
+ { - const level = form.getFieldValue([ - roleField, - "cards", - field.name, - "level", - ]); - if (swogi[String(e - 1 + level)].does_not_exist) { - form.setFieldValue([roleField, "cards", field.name], { - card_id: e, - level: swogi[String(e)].does_not_exist - ? swogi[String(e + 1)].does_not_exist - ? swogi[String(e + 2)].does_not_exist - ? 0 - : 3 - : 2 - : 1, - }); + onChange={(newCardId) => { + let lvl = card.level || 1; + const newIsDream = String(newCardId).startsWith('D'); + const oldIsDream = String(card.card_id).startsWith('D'); + if (newIsDream && !oldIsDream) { + lvl = 5; + } else { + const base = String(newCardId).slice(0, -1); + while (lvl > 1 && (!swogi[base + lvl] || swogi[base + lvl].does_not_exist)) lvl--; + while (lvl < 5 && (!swogi[base + lvl] || swogi[base + lvl].does_not_exist)) lvl++; } + form.setFieldValue([roleField, "cards", field.name], { + card_id: newCardId, + level: lvl, + }); }} /> - - {/* 等级评分 */} - - -
); } From fd261e8f5c6d4a3850237b0aa46683b674cea397 Mon Sep 17 00:00:00 2001 From: sharpobject Date: Sun, 8 Mar 2026 14:20:40 +0900 Subject: [PATCH 2/3] update yxp_images submodule to include dream card images --- public/yxp_images | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/yxp_images b/public/yxp_images index 5bbc06ae..efebff3e 160000 --- a/public/yxp_images +++ b/public/yxp_images @@ -1 +1 @@ -Subproject commit 5bbc06ae6f97bb8624a58e4a5df51f3adcef85f6 +Subproject commit efebff3e7ac72e0fc8da77cf37a498d0a7b36b4d From 3d1cf5f537bf4f438a400b0bbcc09bf5e4dcdf6f Mon Sep 17 00:00:00 2001 From: sharpobject Date: Sun, 8 Mar 2026 14:56:43 +0900 Subject: [PATCH 3/3] fix: dark mode dropdown text, character/side job search, unsupported card levels - Force tree select dropdown text to white in dark mode via CSS - Add optionFilterProp="label" to Character and Side job selects so search filters by name instead of numeric ID - Ignore clicks on card star levels that don't exist in swogi --- src/App.css | 6 ++++++ src/Simulator.jsx | 2 ++ src/components/SortableCard.jsx | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/App.css b/src/App.css index d486bbd4..ecd203e5 100644 --- a/src/App.css +++ b/src/App.css @@ -70,3 +70,9 @@ .ant-input-number { width: 60px; } + +.ant-tree-select-dropdown .ant-select-tree-node-content-wrapper, +.ant-tree-select-dropdown .ant-select-tree-node-content-wrapper * { + color: rgba(255, 255, 255, 0.85) !important; + -webkit-text-fill-color: rgba(255, 255, 255, 0.85) !important; +} diff --git a/src/Simulator.jsx b/src/Simulator.jsx index fc10bf9f..e760a777 100644 --- a/src/Simulator.jsx +++ b/src/Simulator.jsx @@ -445,6 +445,7 @@ const Simulator = ({ l, form, setResult, setIsModalOpen, messageApi }) => { ({ value: key, diff --git a/src/components/SortableCard.jsx b/src/components/SortableCard.jsx index 4f848fc9..76622ee1 100644 --- a/src/components/SortableCard.jsx +++ b/src/components/SortableCard.jsx @@ -75,6 +75,10 @@ export default function SortableCard({ allowClear={false} value={card.level} onChange={(newLevel) => { + if (!card.card_id) return; + const base = String(card.card_id).slice(0, -1); + const entry = swogi[base + newLevel]; + if (!entry || entry.does_not_exist) return; form.setFieldValue([roleField, "cards", field.name, "level"], newLevel); }} />