🧑‍💻 回复数据导出&样式测试

This commit is contained in:
目棃
2024-09-04 20:14:16 +08:00
parent 60e8355d96
commit c34b9d2416
4 changed files with 202 additions and 9 deletions

View File

@@ -0,0 +1,125 @@
<template>
<TOverlay v-model="visible" hide :to-click="onCancel" blur-val="5px">
<div class="tpr-debug-box">
<div class="tpr-debug-title">
<span>文件</span>
<span :title="filePath">{{ filePath }}</span>
<v-btn @click="selectFile" color="primary">选择文件</v-btn>
</div>
<div class="tpr-debug-reply">
<TprReply mode="main" :modelValue="replyData" v-if="replyData !== null" />
</div>
</div>
</TOverlay>
</template>
<script lang="ts" setup>
import { open } from "@tauri-apps/plugin-dialog";
import { readTextFile } from "@tauri-apps/plugin-fs";
import { computed, ref } from "vue";
import showSnackbar from "../func/snackbar.js";
import TOverlay from "../main/t-overlay.vue";
import TprReply from "./tpr-reply.vue";
interface TprDebugProps {
modelValue: boolean;
}
interface TprDebugEmits {
(event: "update:modelValue", value: boolean): void;
}
const props = defineProps<TprDebugProps>();
const emits = defineEmits<TprDebugEmits>();
const visible = computed({
get: () => props.modelValue,
set: (value) => {
emits("update:modelValue", value);
},
});
const filePath = ref<string>("");
const replyData = ref<TGApp.Plugins.Mys.Reply.ReplyFull | null>(null);
function onCancel(): void {
visible.value = false;
}
async function selectFile(): Promise<void> {
const file = await open({
multiple: false,
directory: false,
filter: {
name: "JSON",
extensions: ["json"],
},
});
if (file === null) {
showSnackbar({
text: "未选择文件",
color: "error",
});
return;
}
filePath.value = file.path;
try {
const data = await readTextFile(file.path);
replyData.value = JSON.parse(data);
} catch (error) {
showSnackbar({
text: `解析失败:${error}`,
color: "error",
});
return;
}
}
</script>
<style lang="css" scoped>
.tpr-debug-box {
position: relative;
display: flex;
width: 400px;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 5px;
border-radius: 5px;
background: var(--box-bg-1);
box-shadow: 0 0 5px var(--common-shadow-1);
}
.tpr-debug-title {
display: flex;
overflow: hidden;
width: 100%;
align-items: center;
justify-content: space-between;
padding: 5px;
border-bottom: 1px solid var(--box-bg-2);
font-family: var(--font-title);
text-overflow: ellipsis;
white-space: nowrap;
:nth-child(2) {
overflow: hidden;
width: 300px;
color: var(--common-text-title);
text-overflow: ellipsis;
white-space: nowrap;
}
}
.tpr-debug-reply {
display: flex;
width: 100%;
min-height: 50px;
max-height: 300px;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 5px;
overflow-y: auto;
}
</style>

View File

@@ -21,7 +21,13 @@
<div class="tpr-main-reply">
<!-- 顶部负责显示回复条件&关闭按钮&刷新按钮 -->
<div class="tpr-main-filter">
<v-chip color="primary" label>回复列表</v-chip>
<v-chip
color="primary"
label
@click="handleDebug"
:style="{ cursor: appStore.devMode ? 'pointer' : 'not-allowed' }"
>回复列表
</v-chip>
<v-switch
v-model="onlyLz"
color="primary"
@@ -54,13 +60,16 @@
</div>
</v-menu>
</div>
<TprDebug v-if="appStore.devMode" v-model="showDebug" />
</template>
<script lang="ts" setup>
import { computed, ref, watch } from "vue";
import Mys from "../../plugins/Mys/index.js";
import { useAppStore } from "../../store/modules/app.js";
import showSnackbar from "../func/snackbar.js";
import TprDebug from "./tpr-debug.vue";
import TprReply from "./tpr-reply.vue";
interface TprMainProps {
@@ -69,18 +78,23 @@ interface TprMainProps {
}
const props = defineProps<TprMainProps>();
const reply = ref<Array<TGApp.Plugins.Mys.Reply.ReplyFull>>([]);
const lastId = ref<string | undefined>(undefined);
const isLast = ref<boolean>(false);
const loading = ref<boolean>(false);
const showOverlay = ref<boolean>(false);
const onlyLz = ref<boolean>(false);
const orderType = ref<"hot" | "latest" | "oldest">("hot");
const appStore = useAppStore();
const orderList = [
{ label: "热门", value: "hot" },
{ label: "最新", value: "latest" },
{ label: "最早", value: "oldest" },
];
const reply = ref<Array<TGApp.Plugins.Mys.Reply.ReplyFull>>([]);
const lastId = ref<string | undefined>(undefined);
const isLast = ref<boolean>(false);
const loading = ref<boolean>(false);
const showOverlay = ref<boolean>(false);
const showDebug = ref<boolean>(false);
const onlyLz = ref<boolean>(false);
const orderType = ref<"hot" | "latest" | "oldest">("hot");
const isHot = computed<boolean>(() => orderType.value === "hot");
const replyOrder = computed<1 | 2 | undefined>(() => {
if (orderType.value === "hot") return undefined;
@@ -137,6 +151,14 @@ async function loadReply(): Promise<void> {
});
}
}
function handleDebug(): void {
if (!appStore.devMode || showDebug.value) {
showDebug.value = false;
return;
}
showDebug.value = true;
}
</script>
<style lang="css" scoped>
.tpr-main-box {

View File

@@ -71,6 +71,9 @@
</div>
</div>
<div class="tpr-extra" :title="`ID:${props.modelValue.reply.reply_id}`">
<span class="tpr-debug" @click="exportData">
<v-icon size="small">mdi-file-export</v-icon>
</span>
<span v-if="props.modelValue.r_user" class="tpr-reply-user">
<span>回复</span>
<span>{{ props.modelValue.r_user.nickname }}</span>
@@ -80,9 +83,13 @@
</div>
</template>
<script lang="ts" setup>
import { path } from "@tauri-apps/api";
import { save } from "@tauri-apps/plugin-dialog";
import { writeTextFile } from "@tauri-apps/plugin-fs";
import { toRaw, ref } from "vue";
import Mys from "../../plugins/Mys/index.js";
import showConfirm from "../func/confirm.js";
import showSnackbar from "../func/snackbar.js";
import TpParser from "../post/tp-parser.vue";
@@ -148,6 +155,39 @@ async function loadSub(): Promise<void> {
});
}
}
async function exportData(): Promise<void> {
const confirm = await showConfirm({
title: "导出数据?",
text: "将回复对应的JSON数据导出到文件",
});
if (!confirm) {
showSnackbar({
text: "已取消",
color: "cancel",
});
return;
}
const data = JSON.stringify(toRaw(props.modelValue), null, 2);
const fileName = `reply_${props.modelValue.reply.post_id}_${props.modelValue.reply.floor_id}_${props.modelValue.reply.reply_id}`;
const savePath = await save({
title: "导出回复数据",
filters: [{ name: "JSON", extensions: ["json"] }],
defaultPath: `${await path.downloadDir()}${path.sep()}${fileName}.json`,
});
if (savePath === null) {
showSnackbar({
text: "已取消",
color: "cancel",
});
return;
}
await writeTextFile(savePath, data);
showSnackbar({
text: "导出成功",
color: "success",
});
}
</script>
<style lang="css" scoped>
.tpr-reply-box {
@@ -286,6 +326,13 @@ async function loadSub(): Promise<void> {
opacity: 0.3;
}
.tpr-debug {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.tpr-reply-user {
display: flex;
align-items: center;

View File

@@ -38,7 +38,6 @@
<!-- 右侧内容-->
<div class="right-wrap">
<div v-if="curCardName !== '' && selectedSeries !== -1 && !loading">
<!-- todo这边用 v-if 包装需要经过测试 -->
<TopNamecard :data="curCard" @selected="openImg()" v-if="curCard" />
</div>
<div