剧诗页新增绘想游迹&月谕圣牌浮窗

This commit is contained in:
BTMuli
2026-02-12 21:04:22 +08:00
parent 7f815d2452
commit 435b1a81db
15 changed files with 676 additions and 33 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View 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>

View File

@@ -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);

View 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>

View 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>

View 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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;
};
}