Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-05 18:59:06 +08:00
co-authored by Copilot
parent 44c9df9b20
commit 01b648a3e7
52 changed files with 2491 additions and 89 deletions
+293
View File
@@ -0,0 +1,293 @@
import { defineStore } from "pinia";
import { useInfoStore } from "./info";
import api from "@/api";
import type { IEquipment } from "@/api/info/type";
import type { IResultSkillCount } from "@/api/calc/type";
// | '上衣'
// | '头肩'
// | '下装'
// | '腰带'
// | '鞋'
// | '手镯'
// | '项链'
// | '戒指'
// | '耳环'
// | '辅助装备'
// | '魔法石'
// | '武器',
export interface IConfigEquip {
id: string;
reinforce: number;
reinforceType: number;
enchant: string;
emblem_0: string;
emblem_1: string;
upgrade: number;
refine: number;
adaptation: number;
fusion: string;
precision: number;
weaponFusion: number;
}
export interface IConfigOath {
id: string;
adaptation: number;
}
export interface IConfigEmblem {
lv: number;
items: string[];
}
export interface IConfig {
skills: Record<string, { lv: number; vp: number; up: number }>;
equips: Record<string, IConfigEquip>;
oaths: Record<string, IConfigOath>;
oathSkill: string;
jades: Record<
string,
{
id: number;
value: number;
}
>;
avatar: Record<
string,
{
id: string;
enchant: string;
emblem_0: string;
emblem_1: string;
option: string;
}
>;
sundry: Record<string, unknown>;
bindAwake: number;
/** 系统奶 */
DSB: boolean;
/** 奶 */
BUFF: boolean;
options: Record<string, number>;
avatarLink: string;
emblems: Record<string, IConfigEmblem>;
}
const defaultEqusConfig = {
id: "",
reinforce: 0,
reinforceType: 0,
enchant: "",
emblem_0: "",
emblem_1: "",
upgrade: 0,
refine: 0,
adaptation: 0,
fusion: "",
precision: 0,
weaponFusion: 0,
};
const defaultAvatarConfig = {
id: "",
enchant: "",
emblem_0: "",
emblem_1: "",
option: "0",
};
const defaultOathConfig = {
id: "",
adaptation: 0,
};
const defaultEmblemConfig = {
lv: 0,
items: ["", "", "", "", "", ""],
};
export const useConfigStore = defineStore("configStore", () => {
const config = ref<IConfig>({
skills: {},
equips: {},
oaths: {},
oathSkill: "1",
jades: {},
avatar: {},
sundry: {},
bindAwake: 50,
DSB: false,
BUFF: false,
options: {},
avatarLink: "",
emblems: {},
});
const skillCountConfig = ref<IResultSkillCount[]>([]);
const loadConfig = () => {
const infoStore = useInfoStore();
const alter = infoStore.infos?.alter;
if (alter) {
const localConfig = localStorage.getItem(`dcalc/${alter}/config`);
const localSkillConfig = localStorage.getItem(`dcalc/${alter}/config/skillCount`);
if (localConfig) {
config.value = JSON.parse(localConfig);
}
if (localSkillConfig) {
skillCountConfig.value = JSON.parse(localSkillConfig);
}
}
if (!config.value) {
config.value = {
skills: {},
equips: {},
oaths: {},
oathSkill: "1",
jades: {},
avatar: {},
sundry: {},
bindAwake: 50,
DSB: false,
BUFF: false,
options: {},
avatarLink: "",
emblems: {},
};
}
if (!config.value?.equips) config.value.equips = {};
if (!config.value?.skills) config.value.skills = {};
if (!config.value?.jades) config.value.jades = {};
if (!config.value?.avatar) config.value.avatar = {};
if (!config.value?.sundry) config.value.sundry = {};
if (!config.value?.bindAwake) config.value.bindAwake = 50;
if (!config.value?.options) config.value.options = {};
if (!config.value?.oaths) config.value.oaths = {};
if (!config.value?.emblems) config.value.emblems = {};
const part = [...infoStore.parts, "宠物", "副武器"].filter(
(a) => !config.value?.equips.hasOwnProperty(a),
);
const avatarPart = infoStore.avatarParts
.filter((a) => a != "宠物")
.filter((a) => !config.value?.avatar.hasOwnProperty(a));
const skillIDs = infoStore.skills
.map((skill) => skill.id.toString())
.filter((a) => !config.value?.skills.hasOwnProperty(a));
part.forEach((p) => {
// oxlint-disable-next-line no-unused-expressions
config.value && (config.value.equips[p] = { ...defaultEqusConfig });
});
avatarPart.forEach((p) => {
// oxlint-disable-next-line no-unused-expressions
config.value && (config.value.avatar[p] = { ...defaultAvatarConfig });
});
infoStore.oathParts.forEach((p) => {
// oxlint-disable-next-line no-unused-expressions
config.value &&
!config.value?.oaths.hasOwnProperty(p) &&
(config.value.oaths[p.toString()] = { ...defaultOathConfig });
});
infoStore.options.forEach((option) => {
if (Object.keys(config.value.options).includes(option.id.toString())) return;
config.value.options[option.id.toString()] = 0;
});
skillIDs.forEach((id) => {
// oxlint-disable-next-line no-unused-expressions
config.value &&
(config.value.skills[id] = {
lv: infoStore.skills.find((skill) => skill.id.toString() === id)?.maxLearnLv ?? 0,
vp: 0,
up: 0,
});
});
(
["0", "1", "2", "3"].filter((key) => !Object.keys(config.value.jades).includes(key)) ?? []
).forEach((key) => {
config.value.jades[key] = {
id: -1,
value: 0,
};
});
};
const saveConfig = () => {
const infoStore = useInfoStore();
const alter = infoStore.infos?.alter;
if (alter) {
localStorage.setItem(`dcalc/${alter}/config`, JSON.stringify(config.value));
localStorage.setItem(
`dcalc/${alter}/config/skillCount`,
JSON.stringify(skillCountConfig.value),
);
}
};
const calc = async () => {
if (!useInfoStore().infos?.alter) return undefined;
const res = await api.calc(config.value);
if (res.suits.oath?.suitId != res.suits.suit?.suitId) {
config.value.oathSkill = "1";
}
return res;
};
const chooseEqu = (
equip: IEquipment | undefined,
isFusion: boolean = false,
isSubWeapon: boolean = false,
) => {
if (!equip) return;
const part = isSubWeapon
? "副武器"
: equip?.itemType == "武器"
? "武器"
: equip?.itemDetailType;
if (equip && config.value.equips[part]) {
const key = isFusion ? "fusion" : "id";
if (config.value.equips[part][key] == equip.id) {
config.value.equips[part][key] = "";
} else {
config.value.equips[part][key] = equip.id;
}
}
};
const result = useAsyncState(
() => {
return calc();
},
{
uuid: "",
skills: [],
info: [],
suits: {},
buffer: false,
},
{ resetOnExecute: false },
);
return {
config,
loadConfig,
saveConfig,
calc,
result,
chooseEqu,
skillCountConfig,
defaultEqusConfig,
defaultAvatarConfig,
defaultOathConfig,
defaultEmblemConfig,
};
});
-12
View File
@@ -1,12 +0,0 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
+31
View File
@@ -0,0 +1,31 @@
import { defineStore } from "pinia";
import api from "@/api";
import type { IHelperInfo } from "@/api/info/type";
export const useDnfHelperStore = defineStore("dnfHelperStore", () => {
const helperInfo = useLocalStorage<IHelperInfo | null>("dnfHelperInfo", null, {
serializer: {
read: (v) => (v ? JSON.parse(v) : null),
write: (v) => JSON.stringify(v),
},
});
const refleshHelperInfo = async (uid: string) => {
const data = await api.getHelperList(uid);
console.log("helperInfo", data);
if (data) {
helperInfo.value = data;
console.log(helperInfo.value);
}
};
const logout = () => {
helperInfo.value = null;
};
return {
helperInfo,
refleshHelperInfo,
logout,
};
});
+6
View File
@@ -0,0 +1,6 @@
import { createPinia } from 'pinia'
export * from './info'
export * from './config'
export const pinia = createPinia()
+194
View File
@@ -0,0 +1,194 @@
import api from '@/api'
import type { ICharacterInfo, IEquipment, ISuit } from '@/api/info/type'
import { defineStore } from 'pinia'
import { useConfigStore } from './config'
import type { IResult, IResultSkill, IResultSkillCount } from '@/api/calc/type'
export const useInfoStore = defineStore('infoStore', () => {
const alter_token = ref<string>('')
const infos = ref<ICharacterInfo | null>(null)
const oathCache = ref<
{
suitId: string
skillId: string
rarity: string
lv: number
data: ISuit
}[]
>([])
const skills = computed(() => infos.value?.skills ?? [])
const equips = computed(() => infos.value?.equips ?? [])
const suits = computed(() => infos.value?.suits ?? [])
const enchants = computed(() => infos.value?.enchants ?? [])
const emblems = computed(() => infos.value?.emblems ?? [])
// const stones = computed(() => infos.value?.stones ?? [])
const avatars = computed(() => infos.value?.avatar ?? {})
const jades = computed(() => infos.value?.jades ?? [])
const sundries = computed(() => infos.value?.sundry ?? {})
const options = computed(() => infos.value?.options ?? [])
const oaths = computed(() => {
const origin = infos.value?.oaths ?? []
const result: IEquipment[] = []
origin.forEach((o) => {
o.position.forEach((p, i) => {
result.push({
...o,
oathPos: p,
displayUrl: o.wearUrl?.[parseInt(p)]
? `/equipment/icon/oathprimer/primer_equip/${o.wearUrl?.[parseInt(p)]}`
: o.imageUrl,
})
})
})
return result
})
const getOathInfo = async (suitId: string, skillId: string, rarity: string, lv: number) => {
const res = oathCache.value.find(
(o) => o.suitId === suitId && o.skillId === skillId && o.rarity === rarity && o.lv === lv,
)
if (res) {
return {
...res.data,
}
}
const data: ISuit = await api.getOathInfo(suitId, skillId, rarity, lv)
oathCache.value.push({ suitId, skillId, rarity, lv, data })
return {
...data,
}
}
const oathSkills = computed(() => {
const origin = infos.value?.oaths_skills
if (!origin) return origin
const skillOrder = ['2', '1', '3']
return Object.fromEntries(
Object.entries(origin).map(([key, value]) => [
key,
{
...value,
skills: [...value.skills].sort((left, right) => {
const leftIndex = skillOrder.indexOf(left.skillId)
const rightIndex = skillOrder.indexOf(right.skillId)
const normalizedLeftIndex = leftIndex === -1 ? skillOrder.length : leftIndex
const normalizedRightIndex = rightIndex === -1 ? skillOrder.length : rightIndex
return normalizedLeftIndex - normalizedRightIndex
}),
},
]),
)
})
const standardUUID = ref<string>()
const setStandard = (
result?: IResult,
skillCount?: {
count: number
mode: string
name: string
}[],
) => {
if (!result) {
if (!!standardUUID.value) {
sessionStorage.removeItem(standardUUID.value)
}
standardUUID.value = undefined
} else {
standardUUID.value = result.uuid
sessionStorage.setItem(result.uuid, JSON.stringify({ skills: result.skills, skillCount }))
}
}
const standard = computed(() => {
const value = sessionStorage.getItem(standardUUID.value ?? '')
if (!value) return undefined
else return JSON.parse(value) as { skills: IResultSkill[]; skillCount: IResultSkillCount[] }
})
const parts = [
'头肩',
'上衣',
'下装',
'腰带',
'鞋',
'武器',
'称号',
'手镯',
'项链',
'辅助装备',
'戒指',
'耳环',
'魔法石',
'宠物',
]
const avatarParts = [
'武器装扮',
'头部',
'帽子',
'脸部',
'光环',
'胸部',
'上衣',
'皮肤',
'快捷栏装备',
'腰带',
'下装',
'鞋',
'宠物',
'宠物装备-红',
'宠物装备-绿',
'宠物装备-蓝',
]
const oathParts = Array.from({ length: 12 }, (_, i) => i.toString())
const emblemParts = ['彩色', '红色', '蓝色', '绿色', '黄色', '白金']
const createCharacter = async (alter: string, equVersion?: string) => {
const time = new Date().getTime()
alter_token.value = btoa(JSON.stringify({ alter, equVersion, time }))
infos.value = await api.characterInfo()
useConfigStore().loadConfig()
}
return {
alter_token,
infos,
skills,
equips,
suits,
createCharacter,
enchants,
emblems,
parts,
oaths,
avatarParts,
oathParts,
emblemParts,
avatars,
jades,
setStandard,
standard,
sundries,
options,
oathSkills,
getOathInfo,
}
})