🎨 规范化代码

This commit is contained in:
BTMuli
2025-12-24 02:46:28 +08:00
parent 8500668213
commit 651a89145f
199 changed files with 5067 additions and 5390 deletions

View File

@@ -36,8 +36,8 @@ const model = defineModel<number>({ default: 2 });
const actId = ref<string>();
const showOverlay = ref<boolean>(false);
const nav = shallowRef<TGApp.BBS.Navigator.Navigator[]>([]);
const codeData = shallowRef<TGApp.BBS.Navigator.CodeData[]>([]);
const nav = shallowRef<Array<TGApp.BBS.Navigator.Navigator>>([]);
const codeData = shallowRef<Array<TGApp.BBS.Navigator.CodeData>>([]);
const hasNav = computed<TGApp.BBS.Navigator.Navigator | undefined>(() => {
const liveNames = ["前瞻直播", "前瞻节目", "直播兑换码", "特别节目"];
const find = nav.value.find((item) => liveNames.includes(item.name));

View File

@@ -81,7 +81,7 @@ function parseNameCard(desc: string): string {
return res;
}
function parseDesc(desc: string, inQuote: boolean = false): string[] {
function parseDesc(desc: string, inQuote: boolean = false): Array<string> {
let res = desc.replace(/。/g, "。\n");
res = res.replace(//g, "\n");
/* 闲云·鹤云 */
@@ -113,7 +113,7 @@ function parseDesc(desc: string, inQuote: boolean = false): string[] {
res = res.replace(/\n」/g, "」\n");
}
const match = res.split("\n");
let array: string[] = [];
let array: Array<string> = [];
for (const item of match) {
if (item.length > 0 && item.length <= 32) {
array.push(item);

View File

@@ -1,6 +1,5 @@
/**
* @file component/func/dialog.ts
* @description dialog 组件封装,函数式调用
* dialog 组件封装,函数式调用
* @since Beta v0.6.3
*/
@@ -27,18 +26,15 @@ export type DialogInputParams = {
};
/**
* @description 自定义 confirm 组件
* 自定义 confirm 组件
* @since Beta v0.6.3
* @extends ComponentInternalInstance
* @property {Function} exposeProxy.displayBox 显示 confirm
* @return DialogInstance
*/
interface DialogInstance extends ComponentInternalInstance {
type DialogInstance = {
exposeProxy: {
displayCheckBox: (props: DialogCheckParams) => Promise<boolean | undefined>;
displayInputBox: (props: DialogInputParams) => Promise<string | false | undefined>;
};
}
} & ComponentInternalInstance;
function renderBox(props: DialogParams): VNode {
const container = document.createElement("div");

View File

@@ -13,18 +13,15 @@ const geetestId = "tg-func-geetest";
/**
* 自定义 geetest 组件
* @since Beta v0.8.7
* @extends ComponentInternalInstance
* @property {Function} exposeProxy.displayBox 弹出 geetest 验证
* @return GeetestInstance
*/
interface GeetestInstance extends ComponentInternalInstance {
type GeetestInstance = {
exposeProxy: {
displayBox: (
props: TGApp.BBS.Geetest.CreateRes,
raw?: TGApp.BBS.CaptchaLogin.CaptchaAigis,
) => Promise<TGApp.BBS.Geetest.GeetestVerifyRes | false>;
};
}
} & ComponentInternalInstance;
function renderBox(props: TGApp.BBS.Geetest.CreateRes): VNode {
const container = document.createElement("div");
@@ -40,9 +37,9 @@ let geetestInstance: VNode;
/**
* 弹出 geetest 验证
* @since Beta v0.8.7
* @param {TGApp.BBS.Geetest.CreateRes} props geetest 验证的参数
* @param {TGApp.BBS.CaptchaLogin.CaptchaAigis} raw 原始数据,一般用于 Gt4 验证
* @return {Promise<TGApp.BBS.Geetest.GeetestVerifyRes|false>} 验证成功返回验证数据
* @param props - geetest 验证的参数
* @param raw - 原始数据,一般用于 Gt4 验证
* @returns 验证数据
*/
async function showGeetest(
props: TGApp.BBS.Geetest.CreateRes,

View File

@@ -1,6 +1,5 @@
/**
* @file component/func/loading.ts
* @description loading 组件封装,函数式调用
* loading 组件封装,函数式调用
* @since Beta v0.6.7
*/
@@ -17,9 +16,9 @@ type LoadingUpdateParams = Omit<LoadingParams, "show" | "subtitle"> & { timeout?
const TIMEOUT: Readonly<number> = 150;
/**
* @description 自定义 loading 组件
* 自定义 loading 组件
* @since Beta v0.6.7
* @return LoadingInstance
* @returns LoadingInstance
*/
type LoadingInstance = ComponentInternalInstance & {
exposeProxy: { displayBox: (props: LoadingParams) => Promise<void> };

View File

@@ -1,6 +1,5 @@
/**
* @file component/func/snackbar.ts
* @description snackbar 组件封装,函数式调用
* snackbar 组件封装,函数式调用
* @since Beta v0.6.3
*/
@@ -14,15 +13,14 @@ const snackbarId = "tg-func-snackbar";
export type SnackbarParams = { text: string; color: string; timeout: number };
/**
* @description 自定义 snackbar 组件
* 自定义 snackbar 组件
* @since Beta v0.6.3
* @return SnackbarInstance
*/
interface SnackbarInstance extends ComponentInternalInstance {
type SnackbarInstance = {
exposeProxy: {
displayBox: (props: SnackbarParams) => void;
};
}
} & ComponentInternalInstance;
function renderBox(props: SnackbarParams): VNode {
const container = document.createElement("div");

View File

@@ -1,7 +1,7 @@
<template>
<div :id="`anno_card_${model.id}`" class="anno-card">
<div :title="model.title" class="anno-cover" @click="createAnno">
<TMiImg v-if="model.banner !== ''" :ori="true" :src="model.banner" alt="cover" />
<div :id="`anno_card_${props.anno.ann_id}`" class="anno-card">
<div :title="props.anno.title" class="anno-cover" @click="createAnno">
<TMiImg v-if="props.anno.banner !== ''" :ori="true" :src="props.anno.banner" alt="cover" />
<img v-else alt="cover" src="/source/UI/defaultCover.webp" />
<div class="anno-info">
<div class="anno-time">
@@ -10,26 +10,19 @@
</div>
</div>
</div>
<div :title="model.title" class="anno-title" @click="shareAnno">
{{ parseTitle(model.subtitle) }}
<div :title="props.anno.title" class="anno-title" @click="shareAnno">
{{ parseTitle(props.anno.subtitle) }}
</div>
<div
:style="{ background: str2Color(`${model.tagIcon}${model.tagLabel}`, 40) }"
:title="`标签:${model.tagLabel}`"
class="anno-label"
>
<TMiImg :ori="true" :src="model.tagIcon" alt="tag" />
<span>{{ model.tagLabel }}</span>
</div>
<div :style="{ background: str2Color(`${model.id}`, 0) }" class="anno-id">
ID:{{ model.id }}
<div :title="`标签:${props.anno.tag_label}`" class="anno-label">
<TMiImg :ori="true" :src="props.anno.tag_icon" alt="tag" />
<span>{{ props.anno.tag_label }}</span>
</div>
<div class="anno-id">ID:{{ props.anno.ann_id }}</div>
</div>
</template>
<script lang="ts" setup>
import TMiImg from "@comp/app/t-mi-img.vue";
import showSnackbar from "@comp/func/snackbar.js";
import { AnnoTypeEnum } from "@enum/anno.js";
import useAppStore from "@store/app.js";
import { str2Color } from "@utils/colorFunc.js";
import TGLogger from "@utils/TGLogger.js";
@@ -37,19 +30,26 @@ import { generateShareImg } from "@utils/TGShare.js";
import { createTGWindow } from "@utils/TGWindow.js";
import { decodeRegExp } from "@utils/toolFunc.js";
import { storeToRefs } from "pinia";
import { onMounted, ref, watch } from "vue";
import { computed, onMounted, ref, watch } from "vue";
import type { AnnoCard } from "@/pages/common/PageAnno.vue";
type TaCardProps = { anno: TGApp.Game.Anno.ListAnno; detail?: TGApp.Game.Anno.AnnoDetail };
const { server, lang } = storeToRefs(useAppStore());
const model = defineModel<AnnoCard>({ required: true });
const timeStr = ref<string>(model.value.timeStr);
const props = defineProps<TaCardProps>();
const timeStr = ref<string>("");
const idColor = computed<string>(() => str2Color(`${props.anno.ann_id}`, 0));
const tagColor = computed<string>(() =>
str2Color(`${props.anno.tag_icon}${props.anno.tag_label}`, 40),
);
onMounted(() => refreshAnnoTime());
watch(
() => model.value,
() => props.anno,
(newVal, oldVal) => {
if (newVal.id !== oldVal.id) refreshAnnoTime();
if (newVal.ann_id !== oldVal.ann_id) refreshAnnoTime();
},
);
@@ -59,15 +59,15 @@ function parseTitle(title: string): string {
}
async function createAnno(): Promise<void> {
const annoPath = `/anno_detail/${server.value}/${model.value.id}/${lang.value}`;
const annoTitle = `Anno_${model.value.id} ${model.value.title}`;
await TGLogger.Info(`[Announcements][createAnno][${model.value.id}] 打开公告窗口`);
const annoPath = `/anno_detail/${server.value}/${props.anno.ann_id}/${lang.value}`;
const annoTitle = `Anno_${props.anno.ann_id} ${props.anno.title}`;
await TGLogger.Info(`[Announcements][createAnno][${props.anno.ann_id}] 打开公告窗口`);
await createTGWindow(annoPath, "Sub_window", annoTitle, 960, 720, false, false);
}
async function shareAnno(): Promise<void> {
const fileName = `AnnoCard_${model.value.id}_${model.value.subtitle}`;
const element = document.querySelector<HTMLElement>(`#anno_card_${model.value.id}`);
const fileName = `AnnoCard_${props.anno.ann_id}_${props.anno.subtitle}`;
const element = document.querySelector<HTMLElement>(`#anno_card_${props.anno.ann_id}`);
if (element === null) {
showSnackbar.error("分享失败,未找到分享元素");
return;
@@ -76,18 +76,19 @@ async function shareAnno(): Promise<void> {
}
async function refreshAnnoTime(): Promise<void> {
if (model.value.typeLabel === AnnoTypeEnum.GAME) timeStr.value = model.value.timeStr;
const strGet = getAnnoTime(model.value.detail.content);
// MAGIC ANNO TYPE
if (props.anno.type !== 1) timeStr.value = `${props.anno.start_time} ~ ${props.anno.end_time}`;
const strGet = getAnnoTime(props.detail?.content ?? "");
if (strGet !== false) timeStr.value = strGet;
else timeStr.value = `${props.anno.start_time} ~ ${props.anno.end_time}`;
}
function getAnnoTime(content: string): string | false {
const regexes = [
/〓活动时间〓.*?(\d\.\d|「月之[一二三四五六七八九]」)版本期间持续开放/,
/(?:|).*?(?:(\d\.\d|[])(?:|)|&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;\/t&gt; *?)/s,
/(?:|(|)).*?(?:(\d\.\d|[])(?:|)|&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;\/t&gt; *?)/s,
/(?:||||).*?(\d\.\d|[]).*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;\/t&gt;/s,
/(?:(?:|)||).*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;\/t&gt;.*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;\/t&gt;/s,
// /〓活动时间〓.*?(\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}).*?(\d\.\d版本结束)/
/.*?(\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}).*?((\d\.\d|[]))/s,
];
if (content.match(regexes[0])) {
@@ -224,6 +225,7 @@ function getAnnoTime(content: string): string | false {
align-items: center;
justify-content: flex-start;
padding: 4px;
background: v-bind(tagColor); /* stylelint-disable-line value-keyword-case */
border-bottom-left-radius: 6px;
box-shadow: 0 0 10px var(--tgc-dark-1);
color: var(--tgc-white-1);
@@ -244,7 +246,7 @@ function getAnnoTime(content: string): string | false {
align-items: center;
justify-content: center;
padding: 0 4px;
background: var(--tgc-od-orange);
background: v-bind(idColor); /* stylelint-disable-line value-keyword-case */
border-bottom-right-radius: 4px;
box-shadow: 0 0 8px var(--tgc-dark-1);
color: var(--tgc-white-1);

View File

@@ -24,7 +24,7 @@ import type { MaterialInfo } from "@/pages/common/PageBagMaterial.vue";
/** 组件参数 */
type PbMaterialItemProps = {
/** 数据库数据 */
tb: TGApp.Sqlite.UserBag.TableMaterial;
tb: TGApp.Sqlite.UserBag.MaterialTable;
/** WIKI 数据 */
info: TGApp.App.Material.WikiItem;
/** 当前选中材料 */
@@ -36,7 +36,7 @@ type PbMaterialItemEmits = (e: "select", v: MaterialInfo) => void;
const props = defineProps<PbMaterialItemProps>();
const emits = defineEmits<PbMaterialItemEmits>();
const item = shallowRef<TGApp.Sqlite.UserBag.TableMaterial>(props.tb);
const item = shallowRef<TGApp.Sqlite.UserBag.MaterialTable>(props.tb);
function toMaterial(): void {
emits("select", { tb: item.value, info: props.info });

View File

@@ -37,7 +37,7 @@ async function loadData(): Promise<void> {
const tmp: Array<PboConvertSource> = [];
for (const item of props.data.source) {
let cnt: number = 0;
const dbGet = await TSUserBagMaterial.getMaterial(props.uid, item.id);
const dbGet = await TSUserBagMaterial.getMaterial(props.uid, Number(item.id));
if (dbGet.length > 0) cnt = dbGet[0].count;
tmp.push({ ...item, local: cnt });
}

View File

@@ -78,7 +78,7 @@ const showRecord = computed<boolean>(() => !SKIP_BAG_TYPES.includes(props.data.i
onMounted(async () => (version.value = await getVersion()));
const dbInfo = shallowRef<TGApp.Sqlite.UserBag.TableMaterial>(props.data.tb);
const dbInfo = shallowRef<TGApp.Sqlite.UserBag.MaterialTable>(props.data.tb);
watch(
() => props.data.info,

View File

@@ -36,7 +36,7 @@ const emits = defineEmits<ToPostCollectEmits>();
const visible = defineModel<boolean>();
const select = ref<string>();
const submit = ref<boolean>(false);
const collectList = shallowRef<Array<TGApp.Sqlite.UserCollection.UFCollection>>([]);
const collectList = shallowRef<Array<TGApp.Sqlite.Collection.Collection>>([]);
watch(
() => visible.value,

View File

@@ -194,7 +194,7 @@ async function cycleGetDataGame(): Promise<void> {
model.value = false;
return;
}
const statusRaw: TGApp.Game.Login.StatusPayloadRaw = JSON.parse(res.payload.raw);
const statusRaw: TGApp.Game.Login.StatPayloadRaw = JSON.parse(res.payload.raw);
await showLoading.start("正在获取SToken");
const stResp = await takumiReq.game.stoken(statusRaw);
await showLoading.end();

View File

@@ -42,6 +42,7 @@
</template>
<script lang="ts" setup>
import TMiImg from "@comp/app/t-mi-img.vue";
import bbsEnum from "@enum/bbs.js";
import TSAvatarBirth from "@Sqlm/avatarBirth.js";
import useAppStore from "@store/app.js";
import { parseHtmlText } from "@utils/toolFunc.js";
@@ -90,8 +91,8 @@ async function toBirth(data: TGApp.Archive.Birth.CalendarItem): Promise<void> {
}
async function toNews(): Promise<void> {
recentNewsType.value = "news";
await router.push({ name: "资讯", params: { gid: 2, type: "news" } });
recentNewsType.value = bbsEnum.post.newsType.NEWS;
await router.push({ name: "资讯", params: { gid: 2 } });
}
</script>
<style lang="scss" scoped>

View File

@@ -62,8 +62,8 @@ const { isLogin } = storeToRefs(useAppStore());
const loading = ref<boolean>(false);
const loadingProgress = ref<number>(0);
const loadingText = ref<string>("");
const gameAccounts = ref<TGApp.Sqlite.Account.Game[]>([]);
const signAccounts = ref<SignAccount[]>([]);
const gameAccounts = ref<Array<TGApp.Sqlite.Account.Game>>([]);
const signAccounts = ref<Array<SignAccount>>([]);
watch(
() => uid.value,

View File

@@ -11,7 +11,7 @@
</div>
<div class="subtitle">
<!-- 处理幽境危战 -->
<template v-if="props.pos.type === ActCalendarTypeEnum.HardChallenge">
<template v-if="props.pos.type === gameEnum.actCalendarType.HardChallenge">
<div class="challenge-append" title="点击前往幽境页面" @click="toChallenge()">
<template v-if="!props.pos.hard_challenge_detail.is_unlock">
<span>未解锁</span>
@@ -37,13 +37,13 @@
</div>
</template>
<!-- 处理真境剧诗 -->
<template v-else-if="props.pos.type === ActCalendarTypeEnum.RoleCombat">
<template v-else-if="props.pos.type === gameEnum.actCalendarType.RoleCombat">
<div class="combat-append" title="点击前往剧诗页面" @click="toCombat()">
<span>{{ getCombatStat(props.pos.role_combat_detail) }}</span>
</div>
</template>
<!-- 处理深境螺旋 -->
<template v-else-if="props.pos.type === ActCalendarTypeEnum.Tower">
<template v-else-if="props.pos.type === gameEnum.actCalendarType.Tower">
<div class="abyss-append" title="点击前往深渊页面" @click="toAbyss()">
<template v-if="!props.pos.tower_detail.is_unlock">
<span>未解锁</span>
@@ -60,17 +60,17 @@
</div>
</template>
<!-- 处理区域探索 -->
<template v-else-if="props.pos.type === ActCalendarTypeEnum.Explore">
<template v-else-if="props.pos.type === gameEnum.actCalendarType.Explore">
<span>当前区域探索度: {{ props.pos.explore_detail.explore_percent }}%</span>
</template>
<!-- 处理双倍经验 -->
<template v-else-if="props.pos.type === ActCalendarTypeEnum.Double">
<template v-else-if="props.pos.type === gameEnum.actCalendarType.Double">
<span>
剩余双倍次数: {{ props.pos.double_detail.left }}/{{ props.pos.double_detail.total }}
</span>
</template>
<!-- 处理立本活动 TODO:待完善 -->
<template v-else-if="props.pos.type === ActCalendarTypeEnum.LiBen">
<template v-else-if="props.pos.type === gameEnum.actCalendarType.LiBen">
<span>当天{{ props.pos.liben_detail.status === 1 ? "未" : "已" }}兑换</span>
<span>{{ props.pos.liben_detail.progress }}/{{ props.pos.liben_detail.total }}</span>
<span>
@@ -78,7 +78,7 @@
</span>
</template>
<!-- 处理累登活动 TODO:待完善 -->
<template v-else-if="props.pos.type === ActCalendarTypeEnum.SignIn">
<template v-else-if="props.pos.type === gameEnum.actCalendarType.SignIn">
<span>{{ props.pos.sign_in_detail.progress }}/{{ props.pos.sign_in_detail.total }}</span>
<span>当天{{ props.pos.sign_in_detail.status === 1 ? "未领取" : "已领取" }}</span>
</template>
@@ -114,7 +114,7 @@
</template>
<script lang="ts" setup>
import TMiImg from "@comp/app/t-mi-img.vue";
import { ActCalendarTypeEnum } from "@enum/game.js";
import gameEnum from "@enum/game.js";
import { getHardChallengeDesc } from "@Sql/utils/transUserRecord.js";
import { generateShareImg } from "@utils/TGShare.js";
import { parseHtmlText, stamp2LastTime, timestampToDate } from "@utils/toolFunc.js";

View File

@@ -6,11 +6,11 @@
<div
v-for="(item, index) in channelList"
:key="index"
class="toc-list-item"
:class="props.gid === item.gid.toString() ? 'active' : ''"
class="toc-list-item"
@click="toChannel(item)"
>
<TMiImg :src="item.icon" alt="icon" :ori="true" />
<TMiImg :ori="true" :src="item.icon" alt="icon" />
<span class="toc-list-title">{{ item.title }}</span>
<span class="toc-list-id">GID:{{ item.gid }}</span>
</div>
@@ -22,7 +22,8 @@
import TMiImg from "@comp/app/t-mi-img.vue";
import TOverlay from "@comp/app/t-overlay.vue";
import showSnackbar from "@comp/func/snackbar.js";
import useAppStore, { type NewsType } from "@store/app.js";
import bbsEnum from "@enum/bbs.js";
import useAppStore from "@store/app.js";
import useBBSStore from "@store/bbs.js";
import { storeToRefs } from "pinia";
import { onMounted, shallowRef } from "vue";
@@ -49,11 +50,11 @@ async function toChannel(item: ChannelItem): Promise<void> {
}
visible.value = false;
let link = `/news/${item.gid}/{type}`;
if (recentNewsType.value satisfies NewsType) {
link = link.replace("{type}", recentNewsType.value);
if (recentNewsType.value satisfies TGApp.BBS.Post.NewsTypeEnum) {
link = link.replace("{type}", recentNewsType.value.toString());
} else {
link = link.replace("{type}", "notice");
recentNewsType.value = "notice";
link = link.replace("{type}", bbsEnum.post.newsType.NOTICE.toString());
recentNewsType.value = bbsEnum.post.newsType.NOTICE;
}
window.location.href = link;
}

View File

@@ -61,10 +61,10 @@ const showOverlay = ref<boolean>(false);
const isFinish = ref<boolean>(false);
const ncData = shallowRef<TGApp.App.NameCard.Item>();
const achievements = shallowRef<Array<TGApp.Sqlite.Achievement.RenderAchi>>([]);
const selectedAchi = shallowRef<TGApp.Sqlite.Achievement.RenderAchi>();
const achievements = shallowRef<Array<TGApp.App.Achievement.RenderItem>>([]);
const selectedAchi = shallowRef<TGApp.App.Achievement.RenderItem>();
const renderAchi = computed<Array<TGApp.Sqlite.Achievement.RenderAchi>>(() => {
const renderAchi = computed<Array<TGApp.App.Achievement.RenderItem>>(() => {
if (props.hideFin) return achievements.value.filter((a) => !a.isCompleted);
return achievements.value;
});
@@ -116,7 +116,7 @@ async function loadAchi(): Promise<void> {
showSnackbar.success(`已获取 ${achievements.value.length} 条成就数据`);
}
function selectAchi(data: TGApp.Sqlite.Achievement.RenderAchi): void {
function selectAchi(data: TGApp.App.Achievement.RenderItem): void {
selectedAchi.value = data;
showOverlay.value = true;
}

View File

@@ -1,6 +1,6 @@
<template>
<TOverlay v-model="visible" blur-val="5px">
<div class="tua-ao-container" v-if="props.data">
<div v-if="props.data" class="tua-ao-container">
<slot name="left"></slot>
<div class="tua-ao-box">
<div class="tua-ao-top">
@@ -23,13 +23,13 @@
<div class="tua-ao-mid-title">
<span>原石奖励</span>
<span>{{ props.data.reward }}</span>
<img src="/icon/material/201.webp" alt="原石" />
<img alt="原石" src="/icon/material/201.webp" />
</div>
<div class="tua-ao-mid-title">
<span>触发方式</span>
<span>{{ parseTriggerType() }}</span>
</div>
<div class="tua-ao-mid-item" v-for="item in props.data.trigger.task" :key="item.questId">
<div v-for="item in props.data.trigger.task" :key="item.questId" class="tua-ao-mid-item">
<v-icon size="16">mdi-alert-decagram</v-icon>
<span class="tua-ao-click" @click="searchDirect(item.name)">{{ item.name }}</span>
<span>{{ item.type }}</span>
@@ -40,11 +40,11 @@
<span>是否完成</span>
<span>{{ props.data.isCompleted ? "是" : "否" }}</span>
</div>
<div class="tua-ao-bottom-title" v-if="props.data.isCompleted">
<div v-if="props.data.isCompleted" class="tua-ao-bottom-title">
<span>完成时间</span>
<span>{{ props.data.completedTime }}</span>
</div>
<div class="tua-ao-bottom-title" v-if="props.data.progress > 0">
<div v-if="props.data.progress > 0" class="tua-ao-bottom-title">
<span>当前进度</span>
<span>{{ props.data.progress }}</span>
</div>
@@ -56,7 +56,7 @@
<slot name="right"></slot>
</div>
</TOverlay>
<VpOverlaySearch gid="2" v-model="showSearch" :keyword="search" />
<VpOverlaySearch v-model="showSearch" :keyword="search" gid="2" />
</template>
<script lang="ts" setup>
import TOverlay from "@comp/app/t-overlay.vue";
@@ -68,7 +68,7 @@ import { ref } from "vue";
import { AppAchievementSeriesData } from "@/data/index.js";
type ToAchiInfoProps = { data: TGApp.Sqlite.Achievement.RenderAchi };
type ToAchiInfoProps = { data: TGApp.App.Achievement.RenderItem };
type ToAchiInfoEmits = (e: "select-series", v: number) => void;
const props = defineProps<ToAchiInfoProps>();

View File

@@ -39,17 +39,17 @@ import { ref, toRaw, watch } from "vue";
import { AppAchievementSeriesData } from "@/data/index.js";
type TuaAchiProps = { modelValue: TGApp.Sqlite.Achievement.RenderAchi };
type TuaAchiEmits = (e: "select-achi", data: TGApp.Sqlite.Achievement.RenderAchi) => void;
type TuaAchiProps = { modelValue: TGApp.App.Achievement.RenderItem };
type TuaAchiEmits = (e: "select-achi", data: TGApp.App.Achievement.RenderItem) => void;
const props = defineProps<TuaAchiProps>();
const emits = defineEmits<TuaAchiEmits>();
const model = defineModel<TGApp.Sqlite.Achievement.RenderAchi>();
const data = ref<TGApp.Sqlite.Achievement.RenderAchi>(toRaw(props.modelValue));
const model = defineModel<TGApp.App.Achievement.RenderItem>();
const data = ref<TGApp.App.Achievement.RenderItem>(toRaw(props.modelValue));
watch(
() => props.modelValue,
(newVal: TGApp.Sqlite.Achievement.RenderAchi) => {
(newVal: TGApp.App.Achievement.RenderItem) => {
data.value = toRaw(newVal);
},
);

View File

@@ -1,29 +1,30 @@
<!-- 成就系列 -->
<template>
<div
class="tuas-card"
@click="selectSeries"
v-if="data"
:title="data.name"
:class="{
'tuas-selected': props.cur === props.series,
'tuas-radius': showCard,
}"
:title="data.name"
class="tuas-card"
@click="selectSeries"
>
<div class="tuas-version">v{{ data.version }}</div>
<div class="tuas-reward" v-if="showCard">
<div v-if="showCard" class="tuas-reward">
<img
:class="{ finish: progress === 100 }"
alt="card"
:src="`/WIKI/nameCard/bg/${data.card}.webp`"
alt="card"
/>
</div>
<div class="tuas-icon">
<img alt="icon" :src="`/icon/achievement/${data.icon}.webp`" />
<img :src="`/icon/achievement/${data.icon}.webp`" alt="icon" />
<v-progress-circular
class="progress"
bg-color="var(--tgc-od-white)"
color="var(--tgc-yellow-2)"
:model-value="progress"
bg-color="var(--tgc-od-white)"
class="progress"
color="var(--tgc-yellow-2)"
/>
</div>
<div class="tuas-content">
@@ -47,7 +48,7 @@ let achiListener: UnlistenFn | null = null;
const props = defineProps<TuaSeriesProps>();
const emits = defineEmits<TuaSeriesEmits>();
const overview = shallowRef<TGApp.Sqlite.Achievement.Overview>({ fin: 0, total: 0 });
const overview = shallowRef<TGApp.App.Achievement.Overview>({ fin: 0, total: 0 });
const data = computed<TGApp.App.Achievement.Series | undefined>(() =>
AppAchievementSeriesData.find((s) => s.id === props.series),
);
@@ -109,6 +110,7 @@ function selectSeries(): void {
justify-content: flex-start;
padding: 8px;
border-radius: 4px;
background: var(--app-page-bg);
color: var(--box-text-1);
column-gap: 8px;
cursor: pointer;

View File

@@ -63,7 +63,7 @@ import TuaRelicBox from "./tua-relic-box.vue";
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
type AvatarRelics = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
type TuaAvatarBoxProps = { modelValue: TGApp.Sqlite.Character.UserRole };
type TuaAvatarBoxProps = { modelValue: TGApp.Sqlite.Character.TableTrans };
const props = defineProps<TuaAvatarBoxProps>();
const userStore = useUserStore();
@@ -121,7 +121,7 @@ const nameCard = computed<string>(() => {
function getWeaponTitle(): string {
const weapon = props.modelValue.weapon;
const title: string[] = [];
const title: Array<string> = [];
title.push(`${weapon.type_name} - ${weapon.name}`);
title.push(`${weapon.rarity}星 精炼${weapon.affix_level} Lv.${weapon.level}`);
const propMain = userStore.getProp(weapon.main_property.property_type);

View File

@@ -90,7 +90,7 @@ import TuaDcWeapon from "./tua-dc-weapon.vue";
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
type RelicList = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
type TuaDetailCardProps = { modelValue: TGApp.Sqlite.Character.UserRole };
type TuaDetailCardProps = { modelValue: TGApp.Sqlite.Character.TableTrans };
const props = defineProps<TuaDetailCardProps>();
const userStore = useUserStore();

View File

@@ -55,12 +55,12 @@ import { computed, ref, watch } from "vue";
import TuaDetailCard from "./tua-detail-card.vue";
type TuaDetailOverlayProps = {
avatar: TGApp.Sqlite.Character.UserRole;
avatars: Array<TGApp.Sqlite.Character.UserRole>;
avatar: TGApp.Sqlite.Character.TableTrans;
avatars: Array<TGApp.Sqlite.Character.TableTrans>;
};
type TuaDetailOverlayEmits = {
(e: "toNext", val: boolean): void;
(e: "toAvatar", val: TGApp.Sqlite.Character.UserRole): void;
(e: "toAvatar", val: TGApp.Sqlite.Character.TableTrans): void;
};
const props = defineProps<TuaDetailOverlayProps>();

View File

@@ -46,7 +46,7 @@ function getRelicPosName(): string {
function getRelicTitle(): string {
const posName = getRelicPosName();
if (props.modelValue === false) return `${posName}:未装备`;
const relicProps: string[] = [];
const relicProps: Array<string> = [];
const mainProp = userStore.getProp(props.modelValue.main_property.property_type);
relicProps.push(
`主词条:${mainProp === false ? "未知属性" : mainProp.name} ${props.modelValue.main_property.value}`,

View File

@@ -51,7 +51,7 @@ import DucDetailOlt from "./duc-detail-olt.vue";
import DucDetailOrt from "./duc-detail-ort.vue";
import DucDetailRelic from "./duc-detail-relic.vue";
type DucDetailOverlayProps = { modelValue: TGApp.Sqlite.Character.UserRole };
type DucDetailOverlayProps = { modelValue: TGApp.Sqlite.Character.TableTrans };
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
type RelicList = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;

View File

@@ -84,7 +84,7 @@ import TucDetailDescWeapon from "./tuc-detail-desc-weapon.vue";
import TucDetailItemBox from "./tuc-detail-itembox.vue";
import TucDetailRelic from "./tuc-detail-relic.vue";
type ToUcDetailProps = { modelValue: TGApp.Sqlite.Character.UserRole };
type ToUcDetailProps = { modelValue: TGApp.Sqlite.Character.TableTrans };
type ToUcDetailSelect = { type: "命座" | "武器" | "圣遗物"; pos: number };
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
type RelicList = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;

View File

@@ -21,7 +21,7 @@ import { computed } from "vue";
import { AppGachaBData } from "@/data/index.js";
export type GbrDataLineProps = { data: TGApp.Sqlite.GachaRecords.TableGachaB; count: number };
export type GbrDataLineProps = { data: TGApp.Sqlite.Gacha.GachaB; count: number };
const props = defineProps<GbrDataLineProps>();
const hint = getEndHint();
@@ -47,7 +47,7 @@ const progressColor = computed<string>(() => {
const progressWidth = computed<string>(() => {
let final = 10;
if (props.data.rank === "5") {
if (props.data.gachaType === "302") final = 80;
if (props.data.gachaType === "2000") final = 80;
else final = 90;
} else if (props.data.rank === "4") final = 10;
else return "0%";

View File

@@ -117,7 +117,7 @@ import GbrDataLine, { type GbrDataLineProps } from "./gbr-data-line.vue";
type GachaDataViewProps = {
dataType: "normal" | "boy" | "girl";
dataVal: Array<TGApp.Sqlite.GachaRecords.TableGachaB>;
dataVal: Array<TGApp.Sqlite.Gacha.GachaB>;
};
const props = defineProps<GachaDataViewProps>();
@@ -248,7 +248,7 @@ function loadData(): void {
reset3count.value = currentReset3;
// Helper function to check if item should be displayed based on dataType
function shouldDisplay(item: TGApp.Sqlite.GachaRecords.TableGachaB): boolean {
function shouldDisplay(item: TGApp.Sqlite.Gacha.GachaB): boolean {
if (props.dataType === "normal") return true;
if (props.dataType === "boy") {
return item.opGachaType === "20011" || item.opGachaType === "20012";

View File

@@ -10,13 +10,13 @@ import { computed } from "vue";
import GbrDataView from "./gbr-data-view.vue";
type GachaOverviewProps = { modelValue: Array<TGApp.Sqlite.GachaRecords.TableGachaB> };
type GachaOverviewProps = { modelValue: Array<TGApp.Sqlite.Gacha.GachaB> };
const props = defineProps<GachaOverviewProps>();
const normalData = computed<Array<TGApp.Sqlite.GachaRecords.TableGachaB>>(() =>
const normalData = computed<Array<TGApp.Sqlite.Gacha.GachaB>>(() =>
props.modelValue.filter((item) => item.gachaType === "1000"),
);
const eventData = computed<Array<TGApp.Sqlite.GachaRecords.TableGachaB>>(() =>
const eventData = computed<Array<TGApp.Sqlite.Gacha.GachaB>>(() =>
props.modelValue.filter((item) => item.gachaType === "2000"),
);
</script>

View File

@@ -27,7 +27,7 @@
<script lang="ts" setup>
import { AppGachaBData } from "@/data/index.js";
type GroTableProps = { modelValue: Array<TGApp.Sqlite.GachaRecords.TableGachaB> };
type GroTableProps = { modelValue: Array<TGApp.Sqlite.Gacha.GachaB> };
const props = defineProps<GroTableProps>();
@@ -40,6 +40,7 @@ const headers = <const>[
{ title: "星级", align: "center", key: "rank" },
];
// TODO: 枚举类
function getPool(type: string) {
switch (type) {
case "1000":

View File

@@ -85,8 +85,8 @@ async function getCalendarOptions(): Promise<EChartsOption> {
// 获取年份
const yearsSet = new Set(Object.keys(records).map((v) => v.split("-")[0]));
function getYearData(year: string): [string, number][] {
const res: [string, number][] = [];
function getYearData(year: string): Array<[string, number]> {
const res: Array<[string, number]> = [];
for (const key in records) {
if (key.startsWith(year)) res.push([key, records[key].length]);
}

View File

@@ -99,7 +99,7 @@ async function getStackBarOptions(): Promise<EChartsOption> {
temp4.push(star4);
temp3.push(star3);
}
const series: BarSeriesOption[] = [
const series: Array<BarSeriesOption> = [
{ data: temp5, type: "bar", stack: "a", name: "五星数量" },
{ data: temp4, type: "bar", stack: "a", name: "四星数量" },
{ data: temp3, type: "bar", stack: "a", name: "三星数量" },

View File

@@ -24,7 +24,7 @@ import { computed } from "vue";
*/
export type GroDataLineProps = {
/* 原始数据 */
data: TGApp.Sqlite.GachaRecords.TableGacha;
data: TGApp.Sqlite.Gacha.Gacha;
/* 抽数 */
count: number;
/* 是否是 Up */

View File

@@ -112,7 +112,7 @@ import { AppGachaData } from "@/data/index.js";
type GachaDataViewProps = {
dataType: "new" | "avatar" | "weapon" | "normal" | "mix";
dataVal: Array<TGApp.Sqlite.GachaRecords.TableGacha>;
dataVal: Array<TGApp.Sqlite.Gacha.Gacha>;
};
const props = defineProps<GachaDataViewProps>();
@@ -240,10 +240,10 @@ function getStar5Avg(): string {
/**
* 判断是否是Up物品
* @param {TGApp.Sqlite.GachaRecords.TableGacha} item 原始数据
* @param {TGApp.Sqlite.Gacha.Gacha} item 原始数据
* @returns {boolean|undefined}
*/
function checkIsUp(item: TGApp.Sqlite.GachaRecords.TableGacha): boolean | undefined {
function checkIsUp(item: TGApp.Sqlite.Gacha.Gacha): boolean | undefined {
// 新手池和常驻池不存在UP概念
if (item.gachaType === "100" || item.gachaType === "200") return undefined;
const itemTime = new Date(item.time).getTime();

View File

@@ -37,24 +37,24 @@ import { computed } from "vue";
import GroDataView from "./gro-data-view.vue";
type GachaOverviewProps = { modelValue: Array<TGApp.Sqlite.GachaRecords.TableGacha> };
type GachaOverviewProps = { modelValue: Array<TGApp.Sqlite.Gacha.Gacha> };
const props = defineProps<GachaOverviewProps>();
const swiperModules = [Autoplay, A11y, Pagination];
const newData = computed<Array<TGApp.Sqlite.GachaRecords.TableGacha>>(() =>
const newData = computed<Array<TGApp.Sqlite.Gacha.Gacha>>(() =>
props.modelValue.filter((item) => item.uigfType === "100"),
);
const normalData = computed<Array<TGApp.Sqlite.GachaRecords.TableGacha>>(() =>
const normalData = computed<Array<TGApp.Sqlite.Gacha.Gacha>>(() =>
props.modelValue.filter((item) => item.uigfType === "200"),
);
const avatarData = computed<Array<TGApp.Sqlite.GachaRecords.TableGacha>>(() =>
const avatarData = computed<Array<TGApp.Sqlite.Gacha.Gacha>>(() =>
props.modelValue.filter((item) => item.uigfType === "301"),
);
const weaponData = computed<Array<TGApp.Sqlite.GachaRecords.TableGacha>>(() =>
const weaponData = computed<Array<TGApp.Sqlite.Gacha.Gacha>>(() =>
props.modelValue.filter((item) => item.uigfType === "302"),
);
const mixData = computed<Array<TGApp.Sqlite.GachaRecords.TableGacha>>(() =>
const mixData = computed<Array<TGApp.Sqlite.Gacha.Gacha>>(() =>
props.modelValue.filter((item) => item.uigfType === "500"),
);
</script>

View File

@@ -19,7 +19,7 @@
</v-data-table>
</template>
<script lang="ts" setup>
type GroTableProps = { modelValue: Array<TGApp.Sqlite.GachaRecords.TableGacha> };
type GroTableProps = { modelValue: Array<TGApp.Sqlite.Gacha.Gacha> };
const props = defineProps<GroTableProps>();

View File

@@ -1,9 +1,9 @@
<template>
<div class="user-gacha-history-card-comp">
<img
class="ug-his-banner"
:src="props.pool.banner"
alt="banner"
class="ug-his-banner"
@click="createPost(pool.postId)"
/>
<div class="ug-his-info">
@@ -37,6 +37,7 @@
<script lang="ts" setup>
import TItemBox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
import showSnackbar from "@comp/func/snackbar.js";
import gameEnum from "@enum/game.js";
import { createPost } from "@utils/TGWindow.js";
import { getWikiBrief, timestampToDate } from "@utils/toolFunc.js";
import { useRouter } from "vue-router";
@@ -46,6 +47,17 @@ type UgHisCardProps = { pool: TGApp.App.Gacha.PoolItem };
const router = useRouter();
const props = defineProps<UgHisCardProps>();
const gachaTypeList: ReadonlyArray<TGApp.App.Gacha.PoolGachaType> = [
TGApp.Game.Gacha.GachaType.AvatarUp,
TGApp.Game.Gacha.GachaType.AvatarUp2,
TGApp.Game.Gacha.GachaType.WeaponUp,
TGApp.Game.Gacha.GachaType.MixUp,
];
function isPoolGachaType(x: string): x is TGApp.App.Gacha.PoolGachaType {
return (<ReadonlyArray<string>>gachaTypeList).includes(x);
}
async function toWiki(id: number): Promise<void> {
const find = getWikiBrief(id);
if (!find) {
@@ -59,19 +71,23 @@ async function toWiki(id: number): Promise<void> {
await router.push({ name: "武器图鉴", params: { id: id.toString() } });
}
function getType(type: TGApp.App.Gacha.WishType): string {
switch (type) {
case 301:
return "角色活动祈愿";
case 400:
return "角色活动祈愿2";
case 302:
return "武器活动祈愿";
case 500:
return "集录祈愿";
default:
return `未知类型 ${type}`;
function getType(type: number): string {
const typeStr = type.toString();
if (isPoolGachaType(typeStr)) {
switch (typeStr) {
case gameEnum.gachaType.AvatarUp:
return "角色活动祈愿";
case gameEnum.gachaType.AvatarUp2:
return "角色活动祈愿2";
case gameEnum.gachaType.WeaponUp:
return "武器活动祈愿";
case gameEnum.gachaType.MixUp:
return "集录祈愿";
default:
return `未知类型 ${type}`;
}
}
return `未知类型 ${type}`;
}
function getTimeStr(pool: TGApp.App.Gacha.PoolItem): string {

View File

@@ -162,7 +162,7 @@ async function handleExportData(): Promise<void> {
data.value = tmpData;
}
function parseDataRaw(data: TGApp.Sqlite.GachaRecords.TableGacha[]): UgoUidItem {
function parseDataRaw(data: Array<TGApp.Sqlite.Gacha.Gacha>): UgoUidItem {
const timeList = data.map((item) => new Date(item.time).getTime());
return {
uid: data[0].uid,

View File

@@ -1,19 +1,22 @@
<template>
<div v-if="modelValue.length === 0">暂无数据</div>
<div v-if="worlds.length === 0">暂无数据</div>
<div v-else class="tur-wg-box">
<TurWorldSub v-for="area in modelValue" :key="area.id" :data="area" />
<TurWorldSub v-for="world in worlds" :key="world.id" :world />
</div>
</template>
<script lang="ts" setup>
import TurWorldSub from "./tur-world-sub.vue";
defineProps<{ modelValue: Array<TGApp.Sqlite.Record.WorldExplore> }>();
type TurWorldGridProps = { worlds: Array<TGApp.Sqlite.Record.WorldExplore> };
defineProps<TurWorldGridProps>();
</script>
<style lang="css" scoped>
.tur-wg-box {
position: relative;
display: grid;
width: 100%;
gap: 8px;
grid-template-columns: repeat(3, 0.33fr);
grid-template-columns: repeat(3, 0.34fr);
}
</style>

View File

@@ -1,24 +1,25 @@
<!-- 单地区探索数据 -->
<template>
<div class="tur-ws-box">
<div class="tur-ws-bg">
<TMiImg :ori="true" :src="data.bg" alt="bg" />
<TMiImg :ori="true" :src="world.bg" alt="bg" />
</div>
<div class="tur-ws-icon">
<TMiImg :src="icon" :ori="true" alt="icon" />
<TMiImg :src="world.iconLight" :ori="true" alt="icon" />
</div>
<div class="tur-ws-content">
<div class="tur-ws-title">
<span>{{ data.name }}</span>
<span v-if="data.offerings?.length === 1" class="tur-ws-sub">
<img :src="data.offerings[0].icon" alt="offer" />
<span>{{ data.offerings[0].name }}-</span>
<span>{{ data.offerings[0].level }}</span>
<span>{{ world.name }}</span>
<span v-if="world.offerings?.length === 1" class="tur-ws-sub">
<img :src="world.offerings[0].icon" alt="offer" />
<span>{{ world.offerings[0].name }}-</span>
<span>{{ world.offerings[0].level }}</span>
<span></span>
</span>
</div>
<div class="tur-ws-offerings" v-if="data.offerings && data.offerings.length > 1">
<div class="tur-ws-offerings" v-if="world.offerings && world.offerings.length > 1">
<span
v-for="(offer, idx) in data.offerings"
v-for="(offer, idx) in world.offerings"
:key="idx"
class="tur-ws-sub"
:title="offer.name + '-' + offer.level + '级'"
@@ -28,18 +29,18 @@
<span></span>
</span>
</div>
<div v-if="data.children.length === 0" class="tur-ws-sub">
<div v-if="world.children.length === 0" class="tur-ws-sub">
<span>探索度</span>
<span>{{ data.exploration / 10 }}</span>
<span>{{ world.exploration / 10 }}</span>
<span>%</span>
</div>
<div v-else>
<div v-if="data.exploration !== 0" class="tur-ws-sub">
<span>{{ data.name }}探索度</span>
<span>{{ data.exploration / 10 }}</span>
<div v-if="world.exploration !== 0" class="tur-ws-sub">
<span>{{ world.name }}探索度</span>
<span>{{ world.exploration / 10 }}</span>
<span>%</span>
</div>
<div v-for="item in data.children" :key="item.id" class="tur-ws-sub">
<div v-for="item in world.children" :key="item.id" class="tur-ws-sub">
<span>{{ item.name }}探索度</span>
<span>{{ item.exploration / 10 }}</span>
<span>%</span>
@@ -47,14 +48,14 @@
</div>
<div
v-if="
data.area_exploration_list &&
data.area_exploration_list.length > 0 &&
data.exploration < 1000
world.area_exploration_list &&
world.area_exploration_list.length > 0 &&
world.exploration < 1000
"
class="tur-ws-areas"
>
<span
v-for="area in data.area_exploration_list.filter((i) => i.exploration_percentage < 1000)"
v-for="area in world.area_exploration_list.filter((i) => i.exploration_percentage < 1000)"
:key="area.name"
class="tur-ws-sub"
>
@@ -63,9 +64,9 @@
<span>%</span>
</span>
</div>
<div v-if="data.reputation" class="tur-ws-sub">
<div v-if="world.reputation" class="tur-ws-sub">
<span>声望等级:</span>
<span>{{ data.reputation }}</span>
<span>{{ world.reputation }}</span>
<span>级</span>
</div>
</div>
@@ -77,19 +78,16 @@ import useAppStore from "@store/app.js";
import { storeToRefs } from "pinia";
import { computed } from "vue";
type TurWorldSubProps = { data: TGApp.Sqlite.Record.WorldExplore };
type TurWorldSubProps = { world: TGApp.Sqlite.Record.WorldExplore };
const { theme } = storeToRefs(useAppStore());
const props = defineProps<TurWorldSubProps>();
defineProps<TurWorldSubProps>();
const imgFilter = computed<string>(() => {
if (theme.value === "dark") return "none";
return "invert(0.75)";
});
const icon = computed<string>(() => {
if (props.data.icon) return props.data.icon;
return props.data.iconLight;
});
</script>
<style lang="scss" scoped>
.tur-ws-box {

View File

@@ -254,7 +254,7 @@ async function refreshState(ck: TGApp.App.Account.Cookie): Promise<void> {
}
}
async function trySign(ac: SignAccount[], ck: TGApp.App.Account.Cookie): Promise<void> {
async function trySign(ac: Array<SignAccount>, ck: TGApp.App.Account.Cookie): Promise<void> {
const cookie = { cookie_token: ck.cookie_token, account_id: ck.account_id };
const ckSign = { stoken: ck.stoken, stuid: ck.stuid, mid: ck.mid };
for (const item of ac) {

View File

@@ -103,7 +103,7 @@ function miniImgUrl(): string {
}
function getImageTitle(): string {
const res: string[] = [];
const res: Array<string> = [];
if (props.data.attributes) {
res.push(`宽度:${props.data.attributes.width}px`);
res.push(`高度:${props.data.attributes.height}px`);

View File

@@ -57,11 +57,11 @@ type TpVillaCard = {
owner_nickname: string;
owner_avatar_url: string;
villa_introduce?: string;
tag_list?: string[];
tag_list?: Array<string>;
villa_member_num: string;
is_official?: boolean;
is_available: boolean;
hot_member_avatar?: string[];
hot_member_avatar?: Array<string>;
hot_room?: VillaRoom;
};
};

View File

@@ -78,7 +78,7 @@ onMounted(async () => {
const voteInfo = await ApiHubReq.vote.info(vote.id, vote.uid);
console.log(`[${props.data.insert.vote.id}]voteInfo:`, voteInfo);
const voteResult = await ApiHubReq.vote.result(vote.id, vote.uid);
console.log("[${props.data.insert.vote.id}]voteResult:", voteResult);
console.log(`[${props.data.insert.vote.id}]voteResult:`, voteResult);
votes.value = {
title: voteInfo.title,
count: voteResult.user_cnt,

View File

@@ -26,7 +26,7 @@ type TbCollectProps = { modelValue: number; data?: TGApp.BBS.Post.FullData };
const props = defineProps<TbCollectProps>();
const isCollected = ref<boolean>(false);
const showEdit = ref<boolean>(false);
const collect = shallowRef<Array<TGApp.Sqlite.UserCollection.UFMap>>([]);
const collect = shallowRef<Array<TGApp.Sqlite.Collection.PcMap>>([]);
onBeforeMount(async () => await refresh());

View File

@@ -46,8 +46,8 @@ const props = defineProps<ToPostCollectProps>();
const emits = defineEmits<ToPostCollectEmits>();
const visible = defineModel<boolean>();
const submit = ref<boolean>(false);
const collectList = shallowRef<Array<TGApp.Sqlite.UserCollection.UFCollection>>([]);
const postCollect = shallowRef<Array<TGApp.Sqlite.UserCollection.UFMap>>([]);
const collectList = shallowRef<Array<TGApp.Sqlite.Collection.Collection>>([]);
const postCollect = shallowRef<Array<TGApp.Sqlite.Collection.PcMap>>([]);
const selectList = shallowRef<Array<string>>([]);
watch(
@@ -72,7 +72,7 @@ async function freshData(): Promise<void> {
}
}
async function deleteCollect(item: TGApp.Sqlite.UserCollection.UFCollection): Promise<void> {
async function deleteCollect(item: TGApp.Sqlite.Collection.Collection): Promise<void> {
const delCheck = await showDialog.check("确定删除分类?", "该分类若有帖子,则会变为未分类");
if (!delCheck) {
showSnackbar.cancel("取消删除");