💄 样式美化

This commit is contained in:
BTMuli
2026-04-11 16:28:10 +08:00
parent 02858f3da7
commit f3c3408d71
14 changed files with 341 additions and 246 deletions

View File

@@ -19,10 +19,11 @@
</div>
<div v-else class="dn-container">
<PhDailyNoteItem
v-for="item in dailyNoteAccounts"
v-for="item in sortedDailyNoteAccounts"
:key="`${item.account.gameBiz}_${item.account.gameUid}`"
:account="item.account"
:data="item.data"
:cur="item.account.gameUid === currentGameUid"
@refresh="handleRefresh(item.account)"
/>
</div>
@@ -37,7 +38,7 @@ import useAppStore from "@store/app.js";
import useUserStore from "@store/user.js";
import TGLogger from "@utils/TGLogger.js";
import { storeToRefs } from "pinia";
import { onMounted, ref, watch } from "vue";
import { computed, onMounted, ref, watch } from "vue";
import THomeCard from "./ph-comp-card.vue";
import PhDailyNoteItem from "./ph-daily-note-item.vue";
@@ -54,7 +55,7 @@ type TDailyNoteEmits = {
};
const emits = defineEmits<TDailyNoteEmits>();
const { cookie, uid, briefInfo } = storeToRefs(useUserStore());
const { cookie, uid, briefInfo, account } = storeToRefs(useUserStore());
const { isLogin } = storeToRefs(useAppStore());
const loading = ref<boolean>(false);
@@ -63,6 +64,19 @@ const loadingText = ref<string>("");
const gameAccounts = ref<Array<TGApp.Sqlite.Account.Game>>([]);
const dailyNoteAccounts = ref<Array<DailyNoteAccount>>([]);
const currentGameUid = computed(() => account.value?.gameUid || "");
const sortedDailyNoteAccounts = computed(() => {
if (!currentGameUid.value) return dailyNoteAccounts.value;
return [...dailyNoteAccounts.value].sort((a, b) => {
const aIsCurrent = a.account.gameUid === currentGameUid.value;
const bIsCurrent = b.account.gameUid === currentGameUid.value;
if (aIsCurrent && !bIsCurrent) return -1;
if (!aIsCurrent && bIsCurrent) return 1;
return 0;
});
});
watch(
() => uid.value,
async () => await loadData(),

View File

@@ -34,7 +34,7 @@ const max = computed((): number => {
display: flex;
width: 100%;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 4px;
@@ -65,7 +65,6 @@ const max = computed((): number => {
.pdb-boss-title {
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}

View File

@@ -1,6 +1,6 @@
<!-- 洞天宝钱显示组件 -->
<template>
<div class="ph-dnc-box">
<div :class="{ 'ph-dnc-max': full }" class="ph-dnc-box">
<div class="pdb-coin-icon">
<img alt="洞天宝钱" src="/UI/daily/coin.webp" />
</div>
@@ -16,7 +16,7 @@
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
import { stamp2LastTime } from "@utils/toolFunc.js";
@@ -32,6 +32,7 @@ const current = ref<number>(0);
const max = ref<number>(0);
const remainedTime = ref<number>(0);
const formattedTime = ref<string>("");
const full = computed<boolean>(() => current.value === max.value);
let timer: ReturnType<typeof setInterval> | null = null;
@@ -44,6 +45,15 @@ onUnmounted(() => {
stopTimer();
});
watch(
() => props.recoveryTime,
() => {
initTime();
stopTimer();
startTimer();
},
);
function initTime(): void {
current.value = props.currentCoin || 0;
max.value = props.maxCoin || 0;
@@ -85,10 +95,15 @@ function updateFormattedTime(): void {
display: flex;
width: 100%;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 6px;
gap: 4px;
transition: all 0.3s ease;
&.ph-dnc-max {
background: linear-gradient(135deg, var(--tgc-od-orange) 0%, var(--box-bg-2) 80%);
}
}
.pdb-coin-icon {
@@ -119,7 +134,6 @@ function updateFormattedTime(): void {
justify-content: space-between;
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}

View File

@@ -1,15 +1,18 @@
<!-- 探索派遣单项 -->
<template>
<div class="dni-exp-item">
<div :class="{ empty: expedition.status === dnEnum.expedition.EMPTY }" class="dni-exp-item">
<div class="dni-exp-icon">
<img :src="expedition.avatar_side_icon" alt="角色" />
</div>
<div class="dni-exp-info">
<div v-if="isFinished" class="dni-exp-status finished">已完成</div>
<div v-else class="dni-exp-info-content">
<div v-if="expedition.status === dnEnum.expedition.FINISHED" class="dni-exp-status finished">
已完成
</div>
<div v-else-if="expedition.status === dnEnum.expedition.ONGOING" class="dni-exp-info-content">
<div class="dni-exp-status">派遣中</div>
<div class="dni-exp-time">{{ formattedTime }}</div>
</div>
<div v-else class="dni-exp-status empty">未派遣</div>
</div>
</div>
</template>
@@ -18,6 +21,8 @@ import { onMounted, onUnmounted, ref, watch } from "vue";
import { stamp2LastTime } from "@utils/toolFunc.js";
import dnEnum from "@enum/dailyNote";
type PhDailyNoteExpeditionProps = {
expedition: TGApp.Game.DailyNote.Expedition;
};
@@ -51,7 +56,8 @@ watch(
function initTime(): void {
const time = props.expedition.remained_time;
remainedTime.value = typeof time === "string" ? parseInt(time) : time;
isFinished.value = props.expedition.status === "Finished" || remainedTime.value <= 0;
isFinished.value =
props.expedition.status === dnEnum.expedition.FINISHED || remainedTime.value <= 0;
updateFormattedTime();
}
@@ -94,10 +100,16 @@ function updateFormattedTime(): void {
width: fit-content;
height: 32px;
align-items: center;
padding-right: 12px;
justify-content: flex-start;
padding-right: 14px;
border-radius: 20px;
background: linear-gradient(to right, var(--box-bg-2), transparent 120%);
gap: 6px;
background: linear-gradient(to right, var(--box-bg-2) 32px, var(--box-bg-1) 100%);
column-gap: 4px;
&.empty {
background: var(--box-bg-2);
opacity: 0.5;
}
}
.dni-exp-icon {
@@ -107,7 +119,7 @@ function updateFormattedTime(): void {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--box-bg-4);
background: transparent;
img {
width: 100%;
@@ -126,18 +138,23 @@ function updateFormattedTime(): void {
position: relative;
display: flex;
flex-direction: column;
line-height: 1;
}
.dni-exp-status {
overflow: hidden;
color: var(--box-text-2);
color: var(--tgc-od-orange);
font-size: 10px;
font-weight: bold;
text-overflow: ellipsis;
white-space: nowrap;
&.finished {
color: var(--tgc-od-green);
font-weight: bold;
}
&.empty {
color: var(--tgc-od-white);
}
}

View File

@@ -1,12 +1,13 @@
<!-- 实时便笺单项 -->
<template>
<div class="dni-container">
<div :class="{ 'dni-current': cur }" class="dni-container">
<div class="dni-header">
<div class="dni-header-title">
<span>{{ props.account.nickname }}</span>
<v-icon
:size="16"
color="var(--tgc-od-orange)"
data-html2canvas-ignore
icon="mdi-refresh"
variant="elevated"
@click="handleRefresh"
@@ -17,7 +18,6 @@
<span>{{ props.account.regionName }}</span>
</div>
</div>
<div v-if="props.data" class="dni-content">
<div class="dni-grid">
<div class="dni-row">
@@ -42,18 +42,8 @@
/>
</div>
</div>
<div class="dni-exp-header">
<span class="dni-exp-title">探索派遣</span>
<span class="dni-exp-count">
{{ props.data.current_expedition_num }}/{{ props.data.max_expedition_num }}
</span>
</div>
<div class="dni-exp-grid">
<PhDailyNoteExpedition
v-for="expedition in props.data.expeditions"
:key="expedition.avatar_side_icon"
:expedition="expedition"
/>
<PhDailyNoteExpedition v-for="(expedition, i) in expeditions" :key="i" :expedition />
</div>
</div>
</div>
@@ -66,10 +56,13 @@ import PhDailyNoteTransformer from "./ph-daily-note-transformer.vue";
import PhDailyNoteTask from "./ph-daily-note-task.vue";
import PhDailyNoteQuest from "./ph-daily-note-quest.vue";
import PhDailyNoteBoss from "./ph-daily-note-boss.vue";
import { computed } from "vue";
import dnEnum from "@enum/dailyNote.js";
type PhDailyNoteItemProps = {
account: TGApp.Sqlite.Account.Game;
data?: TGApp.Game.DailyNote.DnRes;
cur?: boolean;
};
type TDailyNoteItemEmits = {
@@ -77,7 +70,24 @@ type TDailyNoteItemEmits = {
};
const emits = defineEmits<TDailyNoteItemEmits>();
const props = defineProps<PhDailyNoteItemProps>();
const props = withDefaults(defineProps<PhDailyNoteItemProps>(), {
cur: false,
});
const expeditions = computed<Array<TGApp.Game.DailyNote.Expedition>>(() => {
if (!props.data) return [];
let res: Array<TGApp.Game.DailyNote.Expedition> = [];
res.push(...props.data.expeditions);
if (res.length < props.data.max_expedition_num) {
for (let i = 0; i < props.data.max_expedition_num - res.length; i++) {
res.push({
avatar_side_icon: "/UI/app/empty.webp",
status: dnEnum.expedition.EMPTY,
remained_time: "0",
});
}
}
return res;
});
function handleRefresh(): void {
emits("refresh");
@@ -90,11 +100,15 @@ function handleRefresh(): void {
width: 100%;
flex-direction: column;
padding: 8px;
border: 1px solid var(--common-shadow-2);
border-radius: 4px;
background: var(--box-bg-1);
color: var(--box-text-1);
gap: 6px;
gap: 4px;
transition: border-color 0.3s ease;
&.dni-current {
border: 1px solid var(--common-shadow-2);
}
}
.dni-header {
@@ -103,7 +117,7 @@ function handleRefresh(): void {
width: 100%;
align-items: center;
justify-content: space-between;
padding-bottom: 6px;
padding-bottom: 4px;
border-bottom: 1px solid var(--common-shadow-1);
}
@@ -125,6 +139,7 @@ function handleRefresh(): void {
.dni-content {
display: flex;
height: 100%;
flex-direction: column;
gap: 8px;
}
@@ -132,12 +147,12 @@ function handleRefresh(): void {
.dni-grid {
display: flex;
flex-direction: column;
gap: 6px;
gap: 4px;
}
.dni-row {
display: grid;
gap: 6px;
gap: 4px;
grid-template-columns: repeat(3, 1fr);
}
@@ -147,10 +162,10 @@ function handleRefresh(): void {
width: 100%;
height: 100%;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 6px;
gap: 4px;
}
.dni-icon {
@@ -177,60 +192,21 @@ function handleRefresh(): void {
gap: 2px;
}
.dni-title {
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}
.dni-desc {
overflow: hidden;
color: var(--box-text-2);
font-size: 10px;
line-height: 1.2;
text-overflow: ellipsis;
white-space: nowrap;
}
.dni-value {
position: relative;
display: flex;
flex-shrink: 0;
align-items: center;
padding: 4px 8px;
border-radius: 4px;
background: var(--box-bg-3);
font-size: 12px;
font-weight: bold;
white-space: nowrap;
}
.dni-exp-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 4px;
margin-top: auto;
gap: 8px;
}
.dni-exp-title {
color: var(--box-text-1);
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
}
.dni-exp-count {
color: var(--box-text-2);
font-size: 11px;
}
.dni-exp-grid {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
margin-top: auto;
column-gap: 12px;
}

View File

@@ -15,39 +15,56 @@
}}
</span>
</div>
<div class="pdb-quest-desc">
<span v-for="q in props.quest.list" :key="q.id">
{{ q.chapter_num }} {{ q.chapter_title }} {{ getQuestStatus(q.status) }}
<div class="pdb-quest-chips">
<span
v-for="q in questList"
:key="q.id"
:class="getQuestClass(q.status)"
:title="q.chapter_num"
class="pdb-quest-chip"
>
{{ q.chapter_title }}
</span>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import dnEnum from "@enum/dailyNote";
type PhDailyNoteQuestProps = { quest: TGApp.Game.DailyNote.ArchonQuestProgress };
const props = defineProps<PhDailyNoteQuestProps>();
function getQuestStatus(stat: string): string {
const questList = computed(() => props.quest.list);
function getQuestClass(stat: TGApp.Game.DailyNote.ArchonStatusEnum): string {
switch (stat) {
case "StatusNotOpen":
return "未开启";
case dnEnum.quest.FINISHED:
return "finished";
case dnEnum.quest.ONGOING:
return "ongoing";
case dnEnum.quest.NOT_OPEN:
return "not-open";
default:
return stat;
return "";
}
}
</script>
<style lang="scss" scoped>
@use "@styles/github.styles.scss" as github-styles;
.ph-dnq-box {
position: relative;
display: flex;
width: 100%;
min-height: 64px;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 6px;
gap: 4px;
}
.pdb-quest-icon {
@@ -80,31 +97,35 @@ function getQuestStatus(stat: string): string {
justify-content: space-between;
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}
.pdb-quest-desc {
.pdb-quest-chips {
display: flex;
overflow: hidden;
flex-direction: column;
color: var(--box-text-2);
font-size: 10px;
line-height: 1.2;
text-overflow: ellipsis;
white-space: nowrap;
flex-wrap: wrap;
gap: 4px;
}
.pdb-quest-value {
position: relative;
display: flex;
flex-shrink: 0;
.pdb-quest-chip {
display: inline-flex;
align-items: center;
padding: 4px 8px;
border-radius: 4px;
background: var(--box-bg-3);
font-size: 12px;
font-weight: bold;
padding: 1px 4px;
border-radius: 10px;
font-size: 10px;
line-height: 1.2;
white-space: nowrap;
&.finished {
@include github-styles.github-tag-dark-gen(#98c379ff);
}
&.ongoing {
@include github-styles.github-tag-dark-gen(#d19a66ff);
}
&.not-open {
@include github-styles.github-tag-dark-gen(#e06c75ff);
}
}
</style>

View File

@@ -1,6 +1,6 @@
<!-- 原粹树脂显示组件 -->
<template>
<div class="ph-dnr-box">
<div :class="{ 'ph-dnr-max': full }" class="ph-dnr-box">
<div class="pdb-resin-icon">
<img alt="原粹树脂" src="/UI/daily/resin.webp" />
</div>
@@ -16,7 +16,7 @@
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
import { stamp2LastTime } from "@utils/toolFunc.js";
@@ -29,9 +29,11 @@ type PhDailyNoteResinProps = {
const props = defineProps<PhDailyNoteResinProps>();
const current = ref<number>(0);
const max = ref<number>(0);
const remainedTime = ref<number>(0);
const formattedTime = ref<string>("");
const initialRecoveryTime = ref<number>(0);
const max = computed<number>(() => props.maxResin ?? 200);
const full = computed<boolean>(() => current.value === max.value);
let timer: ReturnType<typeof setInterval> | null = null;
@@ -44,11 +46,20 @@ onUnmounted(() => {
stopTimer();
});
watch(
() => props.recoveryTime,
() => {
initTime();
stopTimer();
startTimer();
},
);
function initTime(): void {
current.value = props.currentResin || 0;
max.value = props.maxResin || 0;
const time = props.recoveryTime;
remainedTime.value = typeof time === "string" ? parseInt(time) : time || 0;
initialRecoveryTime.value = remainedTime.value;
updateFormattedTime();
}
@@ -59,10 +70,8 @@ function startTimer(): void {
if (remainedTime.value > 0) {
remainedTime.value -= 1;
updateFormattedTime();
// 每 9 分钟恢复 1 点树脂
const totalSecondsPassed =
(props.recoveryTime ? parseInt(props.recoveryTime) : 0) - remainedTime.value;
const resinToRecover = Math.floor(totalSecondsPassed / 540); // 540 秒 = 9 分钟
const totalSecondsPassed = initialRecoveryTime.value - remainedTime.value;
const resinToRecover = Math.floor(totalSecondsPassed / 540);
const newCurrent = Math.min(current.value + resinToRecover, max.value);
if (newCurrent !== current.value) {
current.value = newCurrent;
@@ -93,10 +102,15 @@ function updateFormattedTime(): void {
display: flex;
width: 100%;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 6px;
gap: 4px;
transition: all 0.3s ease;
&.ph-dnr-max {
background: linear-gradient(135deg, var(--tgc-od-orange) 0%, var(--box-bg-2) 80%);
}
}
.pdb-resin-icon {
@@ -127,7 +141,6 @@ function updateFormattedTime(): void {
justify-content: space-between;
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}

View File

@@ -15,52 +15,11 @@
<span>{{ task.stored_attendance }}</span>
</div>
</div>
<div class="pdb-task-task-content">
<div class="pdb-task-task-row">
<span class="pdb-task-task-label">日常</span>
<template v-for="i in props.task?.task_rewards" :key="i">
<v-icon
v-if="i.status === 'TaskRewardStatusFinished'"
color="var(--tgc-od-green)"
size="14"
>
mdi-check
</v-icon>
<v-icon v-else color="var(--tgc-od-white)" size="14"> mdi-square-outline</v-icon>
</template>
</div>
<div v-if="attendanceVisible" class="pdb-task-task-row">
<span class="pdb-task-task-label">历练</span>
<div class="pdb-task-attendance-list">
<div
v-for="reward in attendanceRewards"
:key="reward.progress"
class="pdb-task-attendance-item"
>
<v-progress-circular
:model-value="(Math.min(reward.progress, 2000) / 2000) * 100"
:size="14"
:width="2"
class="pdb-task-attendance-progress"
color="var(--tgc-od-orange)"
/>
<span
v-if="reward.status !== 'AttendanceRewardStatusUnfinished'"
class="pdb-task-attendance-icon"
>
<v-icon
v-if="reward.status === 'AttendanceRewardStatusTakenAward'"
color="var(--tgc-od-green)"
size="8"
>
mdi-check
</v-icon>
<v-icon v-else color="var(--tgc-od-red)" size="8"> mdi-gift </v-icon>
</span>
</div>
</div>
<span v-if="hasUnclaimedAttendance" class="pdb-task-task-warn"> 可领取 </span>
</div>
<div class="pdb-task-content">
<PhDnTr v-for="(reward, i) in props.task?.task_rewards" :key="i" :reward />
<template v-if="attendanceVisible">
<PhDnAr v-for="(reward, i) in props.task?.attendance_rewards" :key="i" :reward="reward" />
</template>
</div>
</div>
<div class="pdb-task-value"></div>
@@ -68,6 +27,8 @@
</template>
<script lang="ts" setup>
import { computed } from "vue";
import PhDnTr from "./ph-dn-tr.vue";
import PhDnAr from "@comp/pageHome/ph-dn-ar.vue";
type PhDailyNoteTaskProps = {
task?: TGApp.Game.DailyNote.DailyTask;
@@ -79,18 +40,6 @@ const attendanceVisible = computed((): boolean => {
return props.task?.attendance_visible ?? false;
});
const attendanceRewards = computed((): Array<TGApp.Game.DailyNote.AttendanceReward> => {
return props.task?.attendance_rewards ?? [];
});
const hasUnclaimedAttendance = computed((): boolean => {
return (
props.task?.attendance_rewards?.some(
(r) => r.progress >= 2000 && r.status !== "AttendanceRewardStatusTakenAward",
) ?? false
);
});
const taskStatus = computed((): string => {
if (!props.task) return "";
const { finished_num, total_num } = props.task;
@@ -106,12 +55,11 @@ const taskStatus = computed((): string => {
position: relative;
display: flex;
width: 100%;
min-height: 64px;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 6px;
gap: 4px;
}
.pdb-task-icon {
@@ -152,70 +100,14 @@ const taskStatus = computed((): string => {
column-gap: 4px;
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}
.pdb-task-task-content {
display: flex;
flex-direction: column;
gap: 2px;
}
.pdb-task-task-row {
display: flex;
align-items: center;
gap: 4px;
}
.pdb-task-task-label {
color: var(--box-text-2);
font-size: 10px;
white-space: nowrap;
}
.pdb-task-task-warn {
color: var(--tgc-od-orange);
font-size: 10px;
font-weight: bold;
white-space: nowrap;
}
.pdb-task-attendance-list {
display: flex;
align-items: center;
column-gap: 2px;
}
.pdb-task-attendance-item {
.pdb-task-content {
position: relative;
display: flex;
width: 16px;
height: 16px;
align-items: center;
justify-content: center;
}
.pdb-task-attendance-progress {
position: absolute;
z-index: 1;
}
.pdb-task-attendance-icon {
position: absolute;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
}
.pdb-task-attendance-progress-text {
position: absolute;
z-index: 2;
color: var(--box-text-1);
font-size: 8px;
font-weight: bold;
white-space: nowrap;
justify-content: flex-start;
}
.pdb-task-stored {

View File

@@ -1,6 +1,6 @@
<!-- 参量质变仪显示组件 -->
<template>
<div class="ph-dnt-box">
<div :class="{ 'ph-dnt-ready': ready }" class="ph-dnt-box">
<div class="pdb-trans-icon">
<img alt="参量质变仪" src="/UI/daily/trans.webp" />
</div>
@@ -13,7 +13,7 @@
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
import { stamp2LastTime } from "@utils/toolFunc.js";
@@ -28,7 +28,7 @@ const formattedTime = ref<string>("");
let timer: ReturnType<typeof setInterval> | null = null;
const valueText = computed((): string => {
const valueText = computed<string>(() => {
if (!props.trans.obtained && !props.trans.recovery_time.reached) {
return "恢复中";
}
@@ -37,6 +37,7 @@ const valueText = computed((): string => {
}
return formattedTime.value;
});
const ready = computed<boolean>(() => props.trans.obtained || props.trans.recovery_time.reached);
onMounted(() => {
initTime();
@@ -47,6 +48,16 @@ onUnmounted(() => {
stopTimer();
});
watch(
() => props.trans.recovery_time,
() => {
initTime();
stopTimer();
startTimer();
},
{ deep: true },
);
function initTime(): void {
const time = props.trans.recovery_time;
if (time) {
@@ -93,10 +104,15 @@ function updateFormattedTime(): void {
display: flex;
width: 100%;
align-items: center;
padding: 6px;
padding: 4px;
border-radius: 4px;
background: var(--box-bg-2);
gap: 6px;
gap: 4px;
transition: all 0.3s ease;
&.ph-dnt-ready {
background: linear-gradient(135deg, var(--tgc-od-orange) 0%, var(--box-bg-2) 80%);
}
}
.pdb-trans-icon {
@@ -124,7 +140,6 @@ function updateFormattedTime(): void {
.pdb-trans-title {
font-family: var(--font-title);
font-size: 13px;
font-weight: bold;
white-space: nowrap;
}

View File

@@ -0,0 +1,99 @@
<!-- ph-daily-note-attendance-reward -->
<template>
<div :class="{ non: isNon }" class="ph-dn-ar-box">
<v-progress-circular
:color="proc"
:model-value="(Math.min(props.reward.progress, 2000) / 2000) * 100"
:size="14"
:width="2"
class="ph-dn-ar-progress"
/>
<span v-if="reward.status !== dnEnum.attendance.UNFINISHED" class="ph-dn-ar-icon">
<v-icon :color="proc" size="8">
{{ midIcon }}
</v-icon>
</span>
</div>
</template>
<script lang="ts" setup>
import dnEnum from "@enum/dailyNote.js";
import { computed } from "vue";
type PhDnArProps = { reward: TGApp.Game.DailyNote.AttendanceReward };
const props = defineProps<PhDnArProps>();
const proc = computed<string>(() => {
switch (props.reward.status) {
case dnEnum.attendance.INVALID:
case dnEnum.attendance.NON_REWARD:
return "var(--tgc-od-white)";
case dnEnum.attendance.UNFINISHED:
return "var(--tgc-od-blue)";
case dnEnum.attendance.TAKEN:
return "var(--tgc-od-green)";
case dnEnum.attendance.WAIT_TAKEN:
return "var(--tgc-od-red)";
case dnEnum.attendance.FORBID:
return "var(--tgc-od-orange)";
default:
return "var(--tgc-od-white)";
}
});
const isNon = computed<boolean>(() => {
switch (props.reward.status) {
case dnEnum.attendance.INVALID:
case dnEnum.attendance.NON_REWARD:
case dnEnum.attendance.FORBID:
return true;
case dnEnum.attendance.UNFINISHED:
case dnEnum.attendance.TAKEN:
case dnEnum.attendance.WAIT_TAKEN:
return false;
default:
return true;
}
});
const midIcon = computed<string>(() => {
switch (props.reward.status) {
case dnEnum.attendance.INVALID:
return "mdi-close";
case dnEnum.attendance.NON_REWARD:
return "mdi-cancel";
case dnEnum.attendance.TAKEN:
return "mdi-check";
case dnEnum.attendance.WAIT_TAKEN:
return "mdi-gift";
case dnEnum.attendance.FORBID:
return "mdi-cancel";
case dnEnum.attendance.UNFINISHED:
default:
return "mdi-info";
}
});
</script>
<style lang="scss" scoped>
.ph-dn-ar-box {
position: relative;
display: flex;
width: 16px;
height: 16px;
align-items: center;
justify-content: center;
&.non {
opacity: 0.5;
}
}
.ph-dn-ar-progress {
position: absolute;
z-index: 1;
}
.ph-dn-ar-icon {
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@@ -0,0 +1,32 @@
<!-- ph-daily-note-task-reward -->
<template>
<v-icon
opacity="0.5"
v-if="props.reward.status === dnEnum.task.INVALID"
color="var(--tgc-od-white)"
size="16"
>
mdi-cancel
</v-icon>
<v-icon
v-else-if="props.reward.status === dnEnum.task.UNFINISHED"
color="var(--tgc-od-white)"
size="16"
>
mdi-checkbox-blank-badge-outline
</v-icon>
<v-icon
v-else-if="props.reward.status === dnEnum.task.FINISHED"
color="var(--tgc-od-red)"
size="16"
>
mdi-gift
</v-icon>
<v-icon v-else color="var(--tgc-od-green)" size="16"> mdi-checkbox-marked-outline </v-icon>
</template>
<script lang="ts" setup>
import dnEnum from "@enum/dailyNote.js";
type PhDnTrProps = { reward: TGApp.Game.DailyNote.DailyTaskReward };
const props = defineProps<PhDnTrProps>();
</script>

View File

@@ -11,6 +11,7 @@
const ExpeditionStatusEnum: typeof TGApp.Game.DailyNote.ExpeditionStatus = {
ONGOING: "Ongoing",
FINISHED: "Finished",
EMPTY: "Empty",
};
/**

View File

@@ -628,9 +628,9 @@ function isFinTarot(data: TGApp.Sqlite.Combat.TableTrans): boolean {
}
.uc-window-item {
overflow: hidden auto;
height: 100%;
padding-right: 8px;
overflow: hidden auto;
}
.ucw-i-ref {

View File

@@ -202,6 +202,8 @@ declare namespace TGApp.Game.DailyNote {
const ExpeditionStatus = <const>{
ONGOING: "Ongoing",
FINISHED: "Finished",
/** 自定义状态 */
EMPTY: "Empty",
};
/**