mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-03-27 05:49:45 +08:00
✨ 剧诗页新增绘想游迹&月谕圣牌浮窗
This commit is contained in:
BIN
public/UI/combat/charBg.webp
Normal file
BIN
public/UI/combat/charBg.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/UI/combat/charFinish.webp
Normal file
BIN
public/UI/combat/charFinish.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
BIN
public/UI/combat/charFront.webp
Normal file
BIN
public/UI/combat/charFront.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
BIN
public/UI/combat/charLock.webp
Normal file
BIN
public/UI/combat/charLock.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/UI/combat/charMaster.webp
Normal file
BIN
public/UI/combat/charMaster.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 638 B |
BIN
public/UI/combat/tarotDefault.webp
Normal file
BIN
public/UI/combat/tarotDefault.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
147
src/components/userCombat/tuc-ov-char.vue
Normal file
147
src/components/userCombat/tuc-ov-char.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<!-- 绘想游迹浮窗 -->
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<div v-if="props.data" :class="{ share: isShare }" class="tuc-ovc-box">
|
||||
<div class="tuc-ovc-top">
|
||||
<div class="tuc-ovc-title" @click="share()">
|
||||
<img alt="char" src="/UI/combat/charMaster.webp" />
|
||||
<span>绘想游迹</span>
|
||||
</div>
|
||||
<div class="tuc-ovc-append">
|
||||
<span>已完成</span>
|
||||
<span>{{ finish }}/{{ total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tuc-ovc-list">
|
||||
<TucOvcItem v-for="(item, idx) in props.data" :key="idx" :item />
|
||||
</div>
|
||||
<div class="tuc-ovc-share">
|
||||
<span>UID {{ props.uid }}</span>
|
||||
<span>|</span>
|
||||
<span>TeyvatGuide v{{ version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import gameEnum from "@enum/game.js";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { generateShareImg } from "@utils/TGShare.js";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
|
||||
import TucOvcItem from "./tuc-ovc-item.vue";
|
||||
|
||||
type TucOvCharProps = { data: Array<TGApp.Game.Combat.CharMaster>; uid: string | undefined };
|
||||
|
||||
const visible = defineModel<boolean>();
|
||||
const props = defineProps<TucOvCharProps>();
|
||||
|
||||
const isShare = ref<boolean>(false);
|
||||
const version = ref<string>("");
|
||||
const finish = computed<number>(
|
||||
() => props.data.filter((i) => i.status === gameEnum.combat.charMasterStat.DONE).length,
|
||||
);
|
||||
const total = computed<number>(() => props.data.length);
|
||||
|
||||
onMounted(async () => {
|
||||
version.value = await getVersion();
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const element = document.querySelector<HTMLElement>(".tuc-ovc-box");
|
||||
if (element === null) {
|
||||
showSnackbar.warn("未获取到分享内容");
|
||||
return;
|
||||
}
|
||||
const fileName = `绘想游迹_${props.uid}_${new Date().getTime()}.png`;
|
||||
await showLoading.start("正在生成分享图", fileName);
|
||||
isShare.value = true;
|
||||
await generateShareImg(fileName, element, 1.2, true);
|
||||
isShare.value = false;
|
||||
await showLoading.end();
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovc-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 800px;
|
||||
max-height: 600px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 8px;
|
||||
background: var(--app-page-bg);
|
||||
gap: 8px;
|
||||
|
||||
&.share {
|
||||
overflow-y: auto;
|
||||
|
||||
.tuc-ovc-list {
|
||||
overflow-y: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovc-top {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tuc-ovc-title {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
|
||||
img {
|
||||
height: 32px;
|
||||
padding: 2px;
|
||||
border-radius: 50%;
|
||||
background: var(--tgc-od-orange);
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovc-append {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.tuc-ovc-list {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
padding-right: 4px;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tuc-ovc-share {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
right: 4px;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -83,7 +83,7 @@ async function share(): Promise<void> {
|
||||
showSnackbar.error("未获取到分享内容");
|
||||
return;
|
||||
}
|
||||
const fileName = `真境剧诗_${new Date().getTime()}.png`;
|
||||
const fileName = `真境剧诗统计_${new Date().getTime()}.png`;
|
||||
await showLoading.start("正在生成分享图", fileName);
|
||||
isShare.value = true;
|
||||
await generateShareImg(fileName, element, 1.2, true);
|
||||
|
||||
129
src/components/userCombat/tuc-ov-tarot.vue
Normal file
129
src/components/userCombat/tuc-ov-tarot.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<!-- 月谕圣牌浮窗 -->
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<div v-if="data" :class="{ share: isShare }" class="tuc-ovt-box">
|
||||
<div class="tuc-ovt-top">
|
||||
<div class="tuc-ovt-title" @click="share()">月谕圣牌</div>
|
||||
<div class="tuc-ovt-append">
|
||||
<span>已解锁:</span>
|
||||
<span>{{ finish }}/{{ total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tuc-ovt-list">
|
||||
<TucOvtItem v-for="(item, index) in data.list" :key="index" :item />
|
||||
</div>
|
||||
<div class="tuc-ovt-share">
|
||||
<span>UID {{ props.uid }}</span>
|
||||
<span>|</span>
|
||||
<span>TeyvatGuide v{{ version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TucOvtItem from "@comp/userCombat/tuc-ovt-item.vue";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { generateShareImg } from "@utils/TGShare.js";
|
||||
import { computed, nextTick, onMounted, ref } from "vue";
|
||||
|
||||
type TucOvTarotProps = { data: TGApp.Game.Combat.TarotState | undefined; uid: string | undefined };
|
||||
|
||||
const visible = defineModel<boolean>();
|
||||
const props = defineProps<TucOvTarotProps>();
|
||||
|
||||
const isShare = ref<boolean>(false);
|
||||
const version = ref<string>("");
|
||||
const finish = computed<number>(() => props.data?.curr_num ?? 0);
|
||||
const total = computed(() => props.data?.total_num ?? 22);
|
||||
|
||||
onMounted(async () => {
|
||||
version.value = await getVersion();
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const element = document.querySelector<HTMLElement>(".tuc-ovt-box");
|
||||
if (element === null) {
|
||||
showSnackbar.warn("未获取到分享内容");
|
||||
return;
|
||||
}
|
||||
const fileName = `月谕圣牌_${props.uid}_${new Date().getTime()}.png`;
|
||||
await showLoading.start("正在生成分享图", fileName);
|
||||
isShare.value = true;
|
||||
await nextTick();
|
||||
await generateShareImg(fileName, element, 1.2, true);
|
||||
isShare.value = false;
|
||||
await showLoading.end();
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovt-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 800px;
|
||||
max-height: 600px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 4px;
|
||||
background: var(--app-page-bg);
|
||||
gap: 8px;
|
||||
|
||||
&.share {
|
||||
overflow-y: auto;
|
||||
|
||||
.tuc-ovt-list {
|
||||
overflow-y: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovt-top {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tuc-ovt-title {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tuc-ovt-append {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.tuc-ovt-list {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
padding-right: 4px;
|
||||
gap: 16px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tuc-ovt-share {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
right: 4px;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
99
src/components/userCombat/tuc-ovc-item.vue
Normal file
99
src/components/userCombat/tuc-ovc-item.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<!-- 绘想游迹项 -->
|
||||
<template>
|
||||
<div
|
||||
:class="{ locked: props.item.status === gameEnum.combat.charMasterStat.LOCK }"
|
||||
class="tuc-ovci-box"
|
||||
>
|
||||
<img alt="bg" class="tuc-ovci-bg" src="/UI/combat/charBg.webp" />
|
||||
<img :src="props.item.icon" alt="icon" class="tuc-ovci-icon" />
|
||||
<img alt="front" class="tuc-ovci-front" src="/UI/combat/charFront.webp" />
|
||||
<div class="tuc-ovci-stat">
|
||||
<template v-if="props.item.status === gameEnum.combat.charMasterStat.DONE">
|
||||
<img alt="finish" src="/UI/combat/charFinish.webp" />
|
||||
</template>
|
||||
<template v-if="props.item.status === gameEnum.combat.charMasterStat.LOCK">
|
||||
<img alt="finish" src="/UI/combat/charLock.webp" />
|
||||
</template>
|
||||
</div>
|
||||
<span class="tuc-ovci-title">{{ props.item.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import gameEnum from "@enum/game.js";
|
||||
|
||||
type TucOvcItemProps = { item: TGApp.Game.Combat.CharMaster };
|
||||
const props = defineProps<TucOvcItemProps>();
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovci-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 100%;
|
||||
aspect-ratio: 327 / 600;
|
||||
|
||||
&.locked {
|
||||
.tuc-ovci-icon {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovci-bg {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tuc-ovci-icon {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 3%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.tuc-ovci-front {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tuc-ovci-stat {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 30%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovci-title {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
color: #a67754;
|
||||
font-family: var(--font-title);
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
41
src/components/userCombat/tuc-ovt-item.vue
Normal file
41
src/components/userCombat/tuc-ovt-item.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- 月谕圣牌项 -->
|
||||
<template>
|
||||
<div class="tuc-ovti-box" @click="console.log(props.item)">
|
||||
<div class="tuc-ovti-icon">
|
||||
<img v-if="!props.item.is_unlock" alt="lock" src="/UI/combat/tarotDefault.webp" />
|
||||
<img v-else :alt="props.item.name" :src="props.item.icon" />
|
||||
</div>
|
||||
<div class="tuc-ovti-name">{{ props.item.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
type TucOvtItemProps = { item: TGApp.Game.Combat.TarotCard };
|
||||
|
||||
const props = defineProps<TucOvtItemProps>();
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovti-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
.tuc-ovti-icon {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovti-name {
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 游戏相关枚举
|
||||
* @since Beta v0.9.1
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -136,6 +136,16 @@ function getGameAnnoLangDesc(lang: TGApp.Game.Anno.AnnoLangEnum): string {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘想游迹状态枚举
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
const CombatCharMasterStatEnum: typeof TGApp.Game.Combat.CharMasterStat = {
|
||||
LOCK: 1,
|
||||
UNFINISH: 2,
|
||||
DONE: 3,
|
||||
};
|
||||
|
||||
/** 游戏相关枚举 */
|
||||
const gameEnum = {
|
||||
actCalendarType: ActCalendarTypeEnum,
|
||||
@@ -149,6 +159,9 @@ const gameEnum = {
|
||||
langList: GameAnnoLangList,
|
||||
langDesc: getGameAnnoLangDesc,
|
||||
},
|
||||
combat: {
|
||||
charMasterStat: CombatCharMasterStatEnum,
|
||||
},
|
||||
};
|
||||
|
||||
export default gameEnum;
|
||||
|
||||
@@ -59,10 +59,20 @@
|
||||
</template>
|
||||
<template #extension>
|
||||
<div class="uct-extension">
|
||||
<v-btn class="uc-btn" variant="elevated" @click="loadWiki()">
|
||||
<img alt="abyss" src="/platforms/other/hutao.webp" />
|
||||
<span>统计数据</span>
|
||||
</v-btn>
|
||||
<div class="uct-extension-left">
|
||||
<v-btn class="uc-btn" variant="elevated" @click="loadWiki()">
|
||||
<img alt="abyss" src="/platforms/other/hutao.webp" />
|
||||
<span>统计数据</span>
|
||||
</v-btn>
|
||||
<v-btn class="uc-btn" variant="elevated" @click="loadCharMaster()">
|
||||
<img alt="char" src="/UI/combat/charMaster.webp" />
|
||||
<span>绘想游迹</span>
|
||||
</v-btn>
|
||||
<v-btn class="uc-btn" variant="elevated" @click="loadTarot()">
|
||||
<img alt="char" src="/UI/combat/tarotDefault.webp" />
|
||||
<span>月谕圣牌</span>
|
||||
</v-btn>
|
||||
</div>
|
||||
<div class="uct-extension-right">
|
||||
<span @click="tryLoginHutao()">{{ userName ?? "登录胡桃云" }}</span>
|
||||
<v-btn
|
||||
@@ -130,7 +140,9 @@
|
||||
<span>暂无数据,请尝试刷新</span>
|
||||
</div>
|
||||
</div>
|
||||
<TucOverlay v-model="showData" :data="cloudCombat" />
|
||||
<TucOvStat v-model="showStat" :data="cloudCombat" />
|
||||
<TucOvChar v-model="showChar" :data="charMasters" :uid="uidCur" />
|
||||
<TucOvTarot v-model="showTarot" :data="tarotStat" :uid="uidCur" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TSubLine from "@comp/app/t-subline.vue";
|
||||
@@ -138,7 +150,9 @@ import showDialog from "@comp/func/dialog.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TucAvatars from "@comp/userCombat/tuc-avatars.vue";
|
||||
import TucOverlay from "@comp/userCombat/tuc-overlay.vue";
|
||||
import TucOvChar from "@comp/userCombat/tuc-ov-char.vue";
|
||||
import TucOvStat from "@comp/userCombat/tuc-ov-stat.vue";
|
||||
import TucOvTarot from "@comp/userCombat/tuc-ov-tarot.vue";
|
||||
import TucOverview from "@comp/userCombat/tuc-overview.vue";
|
||||
import TucRound from "@comp/userCombat/tuc-round.vue";
|
||||
import hutao from "@Hutao/index.js";
|
||||
@@ -166,11 +180,16 @@ const { userName } = storeToRefs(hutaoStore);
|
||||
const userTab = ref<number>(0);
|
||||
const version = ref<string>();
|
||||
const uidCur = ref<string>();
|
||||
const showData = ref<boolean>(false);
|
||||
const uidList = shallowRef<Array<string>>();
|
||||
const cloudCombat = shallowRef<TGApp.Plugins.Hutao.Combat.Data>();
|
||||
const localCombat = shallowRef<Array<TGApp.Sqlite.Combat.TableTrans>>([]);
|
||||
|
||||
const showStat = ref<boolean>(false);
|
||||
const cloudCombat = shallowRef<TGApp.Plugins.Hutao.Combat.Data>();
|
||||
const showChar = ref<boolean>(false);
|
||||
const charMasters = shallowRef<Array<TGApp.Game.Combat.CharMaster>>([]);
|
||||
const showTarot = ref<boolean>(false);
|
||||
const tarotStat = shallowRef<TGApp.Game.Combat.TarotState>();
|
||||
|
||||
onMounted(async () => {
|
||||
await showLoading.start("正在加载剧诗数据");
|
||||
version.value = await getVersion();
|
||||
@@ -204,7 +223,9 @@ async function loadWiki(): Promise<void> {
|
||||
} else cloudCombat.value = res;
|
||||
await showLoading.end();
|
||||
showSnackbar.success("成功获取统计数据");
|
||||
showData.value = true;
|
||||
if (showTarot.value) showTarot.value = false;
|
||||
if (showChar.value) showChar.value = false;
|
||||
showStat.value = true;
|
||||
}
|
||||
|
||||
async function reloadUid(): Promise<void> {
|
||||
@@ -255,13 +276,8 @@ async function refreshCombat(): Promise<void> {
|
||||
}
|
||||
await TGLogger.Info("[UserCombat][refreshCombat] 更新剧诗数据");
|
||||
await showLoading.start(`正在获取${account.value.gameUid}的剧诗数据`);
|
||||
const res = await recordReq.roleCombat(cookie.value, account.value);
|
||||
const res = await recordReq.combat.base(cookie.value, account.value);
|
||||
console.log(res);
|
||||
if (res === false) {
|
||||
await showLoading.end();
|
||||
showSnackbar.warn("用户未解锁幻想真境剧诗");
|
||||
return;
|
||||
}
|
||||
if ("retcode" in res) {
|
||||
await showLoading.end();
|
||||
showSnackbar.error(`[${res.retcode}]${res.message}`);
|
||||
@@ -269,8 +285,13 @@ async function refreshCombat(): Promise<void> {
|
||||
await TGLogger.Error(`[UserCombat][refreshCombat] ${res.retcode} ${res.message}`);
|
||||
return;
|
||||
}
|
||||
if (!res.is_unlock) {
|
||||
await showLoading.end();
|
||||
showSnackbar.warn("用户未解锁幻想真境剧诗");
|
||||
return;
|
||||
}
|
||||
await showLoading.update("正在保存剧诗数据");
|
||||
for (const combat of res) {
|
||||
for (const combat of res.data) {
|
||||
await showLoading.update("正在保存剧诗数据");
|
||||
await TSUserCombat.saveCombat(account.value.gameUid, combat);
|
||||
}
|
||||
@@ -280,6 +301,102 @@ async function refreshCombat(): Promise<void> {
|
||||
await showLoading.end();
|
||||
}
|
||||
|
||||
async function loadCharMaster(): Promise<void> {
|
||||
if (!cookie.value) {
|
||||
showSnackbar.error("未登录");
|
||||
await TGLogger.Warn("[UserCombat][loadCharMaster] 未登录");
|
||||
return;
|
||||
}
|
||||
if (uidCur.value && uidCur.value !== account.value.gameUid) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至 ${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value);
|
||||
await refreshCombat();
|
||||
return;
|
||||
}
|
||||
const freshCheck = await showDialog.check(
|
||||
"确定刷新?",
|
||||
`用户${account.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消剧诗数据刷新");
|
||||
return;
|
||||
}
|
||||
}
|
||||
await TGLogger.Info("[UserCombat][loadCharMaster] 获取绘想游迹数据");
|
||||
await showLoading.start(`正在获取${account.value.gameUid}的绘想游迹数据`);
|
||||
const res = await recordReq.combat.char(cookie.value, account.value);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
await showLoading.end();
|
||||
showSnackbar.error(`[${res.retcode}]${res.message}`);
|
||||
await TGLogger.Error(`[UserCombat][loadCharMaster] 获取${account.value.gameUid}的剧诗数据失败`);
|
||||
await TGLogger.Error(`[UserCombat][loadCharMaster] ${res.retcode} ${res.message}`);
|
||||
return;
|
||||
}
|
||||
if (!res.is_unlock) {
|
||||
await showLoading.end();
|
||||
showSnackbar.warn("用户未解锁绘想游迹");
|
||||
return;
|
||||
} else charMasters.value = res.list;
|
||||
showSnackbar.success("成功获取绘想游迹数据");
|
||||
await showLoading.end();
|
||||
if (showStat.value) showStat.value = false;
|
||||
if (showTarot.value) showTarot.value = false;
|
||||
showChar.value = true;
|
||||
}
|
||||
|
||||
async function loadTarot(): Promise<void> {
|
||||
if (!cookie.value) {
|
||||
showSnackbar.error("未登录");
|
||||
await TGLogger.Warn("[UserCombat][loadTarot] 未登录");
|
||||
return;
|
||||
}
|
||||
if (uidCur.value && uidCur.value !== account.value.gameUid) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至 ${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value);
|
||||
await refreshCombat();
|
||||
return;
|
||||
}
|
||||
const freshCheck = await showDialog.check(
|
||||
"确定刷新?",
|
||||
`用户${account.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消剧诗数据刷新");
|
||||
return;
|
||||
}
|
||||
}
|
||||
await TGLogger.Info("[UserCombat][loadTarot] 获取月谕圣牌数据");
|
||||
await showLoading.start(`正在获取${account.value.gameUid}的月谕圣牌数据`);
|
||||
const res = await recordReq.combat.base(cookie.value, account.value);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
await showLoading.end();
|
||||
showSnackbar.error(`[${res.retcode}]${res.message}`);
|
||||
await TGLogger.Error(`[UserCombat][loadTarot] 获取${account.value.gameUid}的月谕圣牌数据失败`);
|
||||
await TGLogger.Error(`[UserCombat][loadTarot] ${res.retcode} ${res.message}`);
|
||||
return;
|
||||
}
|
||||
if (!res.is_unlock) {
|
||||
await showLoading.end();
|
||||
showSnackbar.warn("用户未解锁幻想真境剧诗");
|
||||
return;
|
||||
} else tarotStat.value = res.tarot_card_state;
|
||||
showSnackbar.success("成功获取月谕圣牌数据");
|
||||
await showLoading.end();
|
||||
if (showStat.value) showStat.value = false;
|
||||
if (showChar.value) showChar.value = false;
|
||||
showTarot.value = true;
|
||||
}
|
||||
|
||||
async function shareCombat(): Promise<void> {
|
||||
await TGLogger.Info(`[UserCombat][shareCombat][${userTab.value}] 生成剧诗数据分享图片`);
|
||||
const fileName = `【真境剧诗】${userTab.value}-${uidCur.value}`;
|
||||
@@ -448,6 +565,14 @@ function isFinTarot(data: TGApp.Sqlite.Combat.TableTrans): boolean {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.uct-extension-left {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.uct-extension-right {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -475,7 +600,6 @@ function isFinTarot(data: TGApp.Sqlite.Combat.TableTrans): boolean {
|
||||
font-family: var(--font-text);
|
||||
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 4px;
|
||||
object-fit: contain;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* TakumiRecordGenshinApi 相关请求
|
||||
* @since Beta v0.9.1
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
|
||||
import gameEnum from "@enum/game.js";
|
||||
@@ -81,7 +81,7 @@ async function index(
|
||||
|
||||
/**
|
||||
* 获取真境剧诗数据
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.9.6
|
||||
* @param cookie - Cookie
|
||||
* @param user - 用户
|
||||
* @returns 真境剧诗数据
|
||||
@@ -89,7 +89,7 @@ async function index(
|
||||
async function roleCombat(
|
||||
cookie: TGApp.App.Account.Cookie,
|
||||
user: TGApp.Sqlite.Account.Game,
|
||||
): Promise<Array<TGApp.Game.Combat.Combat> | TGApp.BBS.Response.Base | false> {
|
||||
): Promise<TGApp.Game.Combat.CombatRes | TGApp.BBS.Response.Base> {
|
||||
const ck = {
|
||||
account_id: cookie.account_id,
|
||||
cookie_token: cookie.cookie_token,
|
||||
@@ -97,13 +97,38 @@ async function roleCombat(
|
||||
ltuid: cookie.ltuid,
|
||||
};
|
||||
const params = { role_id: user.gameUid, server: user.region, active: 1, need_detail: true };
|
||||
const resp = await TGHttp<TGApp.Game.Combat.Response | TGApp.BBS.Response.Base>(
|
||||
const resp = await TGHttp<TGApp.Game.Combat.CombatResp | TGApp.BBS.Response.Base>(
|
||||
`${trgAbu}role_combat`,
|
||||
{ method: "GET", headers: getRequestHeader(ck, "GET", params), query: params },
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
if (!resp.data.is_unlock) return false;
|
||||
return resp.data.data;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绘想游迹数据
|
||||
* @since Beta v0.9.6
|
||||
* @param cookie - Cookie
|
||||
* @param user - 用户
|
||||
* @returns 绘想游迹数据
|
||||
*/
|
||||
async function charMaster(
|
||||
cookie: TGApp.App.Account.Cookie,
|
||||
user: TGApp.Sqlite.Account.Game,
|
||||
): Promise<TGApp.BBS.Response.Base | TGApp.Game.Combat.CharRes> {
|
||||
const ck = {
|
||||
account_id: cookie.account_id,
|
||||
cookie_token: cookie.cookie_token,
|
||||
ltoken: cookie.ltoken,
|
||||
ltuid: cookie.ltuid,
|
||||
};
|
||||
const params = { role_id: user.gameUid, server: user.region };
|
||||
const resp = await TGHttp<TGApp.Game.Combat.CharResp | TGApp.BBS.Response.Base>(
|
||||
`${trgAbu}char_master`,
|
||||
{ method: "GET", headers: getRequestHeader(ck, "GET", params), query: params },
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,7 +234,10 @@ const recordReq = {
|
||||
index: index,
|
||||
actCalendar: actCalendar,
|
||||
character: { list: characterList, detail: characterDetail },
|
||||
roleCombat: roleCombat,
|
||||
combat: {
|
||||
base: roleCombat,
|
||||
char: charMaster,
|
||||
},
|
||||
spiralAbyss: spiralAbyss,
|
||||
challenge: {
|
||||
detail: hardChallengeDetail,
|
||||
|
||||
76
src/types/Game/Combat.d.ts
vendored
76
src/types/Game/Combat.d.ts
vendored
@@ -1,19 +1,26 @@
|
||||
/**
|
||||
* 幻想真境剧诗类型定义
|
||||
* @since Beta v0.8.3
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Game.Combat {
|
||||
/**
|
||||
* 幻想真境剧诗数据返回响应
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type Response = TGApp.BBS.Response.BaseWithData<FullData>;
|
||||
type CombatResp = TGApp.BBS.Response.BaseWithData<CombatRes>;
|
||||
|
||||
/**
|
||||
* 绘想游迹数据返回响应
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type CharResp = TGApp.BBS.Response.BaseWithData<CharRes>;
|
||||
|
||||
/**
|
||||
* 幻想真境剧诗数据返回
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type FullData = {
|
||||
type CombatRes = {
|
||||
/** 是否解锁 */
|
||||
is_unlock: boolean;
|
||||
/** 相关链接 */
|
||||
@@ -24,6 +31,17 @@ declare namespace TGApp.Game.Combat {
|
||||
tarot_card_state: TarotState;
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘想游迹数据返回
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type CharRes = {
|
||||
/** 绘想游迹列表 */
|
||||
list: Array<CharMaster>;
|
||||
/** 是否解锁 */
|
||||
is_unlock: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 角色数据
|
||||
* @since Beta v0.6.3
|
||||
@@ -293,7 +311,7 @@ declare namespace TGApp.Game.Combat {
|
||||
|
||||
/**
|
||||
* 塔罗牌
|
||||
* @since Beta v0.8.3
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type TarotCard = {
|
||||
/** 图标 */
|
||||
@@ -301,8 +319,52 @@ declare namespace TGApp.Game.Combat {
|
||||
/** 名称 */
|
||||
name: string;
|
||||
/** 是否解锁 */
|
||||
is_unlocked: boolean;
|
||||
is_unlock: boolean;
|
||||
/** 解锁数 */
|
||||
unlock_num: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘想游迹状态类型
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
const CharMasterStat = <const>{
|
||||
/** 未解锁 */
|
||||
LOCK: 1,
|
||||
/** 未挑战 */
|
||||
UNFINISH: 2,
|
||||
/** 已拥有 */
|
||||
DONE: 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘想游迹状态枚举
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type CharMasterStatEnum = (typeof CharMasterStat)[keyof typeof CharMasterStat];
|
||||
|
||||
/**
|
||||
* 绘想游迹数据
|
||||
* @since Beta v0.9.6
|
||||
*/
|
||||
type CharMaster = {
|
||||
/** 角色 ID */
|
||||
avatar_id: number;
|
||||
/** 角色名称 */
|
||||
name: string;
|
||||
/** 角色图标 */
|
||||
icon: string;
|
||||
/**
|
||||
* 状态
|
||||
* @example
|
||||
* 1 - 未解锁
|
||||
* 2 - 未挑战
|
||||
* 3 - 已拥有
|
||||
*/
|
||||
status: CharMasterStatEnum;
|
||||
/** 是否有红点 */
|
||||
has_red_dot: boolean;
|
||||
/** 等级ID */
|
||||
level_id: number;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user