mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-15 09:48:14 +08:00
💄 材料Wiki样式优化,支持分类筛选&查询
This commit is contained in:
24
src/App.vue
24
src/App.vue
@@ -60,11 +60,7 @@ onBeforeMount(async () => {
|
|||||||
async function checkResize(): Promise<void> {
|
async function checkResize(): Promise<void> {
|
||||||
const screen = await TauriWindow.currentMonitor();
|
const screen = await TauriWindow.currentMonitor();
|
||||||
if (screen === null) {
|
if (screen === null) {
|
||||||
showSnackbar({
|
showSnackbar({ text: "获取屏幕信息失败!", color: "error", timeout: 3000 });
|
||||||
text: "获取屏幕信息失败!",
|
|
||||||
color: "error",
|
|
||||||
timeout: 3000,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const windowCur = await webviewWindow.getCurrentWebviewWindow();
|
const windowCur = await webviewWindow.getCurrentWebviewWindow();
|
||||||
@@ -178,11 +174,7 @@ async function getDeepLink(): Promise<UnlistenFn> {
|
|||||||
await windowGet.setFocus();
|
await windowGet.setFocus();
|
||||||
const payload = parseDeepLink(e.payload);
|
const payload = parseDeepLink(e.payload);
|
||||||
if (payload === false) {
|
if (payload === false) {
|
||||||
showSnackbar({
|
showSnackbar({ text: "无效的 deep link!", color: "error", timeout: 3000 });
|
||||||
text: "无效的 deep link!",
|
|
||||||
color: "error",
|
|
||||||
timeout: 3000,
|
|
||||||
});
|
|
||||||
await TGLogger.Error(`[App][getDeepLink] 无效的 deep link! ${JSON.stringify(e.payload)}`);
|
await TGLogger.Error(`[App][getDeepLink] 无效的 deep link! ${JSON.stringify(e.payload)}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -216,11 +208,7 @@ async function handleDeepLink(payload: string): Promise<void> {
|
|||||||
if (payload.startsWith("router?path=")) {
|
if (payload.startsWith("router?path=")) {
|
||||||
const routerPath = payload.replace("router?path=", "");
|
const routerPath = payload.replace("router?path=", "");
|
||||||
if (router.currentRoute.value.path === routerPath) {
|
if (router.currentRoute.value.path === routerPath) {
|
||||||
showSnackbar({
|
showSnackbar({ text: "已在当前页面!", color: "warn", timeout: 3000 });
|
||||||
text: "已在当前页面!",
|
|
||||||
color: "warn",
|
|
||||||
timeout: 3000,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await router.push(routerPath);
|
await router.push(routerPath);
|
||||||
@@ -258,11 +246,7 @@ async function checkUpdate(): Promise<void> {
|
|||||||
}
|
}
|
||||||
appStore.buildTime = getBuildTime();
|
appStore.buildTime = getBuildTime();
|
||||||
await TGSqlite.update();
|
await TGSqlite.update();
|
||||||
showSnackbar({
|
showSnackbar({ text: "数据库已更新!", color: "success", timeout: 3000 });
|
||||||
text: "数据库已更新!",
|
|
||||||
color: "success",
|
|
||||||
timeout: 3000,
|
|
||||||
});
|
|
||||||
// todo 6.0发版时取消注释
|
// todo 6.0发版时取消注释
|
||||||
// window.open("https://app.btmuli.ink/docs/Changelogs.html");
|
// window.open("https://app.btmuli.ink/docs/Changelogs.html");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<div class="twom-type">{{ props.data.type }}</div>
|
<div class="twom-type">{{ props.data.type }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="twom-bottom">
|
<div class="twom-bottom">
|
||||||
<div class="twom-desc">{{ parseDesc() }}</div>
|
<div class="twom-desc" v-html="parseHtmlText(props.data.description)" />
|
||||||
<div class="twom-source" v-if="props.data.source.length > 1">
|
<div class="twom-source" v-if="props.data.source.length > 1">
|
||||||
<TwoSource :data="item" v-for="(item, index) in props.data.source" :key="index" />
|
<TwoSource :data="item" v-for="(item, index) in props.data.source" :key="index" />
|
||||||
</div>
|
</div>
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
import { parseHtmlText } from "../../utils/toolFunc.js";
|
||||||
import TOverlay from "../main/t-overlay.vue";
|
import TOverlay from "../main/t-overlay.vue";
|
||||||
|
|
||||||
import TwoConvert from "./two-convert.vue";
|
import TwoConvert from "./two-convert.vue";
|
||||||
@@ -41,25 +42,15 @@ const props = defineProps<TwoMaterialProps>();
|
|||||||
const emits = defineEmits<TwoMaterialEmits>();
|
const emits = defineEmits<TwoMaterialEmits>();
|
||||||
|
|
||||||
const visible = computed({
|
const visible = computed({
|
||||||
get() {
|
get: () => props.modelValue,
|
||||||
return props.modelValue;
|
set: (val) => emits("update:modelValue", val),
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
emits("update:modelValue", value);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
const iconBg = computed(() => {
|
const iconBg = computed(() => {
|
||||||
if (!props.data) return "url('/icon/bg/0-BGC.webp')";
|
if (!props.data) return "url('/icon/bg/0-BGC.webp')";
|
||||||
return `url('/icon/bg/${props.data.star}-BGC.webp')`;
|
return `url('/icon/bg/${props.data.star}-BGC.webp')`;
|
||||||
});
|
});
|
||||||
|
|
||||||
function parseDesc() {
|
|
||||||
if (!props.data) return "";
|
|
||||||
return props.data.description.replace(/\\n/g, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function onCancel() {
|
function onCancel() {
|
||||||
console.log(props.data);
|
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,22 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<v-app-bar density="compact">
|
||||||
|
<template #prepend>
|
||||||
|
<div class="twm-title">
|
||||||
|
<div class="twm-title-left">
|
||||||
|
<img src="/source/UI/wikiGCG.webp" alt="icon" />
|
||||||
|
<span>材料图鉴</span>
|
||||||
|
</div>
|
||||||
|
<v-select
|
||||||
|
v-model="selectType"
|
||||||
|
:items="materialTypes"
|
||||||
|
item-title="type"
|
||||||
|
:hide-details="true"
|
||||||
|
:clearable="true"
|
||||||
|
width="250px"
|
||||||
|
label="材料类别"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
<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()"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-app-bar>
|
||||||
<div class="twm-box">
|
<div class="twm-box">
|
||||||
<div
|
<div
|
||||||
class="twm-item"
|
class="twm-item"
|
||||||
v-for="item in sortMaterialsData"
|
v-for="item in sortMaterialsData"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@click="toMaterial(item)"
|
@click="toMaterial(item)"
|
||||||
|
:title="item.name"
|
||||||
>
|
>
|
||||||
<div class="twm-item-left">
|
<div class="twm-item-left">
|
||||||
<div class="twm-item-bg">
|
<img class="twm-item-bg" :src="`/icon/bg/${item.star}-Star.webp`" alt="bg" />
|
||||||
<img :src="`/icon/bg/${item.star}-Star.webp`" alt="bg" />
|
<img class="twm-item-icon" :src="`/icon/material/${item.id}.webp`" alt="icon" />
|
||||||
</div>
|
|
||||||
<div class="twm-item-icon">
|
|
||||||
<img :src="`/icon/material/${item.id}.webp`" alt="icon" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="twm-item-right">
|
|
||||||
{{ item.name }}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="twm-item-right">{{ item.name }}</div>
|
||||||
|
<div class="twm-item-id">{{ item.id }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<TwoMaterial v-model="visible" :data="curMaterial">
|
<TwoMaterial v-model="visible" :data="curMaterial">
|
||||||
@@ -33,8 +68,9 @@
|
|||||||
</TwoMaterial>
|
</TwoMaterial>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
|
|
||||||
|
import showSnackbar from "../../components/func/snackbar.js";
|
||||||
import TwoMaterial from "../../components/wiki/two-material.vue";
|
import TwoMaterial from "../../components/wiki/two-material.vue";
|
||||||
import { WikiMaterialData } from "../../data/index.js";
|
import { WikiMaterialData } from "../../data/index.js";
|
||||||
|
|
||||||
@@ -44,7 +80,41 @@ const curIndex = ref(0);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
|
|
||||||
onMounted(() => sortData(WikiMaterialData));
|
interface MaterialType {
|
||||||
|
type: string;
|
||||||
|
number: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = ref<string>();
|
||||||
|
const selectType = ref<string | null>(null);
|
||||||
|
const materialTypes = ref<MaterialType[]>([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
WikiMaterialData.forEach((item: TGApp.App.Material.WikiItem) => {
|
||||||
|
const typeFindIndex = materialTypes.value.findIndex((itemT) => itemT.type === item.type);
|
||||||
|
if (typeFindIndex !== -1) {
|
||||||
|
materialTypes.value[typeFindIndex].number++;
|
||||||
|
} else {
|
||||||
|
const itemN: MaterialType = { type: item.type, number: 1 };
|
||||||
|
materialTypes.value.push(itemN);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sortData(WikiMaterialData);
|
||||||
|
showSnackbar({ text: `成功获取${sortMaterialsData.value.length}条数据` });
|
||||||
|
});
|
||||||
|
|
||||||
|
function getSelectMaterials(): TGApp.App.Material.WikiItem[] {
|
||||||
|
if (selectType.value === null) {
|
||||||
|
return WikiMaterialData;
|
||||||
|
} else {
|
||||||
|
return WikiMaterialData.filter((item) => item.type === selectType.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => selectType.value,
|
||||||
|
() => sortData(getSelectMaterials()),
|
||||||
|
);
|
||||||
|
|
||||||
function sortData(data: TGApp.App.Material.WikiItem[]) {
|
function sortData(data: TGApp.App.Material.WikiItem[]) {
|
||||||
sortMaterialsData.value = data;
|
sortMaterialsData.value = data;
|
||||||
@@ -73,29 +143,82 @@ function switchMaterial(isNext: boolean) {
|
|||||||
}
|
}
|
||||||
curMaterial.value = sortMaterialsData.value[curIndex.value];
|
curMaterial.value = sortMaterialsData.value[curIndex.value];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function searchMaterial() {
|
||||||
|
let selectData = getSelectMaterials();
|
||||||
|
if (search.value === undefined || search.value === "") {
|
||||||
|
if (sortMaterialsData.value.length === selectData.length) {
|
||||||
|
showSnackbar({ text: "请输入搜索内容!", color: "warn" });
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
sortData(selectData);
|
||||||
|
showSnackbar({ text: "已重置!" });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectData = selectData.filter(
|
||||||
|
(i) => i.name.includes(search.value!) || i.description.includes(search.value!),
|
||||||
|
);
|
||||||
|
if (selectData.length === 0) {
|
||||||
|
showSnackbar({ text: "未找到符合条件的材料!", color: "warn" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sortData(selectData);
|
||||||
|
showSnackbar({ text: `找到 ${selectData.length} 条符合条件的内容` });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
.twm-box {
|
.twm-title {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: center;
|
||||||
padding: 10px;
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
column-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.twm-title-left {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.twm-box {
|
||||||
|
display: grid;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(200px, 0.25fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.twm-item {
|
.twm-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding-right: 5px;
|
||||||
border: 1px solid var(--common-shadow-1);
|
border: 1px solid var(--common-shadow-1);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: var(--box-bg-1);
|
background: var(--box-bg-1);
|
||||||
|
column-gap: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
gap: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.twm-item-left {
|
.twm-item-left {
|
||||||
|
position: relative;
|
||||||
width: 45px;
|
width: 45px;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
border-bottom-left-radius: 5px;
|
border-bottom-left-radius: 5px;
|
||||||
@@ -112,21 +235,23 @@ function switchMaterial(isNext: boolean) {
|
|||||||
border-top-left-radius: 5px;
|
border-top-left-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twm-item-bg img,
|
|
||||||
.twm-item-icon img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
border-top-left-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.twm-item-right {
|
.twm-item-right {
|
||||||
display: flex;
|
position: relative;
|
||||||
align-items: center;
|
overflow: hidden;
|
||||||
justify-content: center;
|
max-width: 100%;
|
||||||
margin-right: 10px;
|
|
||||||
color: var(--box-text-2);
|
color: var(--box-text-2);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.twm-item-id {
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
bottom: 2px;
|
||||||
|
font-size: 8px;
|
||||||
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-arrow {
|
.card-arrow {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
label="请输入帖子 ID 或搜索词"
|
label="请输入帖子 ID 或搜索词"
|
||||||
:single-line="true"
|
:single-line="true"
|
||||||
:hide-details="true"
|
:hide-details="true"
|
||||||
@keyup.enter="searchPost()"
|
@keydown.enter="searchPost()"
|
||||||
@click:append="searchPost()"
|
@click:append="searchPost()"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user