mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-03-28 05:59:46 +08:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8bd4be8ea | ||
|
|
bd37e3e491 | ||
|
|
286c1e2459 | ||
|
|
b3b3eae57c | ||
|
|
3235545a02 | ||
|
|
ddbc382b8b | ||
|
|
58e99467ae | ||
|
|
10b184950d | ||
|
|
17eb6cc001 | ||
|
|
ae68653938 | ||
|
|
aabb9776d4 | ||
|
|
fd47ebe7c1 | ||
|
|
1a27dc5f02 | ||
|
|
8062935b2c |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -2,12 +2,27 @@
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2025-09-09
|
||||
Update: 2025-09-09
|
||||
Update: 2025-09-11
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2025-09-09 14:30:56`
|
||||
>
|
||||
> 更新于 `2025-09-09 15:18:01`
|
||||
> 更新于 `2025-09-11 13:38:00`
|
||||
|
||||
## [0.8.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.8.1) (2025-09-11)
|
||||
|
||||
- 🍱 添加月神瞳数据&资源
|
||||
- ♻️ 战绩世界探索数据结构调整,增加数据显示
|
||||
- 🐛 修复战绩显示异常
|
||||
- 🐛 首页活动组件隐藏未开始活动,修复未开始活动时间显示异常
|
||||
- 🐛 修复材料浮窗分享图生成异常
|
||||
- 🐛 角色简略视图修复天赋显示异常,增加是否解锁显示
|
||||
- 🐛 修复角色天赋/技能描述显示异常
|
||||
- 🚸 调整名片Wiki页面,支持按类型筛选
|
||||
- 🚸 微调签到奖励交互效果
|
||||
- 💄 优化名片UI
|
||||
- 💄 优化成就项UI
|
||||
- 💄 调整材料图鉴顶部样式,保持UI一致性
|
||||
|
||||
## [0.8.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.8.0) (2025-09-09)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "teyvatguide",
|
||||
"version": "0.8.0",
|
||||
"version": "0.8.1",
|
||||
"description": "Game Tool for GenshinImpact player",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.15.1",
|
||||
|
||||
BIN
public/icon/material/107030.webp
Normal file
BIN
public/icon/material/107030.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -4,7 +4,7 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "TeyvatGuide"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "TeyvatGuide"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
description = "Game Tool for Genshin Impact player"
|
||||
authors = ["BTMuli <bt-muli@outlook.com>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "TeyvatGuide",
|
||||
"identifier": "TeyvatGuide",
|
||||
"version": "0.8.0",
|
||||
"version": "0.8.1",
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm vite:dev",
|
||||
"beforeBuildCommand": "pnpm vite:build",
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
<span>{{ parseNameCard(props.data.desc) }}</span>
|
||||
<span>获取途径:{{ props.data.source }}</span>
|
||||
</div>
|
||||
<div class="ton-type" :title="`ID:${props.data.id}`">{{ props.data.type }}</div>
|
||||
<TwnTypeTag :type="props.data.type" class="ton-type" />
|
||||
<div class="ton-sign">ID:{{ props.data.id }} | TeyvatGuide v{{ version }}</div>
|
||||
<v-btn
|
||||
class="ton-share"
|
||||
@click="shareNameCard"
|
||||
@@ -32,8 +33,10 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TwnTypeTag from "@comp/pageWiki/twn-type-tag.vue";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { generateShareImg } from "@utils/TGShare.js";
|
||||
import { ref } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import TOverlay from "./t-overlay.vue";
|
||||
|
||||
@@ -42,6 +45,11 @@ type ToNameCardProps = { data?: TGApp.App.NameCard.Item };
|
||||
const props = defineProps<ToNameCardProps>();
|
||||
const visible = defineModel<boolean>();
|
||||
const loading = ref<boolean>(false);
|
||||
const version = ref<string>("");
|
||||
|
||||
onMounted(async () => {
|
||||
version.value = await getVersion();
|
||||
});
|
||||
|
||||
function parseNameCard(desc: string): string {
|
||||
let array = [];
|
||||
@@ -141,16 +149,6 @@ async function shareNameCard(): Promise<void> {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ton-type {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
padding: 0 4px;
|
||||
border: 1px solid var(--tgc-white-1);
|
||||
border-radius: 4px;
|
||||
color: var(--tgc-white-1);
|
||||
}
|
||||
|
||||
.ton-content {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
@@ -167,27 +165,42 @@ async function shareNameCard(): Promise<void> {
|
||||
backdrop-filter: blur(5px);
|
||||
background: #00000040;
|
||||
color: var(--tgc-white-1);
|
||||
|
||||
:first-child {
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
text-shadow: 0 0 5px #000000cc;
|
||||
}
|
||||
|
||||
:nth-child(2) {
|
||||
border-bottom: 1px dotted var(--tgc-white-1);
|
||||
text-shadow: 0 0 2px #000000cc;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
:last-child {
|
||||
opacity: 0.8;
|
||||
text-shadow: 0 0 2px black;
|
||||
}
|
||||
}
|
||||
|
||||
.dark .ton-content {
|
||||
background: #00000080;
|
||||
}
|
||||
|
||||
.ton-content :first-child {
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
text-shadow: 0 0 5px #000000cc;
|
||||
.ton-type {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ton-content :nth-child(2) {
|
||||
border-bottom: 1px dotted var(--tgc-white-1);
|
||||
text-shadow: 0 0 2px #000000cc;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.ton-content :last-child {
|
||||
opacity: 0.8;
|
||||
text-shadow: 0 0 2px black;
|
||||
.ton-sign {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ton-share {
|
||||
|
||||
@@ -2,10 +2,16 @@
|
||||
<div
|
||||
class="top-nc-box"
|
||||
@click="emit('selected', props.data)"
|
||||
:class="{ grey: !props.finish }"
|
||||
:class="props.finish ? '' : 'grey'"
|
||||
:title.attr="props.data.name"
|
||||
>
|
||||
<v-list-item :title="props.data.name">
|
||||
<v-list-item>
|
||||
<template #title>
|
||||
<div class="title">
|
||||
<TwnTypeTag :type="props.data.type" />
|
||||
<span>{{ props.data.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #subtitle>
|
||||
<span class="desc" :title="props.data.desc">{{ props.data.desc }}</span>
|
||||
</template>
|
||||
@@ -16,14 +22,13 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TwnTypeTag from "@comp/pageWiki/twn-type-tag.vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
type TopNameCardProps = { data: TGApp.App.NameCard.Item; finish?: boolean };
|
||||
type TopNameCardEmits = (e: "selected", v: TGApp.App.NameCard.Item) => void;
|
||||
|
||||
const props = withDefaults(defineProps<TopNameCardProps>(), {
|
||||
finish: true,
|
||||
});
|
||||
const props = withDefaults(defineProps<TopNameCardProps>(), { finish: true });
|
||||
const emit = defineEmits<TopNameCardEmits>();
|
||||
|
||||
const bgImage = computed<string>(() => {
|
||||
@@ -44,7 +49,6 @@ const bgImage = computed<string>(() => {
|
||||
justify-content: flex-start;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 4px 50px 50px 4px;
|
||||
margin-bottom: 8px;
|
||||
background-color: var(--box-bg-1);
|
||||
background-image: v-bind(bgImage); /* stylelint-disable-line value-keyword-case */
|
||||
background-position: right;
|
||||
@@ -72,6 +76,12 @@ const bgImage = computed<string>(() => {
|
||||
aspect-ratio: 23 / 15;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 4px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
text-shadow: 0 0 2px var(--common-shadow-t-8);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<THomeCard :append="false">
|
||||
<template #title>限时祈愿</template>
|
||||
<template #default>
|
||||
<!-- TODO: 当数量超过2时,改为走轮播,显示2个 -->
|
||||
<div class="pool-grid">
|
||||
<PhPoolCard v-for="(pool, idx) in pools" :key="idx" :pool="pool" />
|
||||
</div>
|
||||
|
||||
@@ -84,7 +84,9 @@ async function loadUserPosition(): Promise<void> {
|
||||
await TGLogger.Error(`获取近期活动失败:[${resp.retcode}-${resp.message}`);
|
||||
return;
|
||||
}
|
||||
userPos.value = [...resp.act_list, ...resp.fixed_act_list];
|
||||
userPos.value = [...resp.act_list, ...resp.fixed_act_list].filter(
|
||||
(i) => i.start_timestamp !== "0",
|
||||
);
|
||||
}
|
||||
|
||||
async function loadWikiPosition(): Promise<void> {
|
||||
|
||||
@@ -68,11 +68,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ph-puc-duration">
|
||||
<span title="剩余时间">{{ stamp2LastTime(restTs * 1000) }}</span>
|
||||
<span title="活动时间">
|
||||
{{ timestampToDate(Number(props.pos.start_timestamp) * 1000) }} ~
|
||||
{{ timestampToDate(Number(props.pos.end_timestamp) * 1000) }}
|
||||
</span>
|
||||
<template v-if="isStart">
|
||||
<span title="剩余时间">{{ stamp2LastTime(restTs * 1000) }}</span>
|
||||
<span title="活动时间">
|
||||
{{ timestampToDate(Number(props.pos.start_timestamp) * 1000) }} ~
|
||||
{{ timestampToDate(Number(props.pos.end_timestamp) * 1000) }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>未开始</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="ph-puc-rewards">
|
||||
<div
|
||||
@@ -94,7 +99,7 @@ import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import { ActCalendarTypeEnum } from "@enum/game.js";
|
||||
import { getHardChallengeDesc } from "@Sql/utils/transUserRecord.js";
|
||||
import { stamp2LastTime, timestampToDate } from "@utils/toolFunc.js";
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
type PhCompPositionUserProps = { pos: TGApp.Game.ActCalendar.ActItem };
|
||||
@@ -110,6 +115,9 @@ const emits = defineEmits<PhCompPositionUserEmits>();
|
||||
const endTs = ref<number>(0);
|
||||
const restTs = ref<number>(0);
|
||||
const durationTs = ref<number>(0);
|
||||
const isStart = computed<boolean>(() => {
|
||||
return props.pos.start_timestamp !== "0";
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
endTs.value = Number(props.pos.end_timestamp);
|
||||
|
||||
62
src/components/pageWiki/twn-type-tag.vue
Normal file
62
src/components/pageWiki/twn-type-tag.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="twn-type-tag" :class="typeCls">
|
||||
{{ props.type }}
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
type TwnTypeTagProps = { type: string };
|
||||
|
||||
const props = defineProps<TwnTypeTagProps>();
|
||||
|
||||
const typeCls = computed<string>(() => {
|
||||
switch (props.type) {
|
||||
case "成就":
|
||||
return "achi";
|
||||
case "好感":
|
||||
return "fetter";
|
||||
case "活动":
|
||||
return "act";
|
||||
case "纪行":
|
||||
return "journey";
|
||||
case "声望":
|
||||
return "pop";
|
||||
default:
|
||||
return "default";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@use "@styles/github.styles.scss" as github-styles;
|
||||
|
||||
.twn-type-tag {
|
||||
padding: 0 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
|
||||
&.achi {
|
||||
@include github-styles.github-tag-dark-gen(#4db6ac);
|
||||
}
|
||||
|
||||
&.fetter {
|
||||
@include github-styles.github-tag-dark-gen(#ba68c8);
|
||||
}
|
||||
|
||||
&.act {
|
||||
@include github-styles.github-tag-dark-gen(#81c784);
|
||||
}
|
||||
|
||||
&.journey {
|
||||
@include github-styles.github-tag-dark-gen(#64b5f6);
|
||||
}
|
||||
|
||||
&.pop {
|
||||
@include github-styles.github-tag-dark-gen(#e57373);
|
||||
}
|
||||
|
||||
&.default {
|
||||
@include github-styles.github-tag-dark-gen(#ffb74d);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -57,6 +57,7 @@ const props = defineProps<TwoConvertProps>();
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="tua-al-container">
|
||||
<div v-if="ncData !== undefined">
|
||||
<div v-if="ncData !== undefined" class="tua-al-nc">
|
||||
<TopNameCard :data="ncData" @selected="showNc = true" :finish="isFinish" />
|
||||
</div>
|
||||
<v-virtual-scroll :items="renderAchi" :item-height="60" class="tua-al-list">
|
||||
@@ -160,6 +160,10 @@ function switchAchiInfo(next: boolean): void {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tua-al-nc {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tua-al-list {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ async function setAchiStat(stat: boolean): Promise<void> {
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
align-items: center;
|
||||
column-gap: 4px;
|
||||
font-family: var(--font-title);
|
||||
font-size: 14px;
|
||||
@@ -175,12 +175,18 @@ async function setAchiStat(stat: boolean): Promise<void> {
|
||||
@include github-styles.github-tag-dark-gen(#00aeec);
|
||||
|
||||
display: flex;
|
||||
height: 21px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
border-radius: 9px;
|
||||
font-family: var(--font-text);
|
||||
font-size: 10px;
|
||||
|
||||
&:hover {
|
||||
@include github-styles.github-tag-dark-gen(#7ab61f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
>
|
||||
<span>{{ talent.name }}</span>
|
||||
<div class="duc-dort-icon">
|
||||
<div v-if="!talent.is_unlock" class="duc-dort-lock">
|
||||
<v-icon color="white">mdi-lock</v-icon>
|
||||
</div>
|
||||
<TMiImg :ori="true" :src="talent.icon" alt="talent" />
|
||||
</div>
|
||||
<span>Lv.{{ talent.level === 0 ? 1 : talent.level }}</span>
|
||||
@@ -25,20 +28,49 @@ const props = defineProps<DucDetailOrtProps>();
|
||||
.duc-dort-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
row-gap: 8px;
|
||||
}
|
||||
|
||||
.duc-dort-item {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
column-gap: 8px;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: var(--tgc-white-1);
|
||||
font-family: var(--font-title);
|
||||
font-size: 16px;
|
||||
text-shadow: 0 0 5px #00000066;
|
||||
|
||||
&:last-child {
|
||||
width: 48px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.duc-dort-lock {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3px;
|
||||
border-radius: 50%;
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
backdrop-filter: blur(5px);
|
||||
background-color: #00000066;
|
||||
}
|
||||
|
||||
.duc-dort-icon {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -54,14 +86,4 @@ const props = defineProps<DucDetailOrtProps>();
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.duc-dort-item span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--tgc-white-1);
|
||||
font-family: var(--font-title);
|
||||
font-size: 16px;
|
||||
text-shadow: 0 0 5px #00000066;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -35,8 +35,7 @@
|
||||
</div>
|
||||
<!-- 底部水印信息 -->
|
||||
<div class="duc-doc-bt">
|
||||
UID: {{ props.modelValue.uid }} Updated: {{ props.modelValue.updated }} | Rendered by
|
||||
TeyvatGuide v{{ version }}
|
||||
UID: {{ props.modelValue.uid }} {{ props.modelValue.updated }} | TeyvatGuide v{{ version }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -149,9 +148,8 @@ async function share(): Promise<void> {
|
||||
|
||||
.duc-doc-rt {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
padding: 5px;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
.duc-doc-lb {
|
||||
|
||||
@@ -49,9 +49,9 @@
|
||||
/>
|
||||
<TurOverviewSub :text="modelValue.domainNumber" title="解锁秘境" />
|
||||
<TurOverviewSub
|
||||
:text="modelValue.pyroCulus"
|
||||
icon="/icon/material/107028.webp"
|
||||
title="火神瞳"
|
||||
:text="modelValue.moonCulus"
|
||||
icon="/icon/material/107030.webp"
|
||||
title="月神瞳"
|
||||
/>
|
||||
<TurOverviewSub
|
||||
:text="modelValue.anemoCulus"
|
||||
@@ -78,6 +78,11 @@
|
||||
icon="/icon/material/107023.webp"
|
||||
title="水神瞳"
|
||||
/>
|
||||
<TurOverviewSub
|
||||
:text="modelValue.pyroCulus"
|
||||
icon="/icon/material/107028.webp"
|
||||
title="火神瞳"
|
||||
/>
|
||||
<TurOverviewSub :text="modelValue.luxuriousChest" title="华丽宝箱数" />
|
||||
<TurOverviewSub :text="modelValue.preciousChest" title="珍贵宝箱数" />
|
||||
<TurOverviewSub :text="modelValue.exquisiteChest" title="精致宝箱数" />
|
||||
@@ -95,15 +100,15 @@ defineProps<{ modelValue: TGApp.Sqlite.Record.Stats }>();
|
||||
.tur-og-box {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-gap: 8px;
|
||||
grid-template-columns: repeat(4, 0.25fr);
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(3, 0.33fr);
|
||||
}
|
||||
|
||||
.tur-og-box-3 {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
grid-gap: 8px;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,10 +9,22 @@
|
||||
<div class="tur-ws-content">
|
||||
<div class="tur-ws-title">
|
||||
<span>{{ data.name }}</span>
|
||||
<span v-if="data.offering" class="tur-ws-sub">
|
||||
<img :src="data.offering.icon" alt="offer" />
|
||||
<span>{{ data.offering.name }}-</span>
|
||||
<span>{{ data.offering.level }}</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>级</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tur-ws-offerings" v-if="data.offerings && data.offerings.length > 1">
|
||||
<span
|
||||
v-for="(offer, idx) in data.offerings"
|
||||
:key="idx"
|
||||
class="tur-ws-sub"
|
||||
:title="offer.name + '-' + offer.level + '级'"
|
||||
>
|
||||
<img :src="offer.icon" alt="offer" />
|
||||
<span>{{ offer.level }}</span>
|
||||
<span>级</span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -33,6 +45,24 @@
|
||||
<span>%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
data.area_exploration_list &&
|
||||
data.area_exploration_list.length > 0 &&
|
||||
data.exploration < 1000
|
||||
"
|
||||
class="tur-ws-areas"
|
||||
>
|
||||
<span
|
||||
v-for="area in data.area_exploration_list.filter((i) => i.exploration_percentage < 1000)"
|
||||
:key="area.name"
|
||||
class="tur-ws-sub"
|
||||
>
|
||||
<span>{{ area.name }}:</span>
|
||||
<span>{{ Math.min(area.exploration_percentage / 10, 100) }}</span>
|
||||
<span>%</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="data.reputation" class="tur-ws-sub">
|
||||
<span>声望等级:</span>
|
||||
<span>{{ data.reputation }}</span>
|
||||
@@ -84,6 +114,7 @@ const icon = computed<string>(() => {
|
||||
}
|
||||
|
||||
.tur-ws-icon {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
@@ -96,6 +127,7 @@ const icon = computed<string>(() => {
|
||||
}
|
||||
|
||||
.tur-ws-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: calc(100% - 68px);
|
||||
height: 100%;
|
||||
@@ -111,6 +143,21 @@ const icon = computed<string>(() => {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.tur-ws-offerings {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.tur-ws-areas {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: 4px 8px;
|
||||
}
|
||||
|
||||
.tur-ws-sub {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -396,7 +396,6 @@ async function trySign(ac: SignAccount[], ck: TGApp.App.Account.Cookie): Promise
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.delete {
|
||||
@@ -430,16 +429,16 @@ async function trySign(ac: SignAccount[], ck: TGApp.App.Account.Cookie): Promise
|
||||
height: 48px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 50%;
|
||||
background: var(--box-bg-4);
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
span {
|
||||
@@ -454,5 +453,11 @@ async function trySign(ac: SignAccount[], ck: TGApp.App.Account.Cookie): Promise
|
||||
font-size: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&:hover img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5527,6 +5527,15 @@
|
||||
"source": [],
|
||||
"convert": []
|
||||
},
|
||||
{
|
||||
"id": 107030,
|
||||
"name": "散失的月神瞳",
|
||||
"description": "浓烈的月矩力积聚成的物质。献给新月的神像,能弥补它在漫长岁月中散失的力量。",
|
||||
"type": "冒险道具",
|
||||
"star": 1,
|
||||
"source": [],
|
||||
"convert": []
|
||||
},
|
||||
{
|
||||
"id": 110001,
|
||||
"name": "面粉",
|
||||
|
||||
@@ -39,9 +39,7 @@
|
||||
<div class="ur-box" v-if="recordData">
|
||||
<div class="ur-box-title">
|
||||
<TurRoleInfo :role="recordData.role" :uid="uidCur ?? 0" />
|
||||
<span class="sign">
|
||||
原神战绩|Render by TeyvatGuide v{{ version }}|更新于 {{ recordData.updated }}
|
||||
</span>
|
||||
<span class="sign">TeyvatGuide v{{ version }} | {{ recordData.updated }}</span>
|
||||
</div>
|
||||
<PhCompCard>
|
||||
<template #title>数据总览</template>
|
||||
@@ -115,6 +113,7 @@ async function loadRecord(): Promise<void> {
|
||||
const record = await TSUserRecord.getRecord(uidCur.value);
|
||||
if (!record) return;
|
||||
recordData.value = record;
|
||||
console.log(recordData.value);
|
||||
}
|
||||
|
||||
async function refreshRecord(): Promise<void> {
|
||||
@@ -144,21 +143,21 @@ async function refreshRecord(): Promise<void> {
|
||||
}
|
||||
await showLoading.start(`正在刷新${account.value.gameUid}的战绩数据`);
|
||||
await TGLogger.Info(`[UserRecord][refresh][${account.value.gameUid}] 刷新战绩数据`);
|
||||
const res = await recordReq.index(cookie.value, account.value);
|
||||
if ("retcode" in res) {
|
||||
const resp = await recordReq.index(cookie.value, account.value);
|
||||
console.log(resp);
|
||||
if ("retcode" in resp) {
|
||||
await showLoading.end();
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
showSnackbar.error(`[${resp.retcode}] ${resp.message}`);
|
||||
await TGLogger.Error(`[UserRecord][refresh][${account.value.gameUid}] 获取战绩数据失败`);
|
||||
await TGLogger.Error(
|
||||
`[UserRecord][refresh][${account.value.gameUid}] ${res.retcode} ${res.message}`,
|
||||
`[UserRecord][refresh][${account.value.gameUid}] ${resp.retcode} ${resp.message}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[UserRecord][refresh][${account.value.gameUid}] 获取战绩数据成功`);
|
||||
await TGLogger.Info(`[UserRecord][refresh][${account.value.gameUid}]`, false);
|
||||
console.log(res);
|
||||
await showLoading.update("正在保存战绩数据");
|
||||
await TSUserRecord.saveRecord(Number(account.value.gameUid), res);
|
||||
await TSUserRecord.saveRecord(Number(account.value.gameUid), resp);
|
||||
await showLoading.update("正在加载战绩数据");
|
||||
await loadUid();
|
||||
await loadRecord();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<v-app-bar density="compact">
|
||||
<v-app-bar>
|
||||
<template #prepend>
|
||||
<div class="twm-title">
|
||||
<div class="twm-title-left">
|
||||
<div class="twm-top-prepend">
|
||||
<div class="title">
|
||||
<img src="/source/UI/wikiGCG.webp" alt="icon" />
|
||||
<span>材料图鉴</span>
|
||||
</div>
|
||||
@@ -14,6 +14,8 @@
|
||||
:clearable="true"
|
||||
width="250px"
|
||||
label="材料类别"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
>
|
||||
<template #item="{ props, item }">
|
||||
<v-list-item v-bind="props">
|
||||
@@ -26,16 +28,19 @@
|
||||
</div>
|
||||
</template>
|
||||
<template #append>
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
width="200px"
|
||||
append-icon="mdi-magnify"
|
||||
label="搜索"
|
||||
:single-line="true"
|
||||
:hide-details="true"
|
||||
@keydown.enter="searchMaterial()"
|
||||
@click:append="searchMaterial()"
|
||||
/>
|
||||
<div class="twm-top-append">
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
variant="outlined"
|
||||
density="compact"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
label="搜索"
|
||||
:single-line="true"
|
||||
:hide-details="true"
|
||||
@keydown.enter="searchMaterial()"
|
||||
@click:prepend-inner="searchMaterial()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</v-app-bar>
|
||||
<div class="twm-box">
|
||||
@@ -158,33 +163,36 @@ function searchMaterial(): void {
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.twm-title {
|
||||
.twm-top-prepend {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
column-gap: 10px;
|
||||
justify-content: flex-start;
|
||||
margin-left: 16px;
|
||||
column-gap: 16px;
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--common-text-title);
|
||||
column-gap: 4px;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.twm-title-left {
|
||||
.twm-top-append {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 5px;
|
||||
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: var(--font-title);
|
||||
font-size: 18px;
|
||||
}
|
||||
width: 600px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.twm-box {
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
<!-- TODO: UI一致性&类别筛选 -->
|
||||
<template>
|
||||
<div class="tw-nc-box">
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
label="搜索"
|
||||
:hide-details="true"
|
||||
variant="outlined"
|
||||
@click:prepend-inner="searchNameCard()"
|
||||
@keyup.enter="searchNameCard()"
|
||||
/>
|
||||
<div class="tw-nc-list">
|
||||
<v-virtual-scroll :items="sortNameCardsData" :item-height="80" item-key="id">
|
||||
<template #default="{ item }">
|
||||
<TopNameCard :data="item" @selected="showNameCard(item)" />
|
||||
</template>
|
||||
</v-virtual-scroll>
|
||||
</div>
|
||||
<v-app-bar>
|
||||
<template #prepend>
|
||||
<div class="wnc-top-prepend">
|
||||
<div class="title">
|
||||
<v-icon size="32">mdi-credit-card-outline</v-icon>
|
||||
<span>名片图鉴</span>
|
||||
</div>
|
||||
<v-select
|
||||
v-model="selectType"
|
||||
:items="namecardTypes"
|
||||
item-title="type"
|
||||
:hide-details="true"
|
||||
:clearable="true"
|
||||
width="250px"
|
||||
label="名片类别"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
>
|
||||
<template #item="{ props, item }">
|
||||
<v-list-item v-bind="props">
|
||||
<template #append>
|
||||
<v-chip>{{ item.raw.number }}</v-chip>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-select>
|
||||
</div>
|
||||
</template>
|
||||
<template #append>
|
||||
<div class="wnc-top-append">
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
density="compact"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
label="搜索"
|
||||
:hide-details="true"
|
||||
variant="outlined"
|
||||
@click:prepend-inner="searchNameCard()"
|
||||
@keyup.enter="searchNameCard()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</v-app-bar>
|
||||
<div class="tw-nc-list">
|
||||
<v-virtual-scroll class="v-scroll" :items="sortNameCardsData" :item-height="80" item-key="id">
|
||||
<template #default="{ item }">
|
||||
<TopNameCard class="item" :data="item" @selected="showNameCard(item)" />
|
||||
</template>
|
||||
</v-virtual-scroll>
|
||||
</div>
|
||||
<ToNameCard v-model="visible" :data="curNameCard">
|
||||
<template #left>
|
||||
@@ -35,18 +66,46 @@
|
||||
import ToNameCard from "@comp/app/to-nameCard.vue";
|
||||
import TopNameCard from "@comp/app/top-nameCard.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { onMounted, ref, shallowRef } from "vue";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import { AppNameCardsData } from "@/data/index.js";
|
||||
|
||||
type NameCardType = { type: string; number: number };
|
||||
|
||||
const curIndex = ref<number>(0);
|
||||
const total = ref<number>(0);
|
||||
const visible = ref<boolean>(false);
|
||||
const search = ref<string>();
|
||||
const selectType = ref<string | null>(null);
|
||||
const namecardTypes = shallowRef<Array<NameCardType>>([]);
|
||||
const curNameCard = shallowRef<TGApp.App.NameCard.Item>();
|
||||
const sortNameCardsData = shallowRef<Array<TGApp.App.NameCard.Item>>([]);
|
||||
|
||||
onMounted(() => sortData(AppNameCardsData));
|
||||
onMounted(() => {
|
||||
const tmpData: Array<NameCardType> = [];
|
||||
for (const item of AppNameCardsData) {
|
||||
const typeFindIndex = tmpData.findIndex((itemT) => itemT.type === item.type);
|
||||
if (typeFindIndex === -1) {
|
||||
const itemN: NameCardType = { type: item.type, number: 1 };
|
||||
tmpData.push(itemN);
|
||||
continue;
|
||||
}
|
||||
tmpData[typeFindIndex].number++;
|
||||
}
|
||||
namecardTypes.value = tmpData;
|
||||
sortData(AppNameCardsData);
|
||||
showSnackbar.success(`成功获取${sortNameCardsData.value.length}条数据`);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => selectType.value,
|
||||
() => sortData(getSelectNameCards()),
|
||||
);
|
||||
|
||||
function getSelectNameCards(): TGApp.App.NameCard.Item[] {
|
||||
if (selectType.value === null) return AppNameCardsData;
|
||||
else return AppNameCardsData.filter((item) => item.type === selectType.value);
|
||||
}
|
||||
|
||||
function sortData(data: TGApp.App.NameCard.Item[]): void {
|
||||
sortNameCardsData.value = data.sort((a, b) => a.type.localeCompare(b.type) || a.id - b.id);
|
||||
@@ -98,16 +157,47 @@ function searchNameCard(): void {
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tw-nc-box {
|
||||
.wnc-top-prepend {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-left: 16px;
|
||||
column-gap: 16px;
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--common-text-title);
|
||||
column-gap: 4px;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.wnc-top-append {
|
||||
position: relative;
|
||||
width: 600px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.tw-nc-list {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
height: calc(100vh - 100px);
|
||||
padding-right: 10px;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
|
||||
.v-scroll {
|
||||
padding-right: 8px;
|
||||
|
||||
.item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-arrow {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file plugins/Sqlite/utils/transUserRecord.ts
|
||||
* @description Sqlite 数据转换 用户战绩数据转换模块
|
||||
* @since Beta v0.7.2
|
||||
* @since Beta v0.8.1
|
||||
*/
|
||||
|
||||
import { getZhElement } from "@utils/toolFunc.js";
|
||||
@@ -89,9 +89,9 @@ export function getHardChallengeDesc(difficulty: number): string {
|
||||
|
||||
/**
|
||||
* @description 将统计信息转换为数据库中的数据
|
||||
* @since Beta v0.8.0
|
||||
* @since Beta v0.8.1
|
||||
* @param {TGApp.Game.Record.Stats} data 统计信息
|
||||
* @return {TGApp.Sqlite.Record.Stats } 转换后的统计信息
|
||||
* @return {TGApp.Sqlite.Record.Stats} 转换后的统计信息
|
||||
*/
|
||||
function transStat(data: TGApp.Game.Record.Stats): TGApp.Sqlite.Record.Stats {
|
||||
return {
|
||||
@@ -107,6 +107,7 @@ function transStat(data: TGApp.Game.Record.Stats): TGApp.Sqlite.Record.Stats {
|
||||
dendroCulus: data.dendroculus_number,
|
||||
hydroCulus: data.hydroculus_number,
|
||||
pyroCulus: data.pyroculus_number,
|
||||
moonCulus: data.moonoculus_number,
|
||||
sprialAbyss: data.spiral_abyss,
|
||||
combatRole: data.role_combat.is_unlock ? `第 ${data.role_combat.max_round_id} 幕` : "未解锁",
|
||||
hardChallenge: data.hard_challenge.is_unlock
|
||||
@@ -122,11 +123,13 @@ function transStat(data: TGApp.Game.Record.Stats): TGApp.Sqlite.Record.Stats {
|
||||
|
||||
/**
|
||||
* @description 将探索信息转换为数据库中的数据
|
||||
* @since Beta v0.7.2
|
||||
* @param {TGApp.Game.Record.WorldExplore[]} data 城市探索信息
|
||||
* @returns {TGApp.Sqlite.Record.WorldExplore[]} 转换后的城市探索信息
|
||||
* @since Beta v0.8.1
|
||||
* @param {Array<TGApp.Game.Record.WorldExplore>} data 城市探索信息
|
||||
* @returns {Array<TGApp.Sqlite.Record.WorldExplore>} 转换后的城市探索信息
|
||||
*/
|
||||
function transWorld(data: TGApp.Game.Record.WorldExplore[]): TGApp.Sqlite.Record.WorldExplore[] {
|
||||
function transWorld(
|
||||
data: Array<TGApp.Game.Record.WorldExplore>,
|
||||
): Array<TGApp.Sqlite.Record.WorldExplore> {
|
||||
const areaParent = data.filter((i) => i.parent_id === 0);
|
||||
const areaChild = data.filter((i) => i.parent_id !== 0);
|
||||
const worlds: TGApp.Sqlite.Record.WorldExplore[] = [];
|
||||
@@ -140,16 +143,11 @@ function transWorld(data: TGApp.Game.Record.WorldExplore[]): TGApp.Sqlite.Record
|
||||
bg: area.background_image,
|
||||
cover: area.cover,
|
||||
exploration: area.exploration_percentage,
|
||||
area_exploration_list: area.area_exploration_list,
|
||||
children: [],
|
||||
};
|
||||
if (area.type === "Reputation") world.reputation = area.level;
|
||||
if (area.offerings !== undefined && area.offerings.length > 0) {
|
||||
world.offering = {
|
||||
name: area.offerings[0].name,
|
||||
level: area.offerings[0].level,
|
||||
icon: area.offerings[0].icon,
|
||||
};
|
||||
}
|
||||
if (area.offerings !== undefined && area.offerings.length > 0) world.offerings = area.offerings;
|
||||
// 对纳塔的特殊处理
|
||||
if (area.name === "纳塔") {
|
||||
world.icon =
|
||||
@@ -164,6 +162,13 @@ function transWorld(data: TGApp.Game.Record.WorldExplore[]): TGApp.Sqlite.Record
|
||||
world.iconLight = world.icon;
|
||||
world.bg =
|
||||
"https://fastcdn.mihoyo.com/static-resource-v2/2025/03/17/8ee1648101a8b292ffb37eb49559032e_6583057448168798147.png";
|
||||
// 对挪德卡莱的特殊处理
|
||||
} else if (area.name === "挪德卡莱") {
|
||||
world.icon =
|
||||
"https://webstatic.mihoyo.com/app/community-game-records/images/world-logo-17.dadac5bf.png";
|
||||
world.iconLight = world.icon;
|
||||
world.bg =
|
||||
"https://fastcdn.mihoyo.com/static-resource-v2/2025/08/22/ace66cea9c5074b70310ecbbb712cd94_2619077306700596372.png";
|
||||
}
|
||||
const children = areaChild.filter((i) => i.parent_id === area.id);
|
||||
for (const child of children) {
|
||||
|
||||
83
src/types/Game/Record.d.ts
vendored
83
src/types/Game/Record.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file types/Game/Record.d.ts
|
||||
* @description 原神战绩相关类型定义文件
|
||||
* @since Beta v0.8.0
|
||||
* @since Beta v0.8.1
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Game.Record {
|
||||
@@ -11,7 +11,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @since Alpha v0.2.0
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {FullData} data - 原神战绩数据
|
||||
* @return Response
|
||||
*/
|
||||
type Response = TGApp.BBS.Response.BaseWithData<FullData>;
|
||||
|
||||
@@ -27,7 +26,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {Array<Home>} homes - 尘歌壶信息
|
||||
* @property {string} query_tool_link - 查询工具链接
|
||||
* @property {string} query_tool_image - 查询工具图片
|
||||
* @return FullData
|
||||
*/
|
||||
type FullData = {
|
||||
role: Role;
|
||||
@@ -49,7 +47,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {string} region - 区域
|
||||
* @property {number} level - 等级
|
||||
* @property {string} game_head_icon - 游戏头像
|
||||
* @return Role
|
||||
*/
|
||||
type Role = {
|
||||
AvatarUrl: string;
|
||||
@@ -75,7 +72,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {boolean} is_chosen - 角色是否展示
|
||||
* @property {unknown} weapon - 角色武器 // null
|
||||
* @property {Array<unknown>} relics - 角色圣遗物 // []
|
||||
* @return Avatar
|
||||
*/
|
||||
type Avatar = {
|
||||
id: number;
|
||||
@@ -95,51 +91,53 @@ declare namespace TGApp.Game.Record {
|
||||
/**
|
||||
* @description 统计信息类型
|
||||
* @interface Stats
|
||||
* @since Beta v0.8.0
|
||||
* @property {number} active_day_number - 活跃天数
|
||||
* @since Beta v0.8.1
|
||||
* @property {number} achievement_number - 成就数量
|
||||
* @property {number} active_day_number - 活跃天数
|
||||
* @property {number} anemoculus_number - 风神瞳数量
|
||||
* @property {number} geoculus_number - 岩神瞳数量
|
||||
* @property {number} avatar_number - 角色数量
|
||||
* @property {number} way_point_number - 解锁传送点数量
|
||||
* @property {number} domain_number - 解锁秘境数量
|
||||
* @property {string} spiral_abyss - 深境螺旋最深达到几层
|
||||
* @property {number} precious_chest_number - 珍贵宝箱数量
|
||||
* @property {number} luxurious_chest_number - 豪华宝箱数量
|
||||
* @property {number} exquisite_chest_number - 精致宝箱数量
|
||||
* @property {number} common_chest_number - 普通宝箱数量
|
||||
* @property {number} electroculus_number - 雷神瞳数量
|
||||
* @property {number} magic_chest_number - 奇馈宝箱数量
|
||||
* @property {number} dendroculus_number - 草神瞳数量
|
||||
* @property {number} hydroculus_number - 水神瞳数量
|
||||
* @property {number} pyroculus_number - 火神瞳数量
|
||||
* @property {number} domain_number - 解锁秘境数量
|
||||
* @property {number} electroculus_number - 雷神瞳数量
|
||||
* @property {number} exquisite_chest_number - 精致宝箱数量
|
||||
* @property {unknown} field_ext_map - 数据对应链接的map,用不到设为 unknown
|
||||
* @property {CombatStats} role_combat - 幻想真境剧诗数据
|
||||
* @property {number} full_fetter_avatar_num - 满好感角色数
|
||||
* @property {number} geoculus_number - 岩神瞳数量
|
||||
* @property {ChallengeStats} hard_challenge - 幽境危战挑战数据
|
||||
* @property {number} hydroculus_number - 水神瞳数量
|
||||
* @property {number} luxurious_chest_number - 豪华宝箱数量
|
||||
* @property {number} magic_chest_number - 奇馈宝箱数量
|
||||
* @property {number} moonoculus_number - 月神瞳数量
|
||||
* @property {number} precious_chest_number - 珍贵宝箱数量
|
||||
* @property {number} pyroculus_number - 火神瞳数量
|
||||
* @property {CombatStats} role_combat - 幻想真境剧诗数据
|
||||
* @property {string} spiral_abyss - 深境螺旋最深达到几层
|
||||
* @property {number} way_point_number - 解锁传送点数量
|
||||
*/
|
||||
type Stats = {
|
||||
active_day_number: number;
|
||||
achievement_number: number;
|
||||
active_day_number: number;
|
||||
anemoculus_number: number;
|
||||
geoculus_number: number;
|
||||
avatar_number: number;
|
||||
way_point_number: number;
|
||||
domain_number: number;
|
||||
spiral_abyss: string;
|
||||
precious_chest_number: number;
|
||||
luxurious_chest_number: number;
|
||||
exquisite_chest_number: number;
|
||||
common_chest_number: number;
|
||||
electroculus_number: number;
|
||||
magic_chest_number: number;
|
||||
dendroculus_number: number;
|
||||
hydroculus_number: number;
|
||||
pyroculus_number: number;
|
||||
domain_number: number;
|
||||
electroculus_number: number;
|
||||
exquisite_chest_number: number;
|
||||
field_ext_map: unknown;
|
||||
role_combat: CombatStats;
|
||||
full_fetter_avatar_num: number;
|
||||
geoculus_number: number;
|
||||
hard_challenge: ChallengeStats;
|
||||
hydroculus_number: number;
|
||||
luxurious_chest_number: number;
|
||||
magic_chest_number: number;
|
||||
moonoculus_number: number;
|
||||
precious_chest_number: number;
|
||||
pyroculus_number: number;
|
||||
role_combat: CombatStats;
|
||||
spiral_abyss: string;
|
||||
way_point_number: number;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -150,7 +148,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {number} max_round_id - 最大报幕数
|
||||
* @property {boolean} has_data - 是否有数据
|
||||
* @property {boolean} has_detail_data - 是否有详细数据
|
||||
* @return CombatStats
|
||||
*/
|
||||
type CombatStats = {
|
||||
is_unlock: boolean;
|
||||
@@ -178,7 +175,7 @@ declare namespace TGApp.Game.Record {
|
||||
/**
|
||||
* @description 世界探索信息类型
|
||||
* @interface WorldExplore
|
||||
* @since Beta 0.7.2
|
||||
* @since Beta 0.8.1
|
||||
* @property {number} level - 声望等级
|
||||
* @property {number} exploration_percentage - 探索千分比
|
||||
* @property {string} icon - 图标
|
||||
@@ -198,9 +195,8 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {boolean} index_active - 索引激活
|
||||
* @property {boolean} detail_active - 详细激活
|
||||
* @property {number} seven_status_level - 七天神像等级
|
||||
* @property {NataReputation[] | null} nata_reputation - 纳塔声望
|
||||
* @property {NataReputation | null} nata_reputation - 纳塔声望
|
||||
* @property {number} world_type - 世界类型
|
||||
* @return WorldExplore
|
||||
*/
|
||||
type WorldExplore = {
|
||||
level: number;
|
||||
@@ -216,7 +212,7 @@ declare namespace TGApp.Game.Record {
|
||||
background_image: string;
|
||||
inner_icon: string;
|
||||
cover: string;
|
||||
area_exploration_list: Array<unknown>;
|
||||
area_exploration_list: Array<AreaExploration>;
|
||||
boss_list: Array<unknown>;
|
||||
is_hot: boolean;
|
||||
index_active: boolean;
|
||||
@@ -233,16 +229,23 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {string} name - 名称
|
||||
* @property {number} level - 等级
|
||||
* @property {string} icon - 图标
|
||||
* @return WorldOffering
|
||||
*/
|
||||
type WorldOffering = { name: string; level: number; icon: string };
|
||||
|
||||
/**
|
||||
* @description 区域探索类型
|
||||
* @interface AreaExploration
|
||||
* @since Beta v0.8.1
|
||||
* @property {string} name - 名称
|
||||
* @property {number} exploration_percentage - 探索千分比
|
||||
*/
|
||||
type AreaExploration = { name: string; exploration_percentage: number };
|
||||
|
||||
/**
|
||||
* @description 纳塔声望类型
|
||||
* @interface NataReputation
|
||||
* @since Beta v0.7.2
|
||||
* @property {Array<NataOffering>} tribal_list - 部落列表
|
||||
* @returns NataReputation
|
||||
*/
|
||||
type NataReputation = { tribal_list: Array<NataOffering> };
|
||||
|
||||
@@ -252,7 +255,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @extends WorldOffering
|
||||
* @property {number} id - ID
|
||||
* @property {string} image - 图片
|
||||
* @returns NataOffering
|
||||
*/
|
||||
type NataOffering = WorldOffering & { id: number; image: string };
|
||||
|
||||
@@ -268,7 +270,6 @@ declare namespace TGApp.Game.Record {
|
||||
* @property {string} icon - 图标
|
||||
* @property {string} comfort_level_name - 洞天仙力等级名称
|
||||
* @property {string} comfort_level_icon - 洞天仙力等级图标
|
||||
* @return Home
|
||||
*/
|
||||
type Home = {
|
||||
level: number;
|
||||
|
||||
36
src/types/Sqlite/Record.d.ts
vendored
36
src/types/Sqlite/Record.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file types/Sqlite/Record.d.ts
|
||||
* @description Sqlite 原神战绩相关类型定义文件
|
||||
* @since Beta v0.8.0
|
||||
* @since Beta v0.8.1
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Sqlite.Record {
|
||||
@@ -16,7 +16,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {string} worldExplore - 世界探索信息
|
||||
* @property {string} homes - 尘歌壶信息
|
||||
* @property {string} updated - 更新时间
|
||||
* @return SingleTable
|
||||
*/
|
||||
type SingleTable = {
|
||||
uid: number;
|
||||
@@ -39,7 +38,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {WorldExplore[]} worldExplore - 世界探索信息
|
||||
* @property {Home[]} homes - 尘歌壶信息
|
||||
* @property {string} updated - 更新时间
|
||||
* @returns RenderData
|
||||
*/
|
||||
type RenderData = {
|
||||
uid: number;
|
||||
@@ -59,7 +57,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {string} region - 区域
|
||||
* @property {number} level - 等级
|
||||
* @property {string} avatar - 头像
|
||||
* @return Role
|
||||
*/
|
||||
type Role = { nickname: string; region: string; level: number; avatar: string };
|
||||
|
||||
@@ -75,7 +72,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {number} star - 角色星级
|
||||
* @property {number} constellation - 角色命座
|
||||
* @property {boolean} isShow - 角色是否展示
|
||||
* @return Avatar
|
||||
*/
|
||||
type Avatar = {
|
||||
id: number;
|
||||
@@ -91,7 +87,7 @@ declare namespace TGApp.Sqlite.Record {
|
||||
/**
|
||||
* @description 统计信息类型
|
||||
* @interface Stats
|
||||
* @since Beta v0.8.0
|
||||
* @since Beta v0.8.1
|
||||
* @property {number} activeDays - 活跃天数
|
||||
* @property {number} achievementNumber - 成就达成数
|
||||
* @property {number} avatarNumber - 获得角色数
|
||||
@@ -104,6 +100,7 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {number} dendroCulus - 草神瞳数
|
||||
* @property {number} hydroCulus - 水神瞳数
|
||||
* @property {number} pyroCulus - 火神瞳数
|
||||
* @property {number} moonCulus - 月神瞳数
|
||||
* @property {string} sprialAbyss - 深境螺旋信息
|
||||
* @property {string} combatRole - 幻想真境剧诗
|
||||
* @property {string} hardChallenge - 幽境危战挑战
|
||||
@@ -112,7 +109,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {number} exquisiteChest - 精致宝箱数
|
||||
* @property {number} commonChest - 普通宝箱数
|
||||
* @property {number} magicChest - 奇馈宝箱数
|
||||
* @return Stats
|
||||
*/
|
||||
type Stats = {
|
||||
activeDays: number;
|
||||
@@ -127,6 +123,7 @@ declare namespace TGApp.Sqlite.Record {
|
||||
dendroCulus: number;
|
||||
hydroCulus: number;
|
||||
pyroCulus: number;
|
||||
moonCulus: number;
|
||||
sprialAbyss: string;
|
||||
combatRole: string;
|
||||
hardChallenge: string;
|
||||
@@ -140,7 +137,7 @@ declare namespace TGApp.Sqlite.Record {
|
||||
/**
|
||||
* @description 世界探索信息类型
|
||||
* @interface WorldExplore
|
||||
* @since Beta v0.7.2
|
||||
* @since Beta v0.8.1
|
||||
* @property {number} id - 地区 ID
|
||||
* @property {string} name - 地区名称
|
||||
* @property {string} iconLight - 地区图标(亮)
|
||||
@@ -148,9 +145,9 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {string} cover - 封面
|
||||
* @property {number} reputation - 地区声望等级
|
||||
* @property {WorldOffering} offering - 地区供奉信息
|
||||
* @property {Array<WorldOffering>} offerings - 地区供奉列表
|
||||
* @property {number} exploration - 地区探索进度
|
||||
* @property {WorldChild[]} children - 子地区
|
||||
* @return WorldExplore
|
||||
* @property {Array<WorldChild>} children - 子地区
|
||||
*/
|
||||
type WorldExplore = {
|
||||
id: number;
|
||||
@@ -160,9 +157,14 @@ declare namespace TGApp.Sqlite.Record {
|
||||
bg: string;
|
||||
cover: string;
|
||||
reputation?: number;
|
||||
/**
|
||||
* @deprecated 已弃用,建议使用 offerings
|
||||
*/
|
||||
offering?: WorldOffering;
|
||||
offerings?: Array<WorldOffering>;
|
||||
exploration: number;
|
||||
children: WorldChild[];
|
||||
area_exploration_list?: Array<AreaExploration>;
|
||||
children: Array<WorldChild>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -172,10 +174,18 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {string} name - 名称
|
||||
* @property {number} level - 等级
|
||||
* @property {string} icon - 图标
|
||||
* @return WorldOffering
|
||||
*/
|
||||
type WorldOffering = { name: string; level: number; icon: string };
|
||||
|
||||
/**
|
||||
* @description 区域探索类型
|
||||
* @interface AreaExploration
|
||||
* @since Beta v0.8.1
|
||||
* @property {string} name - 名称
|
||||
* @property {number} exploration_percentage - 探索千分比
|
||||
*/
|
||||
type AreaExploration = { name: string; exploration_percentage: number };
|
||||
|
||||
/**
|
||||
* @description 子地区类型
|
||||
* @interface WorldChild
|
||||
@@ -183,7 +193,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {number} id - 子地区 ID
|
||||
* @property {string} name - 子地区名称
|
||||
* @property {number} exploration - 子地区探索进度
|
||||
* @return WorldChild
|
||||
*/
|
||||
type WorldChild = { id: number; name: string; exploration: number };
|
||||
|
||||
@@ -199,7 +208,6 @@ declare namespace TGApp.Sqlite.Record {
|
||||
* @property {number} furniture - 获得摆设数
|
||||
* @property {number} visit - ;历史访客数
|
||||
* @property {string} bg - 背景
|
||||
* @return Home
|
||||
*/
|
||||
type Home = {
|
||||
comfortIcon: string;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file utils/toolFunc.ts
|
||||
* @description 一些工具函数
|
||||
* @since Beta v0.8.0
|
||||
* @since Beta v0.8.1
|
||||
*/
|
||||
|
||||
import { AvatarExtResTypeEnum, AvatarExtTypeEnum } from "@enum/bbs.js";
|
||||
@@ -220,18 +220,30 @@ export function isColorSimilar(colorBg: string, colorText: string): boolean {
|
||||
|
||||
/**
|
||||
* @description 解析带样式的文本
|
||||
* @since Beta v0.3.8
|
||||
* @since Beta v0.8.1
|
||||
* @param {string} desc - 带样式的文本
|
||||
* @returns {string} 解析后的文本
|
||||
*/
|
||||
export function parseHtmlText(desc: string): string {
|
||||
const reg = /<color=(.*?)>(.*?)<\/color>/g;
|
||||
let match = reg.exec(desc);
|
||||
while (match !== null) {
|
||||
const color = match[1];
|
||||
const text = match[2];
|
||||
desc = desc.replace(match[0], `<span title="${text}" style="color: ${color}">${text}</span>`);
|
||||
match = reg.exec(desc);
|
||||
const linkReg = /\{LINK#(.*?)}(.*?)\{\/LINK}/g;
|
||||
let linkMatch = linkReg.exec(desc);
|
||||
while (linkMatch !== null) {
|
||||
const link = linkMatch[1];
|
||||
const text = linkMatch[2];
|
||||
// TODO: 后续处理 t-link
|
||||
desc = desc.replace(linkMatch[0], `<t-link data-link="${link}">${text}</t-link>`);
|
||||
linkMatch = linkReg.exec(desc);
|
||||
}
|
||||
const colorReg = /<color=(.*?)>(.*?)<\/color>/g;
|
||||
let colorMatch = colorReg.exec(desc);
|
||||
while (colorMatch !== null) {
|
||||
const color = colorMatch[1];
|
||||
const text = new DOMParser().parseFromString(colorMatch[2], "text/html").body.textContent;
|
||||
desc = desc.replace(
|
||||
colorMatch[0],
|
||||
`<span title="${text}" style="color: ${color}">${text}</span>`,
|
||||
);
|
||||
colorMatch = colorReg.exec(desc);
|
||||
}
|
||||
desc = desc.replace(/\\n/g, "<br />");
|
||||
return desc;
|
||||
|
||||
Reference in New Issue
Block a user