1
This commit was merged in pull request #1.
This commit is contained in:
@@ -11,12 +11,13 @@ import {
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import type { IJade } from "@/api/info/type";
|
||||
import ResultPanel from "@/pages/Dcalc/Character/Result/Index.vue";
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const infoStore = useInfoStore();
|
||||
|
||||
const moduleMode = ref<"equip" | "oath" | "avatar" | "global">("equip");
|
||||
const moduleMode = ref<"equip" | "oath" | "avatar" | "jade" | "sundry" | "global">("equip");
|
||||
const forgeViewTab = ref<"config" | "result">("result");
|
||||
const notice = ref("");
|
||||
const noticeType = ref<"error" | "info">("info");
|
||||
@@ -27,6 +28,8 @@ const avatarOptionKeyword = ref("");
|
||||
const emblemOptionKeyword = ref("");
|
||||
const onlyConfiguredAvatarParts = ref(false);
|
||||
const onlyConfiguredEmblemSlots = ref(false);
|
||||
const equipBatchApply = ref(false);
|
||||
const oathBatchApply = ref(false);
|
||||
|
||||
const noEnchantAvatarParts = ["头部", "帽子", "脸部", "胸部", "上衣", "腰带", "下装", "鞋"];
|
||||
|
||||
@@ -49,6 +52,19 @@ const emblemLevels = [
|
||||
"史诗Lv.1",
|
||||
];
|
||||
|
||||
const jadeKeys = ["0", "1", "2", "3"] as const;
|
||||
const sundryFields = [
|
||||
{ key: "fog", label: "迷雾系统", defaultValue: 10 },
|
||||
{ key: "adventure", label: "冒险团", defaultValue: 30 },
|
||||
{ key: "marriage_house", label: "结婚房屋", defaultValue: 4 },
|
||||
{ key: "marriage_ring", label: "结婚戒指", defaultValue: 2 },
|
||||
{ key: "contract", label: "晶体契约", defaultValue: 1 },
|
||||
{ key: "collection_type", label: "收集箱类型", defaultValue: 1 },
|
||||
{ key: "collection_num_0", label: "收集箱数量一", defaultValue: 5 },
|
||||
{ key: "collection_num_1", label: "收集箱数量二", defaultValue: 5 },
|
||||
{ key: "costume_card", label: "名称装扮", defaultValue: 1 },
|
||||
] as const;
|
||||
|
||||
const setNotice = (message: string, type: "error" | "info" = "info") => {
|
||||
notice.value = message;
|
||||
noticeType.value = type;
|
||||
@@ -71,12 +87,21 @@ const summary = computed(() => {
|
||||
const emblemCount = Object.values(configStore.config.emblems || {}).reduce((acc, item) => {
|
||||
return acc + (item.items?.filter(Boolean).length ?? 0);
|
||||
}, 0);
|
||||
const jadeCount = Object.values(configStore.config.jades || {}).filter(
|
||||
(item) => Number(item.id) >= 0,
|
||||
).length;
|
||||
const sundryCount = sundryFields.filter((item) => {
|
||||
const value = configStore.config.sundry?.[item.key] ?? item.defaultValue;
|
||||
return value !== 0 && value !== "" && value !== undefined;
|
||||
}).length;
|
||||
|
||||
return {
|
||||
equipCount,
|
||||
avatarCount,
|
||||
oathCount,
|
||||
emblemCount,
|
||||
jadeCount,
|
||||
sundryCount,
|
||||
emblemSlots: infoStore.emblemParts.length,
|
||||
};
|
||||
});
|
||||
@@ -182,9 +207,127 @@ const emblemMaxCount = computed(() => {
|
||||
return 4;
|
||||
});
|
||||
|
||||
const setNumberField = (
|
||||
const setOathAdaptation = (part: string, value: string) => {
|
||||
const target = configStore.config.oaths[part];
|
||||
if (!target) return;
|
||||
|
||||
const parsed = Number.parseInt(value || "0", 10);
|
||||
if (Number.isNaN(parsed)) {
|
||||
setNotice(`誓约槽位 ${part} 的输入无效,请输入数字。`, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const partsToApply = oathBatchApply.value ? infoStore.oathParts : [part];
|
||||
partsToApply.forEach((item) => {
|
||||
if (!configStore.config.oaths[item]) {
|
||||
configStore.config.oaths[item] = { ...configStore.defaultOathConfig };
|
||||
}
|
||||
configStore.config.oaths[item].adaptation = Math.max(0, parsed);
|
||||
});
|
||||
|
||||
setNotice(oathBatchApply.value ? "已批量更新全部誓约槽位适配值。" : `已更新誓约槽位 ${part} 的适配值。`);
|
||||
trackSource(oathBatchApply.value ? "誓约适配已批量更新" : `誓约槽位 ${part} 适配已更新`);
|
||||
};
|
||||
|
||||
const equipCfg = (part: string) => configStore.config.equips[part] ?? configStore.defaultEqusConfig;
|
||||
const oathCfg = (part: string) => configStore.config.oaths[part] ?? configStore.defaultOathConfig;
|
||||
const avatarCfg = (part: string) =>
|
||||
configStore.config.avatar[part] ?? configStore.defaultAvatarConfig;
|
||||
const canUpgradeEquip = (part: string) => !["称号", "宠物"].includes(part);
|
||||
const canSetSecret = (part: string) => ["武器", "辅助装备", "魔法石", "耳环"].includes(part);
|
||||
const equipEnchantOptions = (part: string) =>
|
||||
infoStore.enchants
|
||||
.filter(
|
||||
(item) =>
|
||||
item.position.includes(part) &&
|
||||
!item.position.includes("武器装扮") &&
|
||||
!item.position.includes("宠物装备"),
|
||||
)
|
||||
.sort((a, b) => (b.fame ?? 0) - (a.fame ?? 0));
|
||||
const formatFloat = (value: number, digits = 1) => Number(value.toFixed(digits)).toString();
|
||||
|
||||
const ensureJade = (key: string) => {
|
||||
if (!configStore.config.jades[key]) {
|
||||
configStore.config.jades[key] = { id: -1, value: 0 };
|
||||
}
|
||||
return configStore.config.jades[key];
|
||||
};
|
||||
|
||||
const jadeValueOptions = (id: number) => {
|
||||
if (id < 0) return [];
|
||||
const current = infoStore.jades.find((item) => item.id === id) as IJade | undefined;
|
||||
if (!current) return [];
|
||||
|
||||
const result: { id: number; value: string }[] = [];
|
||||
const max = Number(current.max);
|
||||
const min = Number(current.min);
|
||||
const step = Number(current.pre);
|
||||
|
||||
if (current.unit.includes("等级")) {
|
||||
result.push({ id: 1, value: current.unit });
|
||||
} else if (step > 0) {
|
||||
for (let value = max; value >= min; value = Number((value - step).toFixed(1))) {
|
||||
if (value !== 0) {
|
||||
result.push({
|
||||
id: value,
|
||||
value: `${value > 0 ? "+" : ""}${formatFloat(value, 1)}${current.unit}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const setJadeId = (key: string, value: string) => {
|
||||
const target = ensureJade(key);
|
||||
const id = Number.parseInt(value, 10);
|
||||
target.id = Number.isNaN(id) ? -1 : id;
|
||||
target.value = jadeValueOptions(target.id)[0]?.id ?? 0;
|
||||
setNotice(`已更新辟邪玉槽位 ${Number(key) + 1}。`);
|
||||
trackSource(`辟邪玉槽位 ${Number(key) + 1} 已更新`);
|
||||
};
|
||||
|
||||
const setJadeValue = (key: string, value: string) => {
|
||||
const target = ensureJade(key);
|
||||
const parsed = Number(value);
|
||||
target.value = Number.isNaN(parsed) ? 0 : parsed;
|
||||
setNotice(`已更新辟邪玉槽位 ${Number(key) + 1} 数值。`);
|
||||
trackSource(`辟邪玉槽位 ${Number(key) + 1} 数值已更新`);
|
||||
};
|
||||
|
||||
const resetJades = () => {
|
||||
jadeKeys.forEach((key) => {
|
||||
configStore.config.jades[key] = { id: -1, value: 0 };
|
||||
});
|
||||
setNotice("已重置辟邪玉配置。");
|
||||
trackSource("辟邪玉配置已重置");
|
||||
};
|
||||
|
||||
const sundryOptions = (key: string) => infoStore.sundries[key]?.options ?? [];
|
||||
|
||||
const sundryValue = (key: string, defaultValue: number) => {
|
||||
return String(configStore.config.sundry?.[key] ?? defaultValue);
|
||||
};
|
||||
|
||||
const setSundryValue = (key: string, value: string) => {
|
||||
const parsed = Number(value);
|
||||
configStore.config.sundry[key] = Number.isNaN(parsed) ? value : parsed;
|
||||
setNotice("已更新其它系统配置。");
|
||||
trackSource(`其它系统 ${key} 已更新`);
|
||||
};
|
||||
|
||||
const resetSundry = () => {
|
||||
sundryFields.forEach((field) => {
|
||||
configStore.config.sundry[field.key] = field.defaultValue;
|
||||
});
|
||||
setNotice("已重置其它系统配置。");
|
||||
trackSource("其它系统配置已重置");
|
||||
};
|
||||
|
||||
const setEquipNumberField = (
|
||||
part: string,
|
||||
field: "reinforce" | "refine" | "adaptation",
|
||||
field: "reinforce" | "reinforceType" | "refine" | "adaptation" | "precision",
|
||||
value: string,
|
||||
) => {
|
||||
const target = configStore.config.equips[part];
|
||||
@@ -196,29 +339,45 @@ const setNumberField = (
|
||||
return;
|
||||
}
|
||||
|
||||
target[field] = Math.max(0, parsed);
|
||||
setNotice(`已更新 ${part} 的打造参数。`);
|
||||
const normalized =
|
||||
field === "precision" ? Math.max(0, Math.min(parsed, 100)) : Math.max(0, parsed);
|
||||
const canBatch = equipBatchApply.value && ["reinforceType", "reinforce", "adaptation"].includes(field);
|
||||
const partsToApply = canBatch ? infoStore.parts.filter(canUpgradeEquip) : [part];
|
||||
|
||||
partsToApply.forEach((item) => {
|
||||
if (!configStore.config.equips[item]) {
|
||||
configStore.config.equips[item] = { ...configStore.defaultEqusConfig };
|
||||
}
|
||||
configStore.config.equips[item][field] = normalized;
|
||||
});
|
||||
|
||||
setNotice(canBatch ? "已批量更新装备打造参数。" : `已更新 ${part} 的打造参数。`);
|
||||
trackSource(canBatch ? `装备 ${field} 已批量更新` : `装备 ${part} ${field} 已更新`);
|
||||
};
|
||||
|
||||
const setOathAdaptation = (part: string, value: string) => {
|
||||
const target = configStore.config.oaths[part];
|
||||
const setEquipEnchant = (part: string, value: string) => {
|
||||
const target = configStore.config.equips[part];
|
||||
if (!target) return;
|
||||
|
||||
const parsed = Number.parseInt(value || "0", 10);
|
||||
if (Number.isNaN(parsed)) {
|
||||
setNotice(`誓约槽位 ${part} 的输入无效,请输入数字。`, "error");
|
||||
return;
|
||||
}
|
||||
const enchant = infoStore.enchants.find((item) => String(item.id) === value);
|
||||
const partsToApply =
|
||||
equipBatchApply.value && enchant?.position.length
|
||||
? enchant.position.filter((item) => configStore.config.equips[item])
|
||||
: [part];
|
||||
|
||||
target.adaptation = Math.max(0, parsed);
|
||||
setNotice(`已更新誓约槽位 ${part} 的适配值。`);
|
||||
partsToApply.forEach((item) => {
|
||||
if (!configStore.config.equips[item]) {
|
||||
configStore.config.equips[item] = { ...configStore.defaultEqusConfig };
|
||||
}
|
||||
configStore.config.equips[item].enchant = value;
|
||||
});
|
||||
|
||||
setNotice(equipBatchApply.value && partsToApply.length > 1 ? "已批量更新装备附魔。" : `已更新 ${part} 的附魔。`);
|
||||
trackSource(
|
||||
equipBatchApply.value && partsToApply.length > 1 ? "装备附魔已批量更新" : `装备 ${part} 附魔已更新`,
|
||||
);
|
||||
};
|
||||
|
||||
const equipCfg = (part: string) => configStore.config.equips[part] ?? configStore.defaultEqusConfig;
|
||||
const oathCfg = (part: string) => configStore.config.oaths[part] ?? configStore.defaultOathConfig;
|
||||
const avatarCfg = (part: string) =>
|
||||
configStore.config.avatar[part] ?? configStore.defaultAvatarConfig;
|
||||
|
||||
const ensureAvatarPart = (part: string) => {
|
||||
if (!configStore.config.avatar[part]) {
|
||||
configStore.config.avatar[part] = { ...configStore.defaultAvatarConfig };
|
||||
@@ -339,6 +498,12 @@ const resetAllForge = () => {
|
||||
infoStore.emblemParts.forEach((part) => {
|
||||
configStore.config.emblems[part] = { ...configStore.defaultEmblemConfig };
|
||||
});
|
||||
jadeKeys.forEach((key) => {
|
||||
configStore.config.jades[key] = { id: -1, value: 0 };
|
||||
});
|
||||
sundryFields.forEach((field) => {
|
||||
configStore.config.sundry[field.key] = field.defaultValue;
|
||||
});
|
||||
setNotice("已重置当前角色的打造参数。", "info");
|
||||
trackSource("当前角色 Forge 配置已快速重置");
|
||||
};
|
||||
@@ -352,7 +517,8 @@ const resetAllForge = () => {
|
||||
<span>Forge 面板</span>
|
||||
<span class="text-xs font-normal text-muted-foreground">
|
||||
装备 {{ summary.equipCount }} · 时装 {{ summary.avatarCount }} · 誓约
|
||||
{{ summary.oathCount }} · 徽章 {{ summary.emblemCount }}
|
||||
{{ summary.oathCount }} · 徽章 {{ summary.emblemCount }} · 辟邪玉
|
||||
{{ summary.jadeCount }} · 其它 {{ summary.sundryCount }}
|
||||
</span>
|
||||
</CardTitle>
|
||||
<CardDescription>Forge 进阶:子模块可编辑,统一浅色/深色模式。</CardDescription>
|
||||
@@ -400,6 +566,20 @@ const resetAllForge = () => {
|
||||
>
|
||||
时装徽章
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
:variant="moduleMode === 'jade' ? 'default' : 'ghost'"
|
||||
@click="moduleMode = 'jade'"
|
||||
>
|
||||
辟邪玉
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
:variant="moduleMode === 'sundry' ? 'default' : 'ghost'"
|
||||
@click="moduleMode = 'sundry'"
|
||||
>
|
||||
其它
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
:variant="moduleMode === 'global' ? 'default' : 'ghost'"
|
||||
@@ -433,6 +613,18 @@ const resetAllForge = () => {
|
||||
>时装、徽章、等级与条目配置。</AccordionContent
|
||||
>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="jade">
|
||||
<AccordionTrigger @click="moduleMode = 'jade'">辟邪玉</AccordionTrigger>
|
||||
<AccordionContent class="text-xs text-muted-foreground"
|
||||
>4 个辟邪玉词条与数值配置。</AccordionContent
|
||||
>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="sundry">
|
||||
<AccordionTrigger @click="moduleMode = 'sundry'">其它</AccordionTrigger>
|
||||
<AccordionContent class="text-xs text-muted-foreground"
|
||||
>迷雾、冒险团、结婚、晶体契约等系统配置。</AccordionContent
|
||||
>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="global">
|
||||
<AccordionTrigger @click="moduleMode = 'global'">全局</AccordionTrigger>
|
||||
<AccordionContent class="text-xs text-muted-foreground"
|
||||
@@ -483,40 +675,121 @@ const resetAllForge = () => {
|
||||
<CardDescription>强化、锻造、品级编辑并即时回写配置。</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-2 text-xs sm:space-y-3 sm:text-sm">
|
||||
<label
|
||||
class="flex flex-wrap items-center justify-between gap-2 rounded-md border bg-muted/30 p-2 text-muted-foreground"
|
||||
>
|
||||
<span>批量应用到同类部位</span>
|
||||
<input v-model="equipBatchApply" type="checkbox" class="size-4" />
|
||||
</label>
|
||||
<div
|
||||
v-for="part in parts"
|
||||
:key="part"
|
||||
class="grid grid-cols-1 gap-2 rounded-md border p-2 md:grid-cols-[7rem_1fr_6rem_6rem_6rem_auto] md:items-center md:p-3"
|
||||
class="space-y-3 rounded-md border p-2 md:p-3"
|
||||
>
|
||||
<div class="font-medium">{{ part }}</div>
|
||||
<div class="truncate text-muted-foreground">
|
||||
{{ equipNameById.get(equipCfg(part).id) || "未选择装备(可在装备页选择)" }}
|
||||
<div class="grid grid-cols-[5rem_minmax(0,1fr)_auto] items-center gap-2">
|
||||
<div class="font-medium">{{ part }}</div>
|
||||
<div class="truncate text-muted-foreground">
|
||||
{{ equipNameById.get(equipCfg(part).id) || "未选择装备(可在装备页选择)" }}
|
||||
</div>
|
||||
<Button size="sm" variant="ghost" @click="resetEquipPart(part)">重置</Button>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4">
|
||||
<label v-if="canUpgradeEquip(part)" class="space-y-1">
|
||||
<span class="text-muted-foreground">强化类型</span>
|
||||
<select
|
||||
class="h-8 w-full rounded-md border border-input bg-background px-2"
|
||||
:value="String(equipCfg(part).reinforceType)"
|
||||
@change="
|
||||
(event) =>
|
||||
setEquipNumberField(
|
||||
part,
|
||||
'reinforceType',
|
||||
(event.target as HTMLSelectElement).value,
|
||||
)
|
||||
"
|
||||
>
|
||||
<option value="0">强化</option>
|
||||
<option value="1">增幅</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label v-if="canUpgradeEquip(part)" class="space-y-1">
|
||||
<span class="text-muted-foreground">强化/增幅</span>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).reinforce)"
|
||||
type="number"
|
||||
min="0"
|
||||
max="30"
|
||||
class="h-8 text-xs"
|
||||
@update:model-value="
|
||||
(value) => setEquipNumberField(part, 'reinforce', String(value))
|
||||
"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="space-y-1">
|
||||
<span class="text-muted-foreground">锻造</span>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).refine)"
|
||||
type="number"
|
||||
min="0"
|
||||
max="8"
|
||||
class="h-8 text-xs"
|
||||
@update:model-value="
|
||||
(value) => setEquipNumberField(part, 'refine', String(value))
|
||||
"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label v-if="canUpgradeEquip(part)" class="space-y-1">
|
||||
<span class="text-muted-foreground">调适</span>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).adaptation)"
|
||||
type="number"
|
||||
min="0"
|
||||
max="3"
|
||||
class="h-8 text-xs"
|
||||
@update:model-value="
|
||||
(value) => setEquipNumberField(part, 'adaptation', String(value))
|
||||
"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label v-if="equipEnchantOptions(part).length" class="space-y-1 sm:col-span-2">
|
||||
<span class="text-muted-foreground">附魔</span>
|
||||
<select
|
||||
class="h-8 w-full min-w-0 rounded-md border border-input bg-background px-2"
|
||||
:value="equipCfg(part).enchant"
|
||||
@change="
|
||||
(event) => setEquipEnchant(part, (event.target as HTMLSelectElement).value)
|
||||
"
|
||||
>
|
||||
<option value="">无</option>
|
||||
<option
|
||||
v-for="item in equipEnchantOptions(part)"
|
||||
:key="item.id"
|
||||
:value="String(item.id)"
|
||||
>
|
||||
{{ item.detail }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label v-if="canSetSecret(part)" class="space-y-1">
|
||||
<span class="text-muted-foreground">秘宝精度</span>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).precision)"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
class="h-8 text-xs"
|
||||
@update:model-value="
|
||||
(value) => setEquipNumberField(part, 'precision', String(value))
|
||||
"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).reinforce)"
|
||||
type="number"
|
||||
min="0"
|
||||
class="h-8 text-xs"
|
||||
placeholder="强化"
|
||||
@update:model-value="(value) => setNumberField(part, 'reinforce', String(value))"
|
||||
/>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).refine)"
|
||||
type="number"
|
||||
min="0"
|
||||
class="h-8 text-xs"
|
||||
placeholder="锻造"
|
||||
@update:model-value="(value) => setNumberField(part, 'refine', String(value))"
|
||||
/>
|
||||
<Input
|
||||
:model-value="String(equipCfg(part).adaptation)"
|
||||
type="number"
|
||||
min="0"
|
||||
class="h-8 text-xs"
|
||||
placeholder="品级"
|
||||
@update:model-value="(value) => setNumberField(part, 'adaptation', String(value))"
|
||||
/>
|
||||
<Button size="sm" variant="ghost" @click="resetEquipPart(part)">重置</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -532,6 +805,12 @@ const resetAllForge = () => {
|
||||
<CardDescription>编辑誓约槽位适配值。</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-2 text-xs sm:space-y-3 sm:text-sm">
|
||||
<label
|
||||
class="flex flex-wrap items-center justify-between gap-2 rounded-md border bg-muted/30 p-2 text-muted-foreground"
|
||||
>
|
||||
<span>批量应用到全部誓约槽位</span>
|
||||
<input v-model="oathBatchApply" type="checkbox" class="size-4" />
|
||||
</label>
|
||||
<div
|
||||
v-for="part in oathParts"
|
||||
:key="part"
|
||||
@@ -779,6 +1058,104 @@ const resetAllForge = () => {
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="forgeViewTab === 'config' && moduleMode === 'jade'"
|
||||
class="grid grid-cols-1 gap-4"
|
||||
>
|
||||
<Card class="border-border/60 bg-card/90">
|
||||
<CardHeader>
|
||||
<CardTitle class="flex items-center gap-2">
|
||||
<Sparkles class="size-4" />
|
||||
辟邪玉
|
||||
</CardTitle>
|
||||
<CardDescription>从旧版 Forge 迁移的 4 个辟邪玉词条与数值配置。</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-2 text-xs sm:space-y-3 sm:text-sm">
|
||||
<div
|
||||
v-for="key in jadeKeys"
|
||||
:key="key"
|
||||
class="grid grid-cols-1 gap-2 rounded-md border p-2 md:grid-cols-[6rem_1fr_12rem] md:items-center md:p-3"
|
||||
>
|
||||
<div class="font-medium">槽位 {{ Number(key) + 1 }}</div>
|
||||
<select
|
||||
class="h-8 min-w-0 rounded-md border border-input bg-background px-2"
|
||||
:value="String(ensureJade(key).id)"
|
||||
@change="(event) => setJadeId(key, (event.target as HTMLSelectElement).value)"
|
||||
>
|
||||
<option value="-1">无</option>
|
||||
<option v-for="item in infoStore.jades" :key="item.id" :value="String(item.id)">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
</select>
|
||||
<select
|
||||
class="h-8 min-w-0 rounded-md border border-input bg-background px-2"
|
||||
:value="String(ensureJade(key).value)"
|
||||
:disabled="ensureJade(key).id < 0"
|
||||
@change="(event) => setJadeValue(key, (event.target as HTMLSelectElement).value)"
|
||||
>
|
||||
<option value="0">无</option>
|
||||
<option
|
||||
v-for="item in jadeValueOptions(ensureJade(key).id)"
|
||||
:key="item.id"
|
||||
:value="String(item.id)"
|
||||
>
|
||||
{{ item.value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<Button size="sm" variant="outline" @click="resetJades">重置辟邪玉</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="forgeViewTab === 'config' && moduleMode === 'sundry'"
|
||||
class="grid grid-cols-1 gap-4"
|
||||
>
|
||||
<Card class="border-border/60 bg-card/90">
|
||||
<CardHeader>
|
||||
<CardTitle class="flex items-center gap-2">
|
||||
<ShieldCheck class="size-4" />
|
||||
其它系统
|
||||
</CardTitle>
|
||||
<CardDescription>迷雾、冒险团、结婚系统、晶体契约、收集箱等配置。</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-2 text-xs sm:space-y-3 sm:text-sm">
|
||||
<div class="grid grid-cols-1 gap-2 md:grid-cols-2 xl:grid-cols-3">
|
||||
<div
|
||||
v-for="field in sundryFields"
|
||||
:key="field.key"
|
||||
class="grid grid-cols-1 gap-2 rounded-md border p-2 sm:grid-cols-[6rem_1fr] sm:items-center sm:p-3"
|
||||
>
|
||||
<div class="font-medium">{{ field.label }}</div>
|
||||
<select
|
||||
class="h-8 min-w-0 rounded-md border border-input bg-background px-2"
|
||||
:value="sundryValue(field.key, field.defaultValue)"
|
||||
@change="
|
||||
(event) => setSundryValue(field.key, (event.target as HTMLSelectElement).value)
|
||||
"
|
||||
>
|
||||
<option
|
||||
v-for="item in sundryOptions(field.key)"
|
||||
:key="`${field.key}-${item.value}`"
|
||||
:value="String(item.value)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<Button size="sm" variant="outline" @click="resetSundry">重置其它系统</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="forgeViewTab === 'config' && moduleMode === 'global'"
|
||||
class="grid grid-cols-1 gap-4 lg:grid-cols-2"
|
||||
@@ -815,6 +1192,8 @@ const resetAllForge = () => {
|
||||
<div>誓约槽位: {{ summary.oathCount }}</div>
|
||||
<div>已配置时装: {{ summary.avatarCount }}</div>
|
||||
<div>已配置徽章条目: {{ summary.emblemCount }}</div>
|
||||
<div>已配置辟邪玉: {{ summary.jadeCount }}</div>
|
||||
<div>其它系统项目: {{ summary.sundryCount }}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user