mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
♻️ showConfirm重构
This commit is contained in:
@@ -21,7 +21,7 @@ import { useRouter } from "vue-router";
|
||||
|
||||
import TBackTop from "./components/app/t-backTop.vue";
|
||||
import TSidebar from "./components/app/t-sidebar.vue";
|
||||
import showConfirm from "./components/func/confirm.js";
|
||||
import showDialog from "./components/func/dialog.js";
|
||||
import showSnackbar from "./components/func/snackbar.js";
|
||||
import TGSqlite from "./plugins/Sqlite/index.js";
|
||||
import TSUserAccount from "./plugins/Sqlite/modules/userAccount.js";
|
||||
@@ -247,11 +247,8 @@ async function checkUpdate(): Promise<void> {
|
||||
const needUpdate = await TGSqlite.checkUpdate();
|
||||
if (needUpdate && isProdEnv) {
|
||||
await TGLogger.Info("[App][checkUpdate] 检测到版本更新!");
|
||||
const confirm = await showConfirm({
|
||||
title: "检测到版本更新",
|
||||
text: "是否更新数据库数据?(请确保成就数据已导出)",
|
||||
});
|
||||
if (!confirm) {
|
||||
const updateCheck = await showDialog.check("检测到版本更新", "是否更新数据库数据?");
|
||||
if (!updateCheck) {
|
||||
showSnackbar.error("请到设置页手动更新数据库!", 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import { backUpUserData } from "../../utils/dataBS.js";
|
||||
import TGShell from "../../utils/TGShell.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
const appStore = storeToRefs(useAppStore());
|
||||
@@ -100,8 +100,8 @@ onMounted(async () => {
|
||||
|
||||
async function confirmCUD(): Promise<void> {
|
||||
const oriDir = appStore.userDir.value;
|
||||
const check = await showConfirm({ title: "确认修改用户数据路径吗?" });
|
||||
if (!check) {
|
||||
const changeCheck = await showDialog.check("确认修改用户数据路径吗?");
|
||||
if (!changeCheck) {
|
||||
showSnackbar.cancel("已取消修改");
|
||||
return;
|
||||
}
|
||||
@@ -122,8 +122,8 @@ async function confirmCUD(): Promise<void> {
|
||||
await TGSqlite.saveAppData("userDir", dir);
|
||||
await backUpUserData(dir);
|
||||
showSnackbar.success("已修改用户数据路径!");
|
||||
const confirm = await showConfirm({ title: "是否删除原用户数据目录?", text: "删除后不可恢复!" });
|
||||
if (confirm) {
|
||||
const delCheck = await showDialog.check("是否删除原用户数据目录?");
|
||||
if (delCheck) {
|
||||
await remove(oriDir, { recursive: true });
|
||||
showSnackbar.success("已删除原用户数据目录!");
|
||||
}
|
||||
@@ -136,11 +136,11 @@ async function confirmCGD(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
const oriEmpty = appStore.gameDir.value === "未设置";
|
||||
const editConfirm = await showConfirm({
|
||||
title: oriEmpty ? "确认设置目录?" : "确认修改目录?",
|
||||
text: oriEmpty ? "请选择启动器所在目录" : `当前:${appStore.gameDir.value}`,
|
||||
});
|
||||
if (!editConfirm) {
|
||||
const editCheck = await showDialog.check(
|
||||
oriEmpty ? "确认设置游戏目录?" : "确认修改游戏目录?",
|
||||
oriEmpty ? "请选择启动器所在目录" : `当前:${appStore.gameDir.value}`,
|
||||
);
|
||||
if (!editCheck) {
|
||||
showSnackbar.cancel(oriEmpty ? "已取消设置" : "已取消修改");
|
||||
return;
|
||||
}
|
||||
@@ -175,11 +175,8 @@ function isOverWeek(date: string): boolean {
|
||||
}
|
||||
|
||||
async function confirmCLD(): Promise<void> {
|
||||
const check = await showConfirm({
|
||||
title: "确认清理日志文件吗?",
|
||||
text: "将保留一周内的日志文件",
|
||||
});
|
||||
if (!check) {
|
||||
const delCheck = await showDialog.check("确认清理日志文件吗?", "将保留一周内的日志文件");
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消清理");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ import { useAppStore } from "../../store/modules/app.js";
|
||||
import { useUserStore } from "../../store/modules/user.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import TGRequest from "../../web/request/TGRequest.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showGeetest from "../func/geetest.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
@@ -139,7 +139,7 @@ const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
|
||||
});
|
||||
|
||||
async function tryCaptchaLogin(): Promise<void> {
|
||||
const phone = await showConfirm({ mode: "input", title: "请输入手机号", text: "+86" });
|
||||
const phone = await showDialog.input("请输入手机号", "+86");
|
||||
if (!phone) {
|
||||
showSnackbar.cancel("已取消验证码登录");
|
||||
return;
|
||||
@@ -152,12 +152,7 @@ async function tryCaptchaLogin(): Promise<void> {
|
||||
const actionType = await tryGetCaptcha(phone);
|
||||
if (!actionType) return;
|
||||
showSnackbar.success(`已发送验证码到 ${phone}`);
|
||||
const captcha = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入验证码",
|
||||
text: "验证码:",
|
||||
otcancel: false,
|
||||
});
|
||||
const captcha = await showDialog.input("请输入验证码", "验证码:", undefined, false);
|
||||
if (!captcha) {
|
||||
showSnackbar.warn("输入验证码为空");
|
||||
return;
|
||||
@@ -365,31 +360,28 @@ async function loadAccount(uid: string): Promise<void> {
|
||||
}
|
||||
|
||||
async function confirmRefreshUser(uid: string): Promise<void> {
|
||||
const res = await showConfirm({ title: "确认刷新用户信息吗?", text: "将会重新获取用户信息" });
|
||||
if (!res) {
|
||||
const freshCheck = await showDialog.check("确认刷新用户信息吗?", "将会重新获取用户信息");
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消刷新用户信息");
|
||||
return;
|
||||
}
|
||||
await refreshUser(uid);
|
||||
if (userStore.uid.value === uid) showSnackbar.success("成功刷新用户信息");
|
||||
const confirm = await showConfirm({ title: "是否切换用户?", text: `将切换到用户${uid}` });
|
||||
if (!confirm) return;
|
||||
const switchCheck = await showDialog.check("是否切换用户?", `将切换到用户${uid}`);
|
||||
if (!switchCheck) return;
|
||||
await loadAccount(uid);
|
||||
}
|
||||
|
||||
async function confirmCopyCookie(): Promise<void> {
|
||||
const res = await showConfirm({
|
||||
title: "确认复制 Cookie 吗?",
|
||||
text: "将会复制当前登录的 Cookie",
|
||||
});
|
||||
if (!res) {
|
||||
showSnackbar.cancel("已取消复制 Cookie");
|
||||
return;
|
||||
}
|
||||
if (!userStore.cookie.value) {
|
||||
showSnackbar.warn("请先登录");
|
||||
return;
|
||||
}
|
||||
const copyCheck = await showDialog.check("确认复制 Cookie 吗?", "将会复制当前登录的 Cookie");
|
||||
if (!copyCheck) {
|
||||
showSnackbar.cancel("已取消复制 Cookie");
|
||||
return;
|
||||
}
|
||||
const ckText = TSUserAccount.account.copy(userStore.cookie.value);
|
||||
await navigator.clipboard.writeText(ckText);
|
||||
showSnackbar.success("已复制 Cookie!");
|
||||
@@ -447,11 +439,7 @@ async function showAccounts(): Promise<void> {
|
||||
}
|
||||
|
||||
async function addByCookie(): Promise<void> {
|
||||
const ckInput = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入cookie",
|
||||
text: "Cookie:",
|
||||
});
|
||||
const ckInput = await showDialog.input("请输入Cookie", "Cookie:");
|
||||
if (!ckInput) {
|
||||
showSnackbar.cancel("已取消Cookie输入");
|
||||
return;
|
||||
@@ -553,8 +541,8 @@ async function clearUser(user: TGApp.App.Account.User): Promise<void> {
|
||||
showSnackbar.warn("当前登录用户不许删除!");
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({ title: "确认删除", text: "将删除账号及其游戏账号数据" });
|
||||
if (!confirm) {
|
||||
const delCheck = await showDialog.check("确认删除用户吗?", "将删除账号及其游戏账号数据");
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消删除用户数据");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
* @file component/func/confirm.ts
|
||||
* @description 封装自定义 confirm 组件,通过函数调用的方式,简化 confirm 的使用
|
||||
* @since Beta v0.3.9
|
||||
*/
|
||||
|
||||
import { h, render } from "vue";
|
||||
import type { ComponentInternalInstance, VNode } from "vue";
|
||||
|
||||
import confirm from "./confirm.vue";
|
||||
|
||||
const confirmId = "tg-func-confirm";
|
||||
|
||||
/**
|
||||
* @description 自定义 confirm 组件
|
||||
* @since Beta v0.3.4
|
||||
* @extends ComponentInternalInstance
|
||||
* @property {Function} exposeProxy.displayBox 显示 confirm
|
||||
* @return ConfirmInstance
|
||||
*/
|
||||
interface ConfirmInstance extends ComponentInternalInstance {
|
||||
exposeProxy: {
|
||||
displayBox: (props: TGApp.Component.Confirm.Params) => Promise<string | boolean>;
|
||||
};
|
||||
}
|
||||
|
||||
const renderBox = (props: TGApp.Component.Confirm.Params): VNode => {
|
||||
const container = document.createElement("div");
|
||||
container.id = confirmId;
|
||||
const boxVNode: VNode = h(confirm, props);
|
||||
render(boxVNode, container);
|
||||
document.body.appendChild(container);
|
||||
return boxVNode;
|
||||
};
|
||||
|
||||
let confirmInstance: VNode;
|
||||
|
||||
/**
|
||||
* @function showConfirm
|
||||
* @since Beta v0.3.9
|
||||
* @description 弹出 confirm
|
||||
* @param {TGApp.Component.Confirm.Params} props confirm 的参数
|
||||
* @return {Promise<string | boolean | undefined>} 点击确认返回 true,点击取消返回 false,点击外部返回 undefined
|
||||
*/
|
||||
async function showConfirm(
|
||||
props: TGApp.Component.Confirm.ParamsConfirm,
|
||||
): Promise<boolean | undefined>;
|
||||
async function showConfirm(
|
||||
props: TGApp.Component.Confirm.ParamsInput,
|
||||
): Promise<string | false | undefined>;
|
||||
async function showConfirm(
|
||||
props: TGApp.Component.Confirm.Params,
|
||||
): Promise<string | boolean | undefined>;
|
||||
async function showConfirm(
|
||||
props: TGApp.Component.Confirm.Params,
|
||||
): Promise<string | boolean | undefined> {
|
||||
if (confirmInstance !== undefined) {
|
||||
const boxVue = <ConfirmInstance>confirmInstance.component;
|
||||
return await boxVue.exposeProxy.displayBox(props);
|
||||
} else {
|
||||
confirmInstance = renderBox(props);
|
||||
return await showConfirm(props);
|
||||
}
|
||||
}
|
||||
|
||||
export default showConfirm;
|
||||
@@ -1,270 +0,0 @@
|
||||
<template>
|
||||
<transition name="func-confirm-outer">
|
||||
<div v-show="show || showOuter" class="confirm-overlay" @click.self.prevent="handleOuter">
|
||||
<transition name="func-confirm-inner">
|
||||
<div v-show="showInner" class="confirm-box">
|
||||
<div class="confirm-title">{{ data.title }}</div>
|
||||
<div
|
||||
v-show="data?.text !== '' && data.mode === 'confirm'"
|
||||
class="confirm-subtitle"
|
||||
:title="data.text"
|
||||
>
|
||||
{{ data.text }}
|
||||
</div>
|
||||
<div v-show="data?.text !== '' && data.mode === 'input'" class="confirm-input">
|
||||
<div class="confirm-input-label">{{ data.text }}</div>
|
||||
<input
|
||||
v-model="inputVal"
|
||||
class="confirm-input-box"
|
||||
ref="inputRef"
|
||||
@keydown.enter="handleConfirm"
|
||||
/>
|
||||
</div>
|
||||
<div class="confirm-btn-box">
|
||||
<button class="confirm-btn no-btn" @click="handleCancel">取消</button>
|
||||
<button class="confirm-btn ok-btn" @click="handleConfirm">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, reactive, ref, watch, useTemplateRef } from "vue";
|
||||
|
||||
interface ConfirmProps {
|
||||
title: string;
|
||||
text?: string;
|
||||
mode?: "confirm" | "input";
|
||||
otcancel?: boolean;
|
||||
}
|
||||
|
||||
const defaultProp: ConfirmProps = { title: "", text: "", mode: "confirm", otcancel: false };
|
||||
|
||||
const props = withDefaults(defineProps<ConfirmProps>(), {
|
||||
title: "",
|
||||
text: "",
|
||||
mode: "confirm",
|
||||
otcancel: false,
|
||||
});
|
||||
|
||||
// 组件参数
|
||||
const data = reactive<TGApp.Component.Confirm.Params>(defaultProp);
|
||||
const show = ref<boolean>(false);
|
||||
const showOuter = ref<boolean>(false);
|
||||
const showInner = ref<boolean>(false);
|
||||
const confirmVal = ref<boolean | string | undefined>();
|
||||
const inputVal = ref<string>("");
|
||||
const inputEl = useTemplateRef<HTMLInputElement>("inputRef");
|
||||
|
||||
watch(
|
||||
() => show.value,
|
||||
() => {
|
||||
if (show.value) {
|
||||
showOuter.value = true;
|
||||
setTimeout(() => (showInner.value = true), 100);
|
||||
return;
|
||||
}
|
||||
setTimeout(() => (showInner.value = false), 100);
|
||||
setTimeout(() => (showOuter.value = false), 300);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(async () => await displayBox(props));
|
||||
|
||||
async function displayBox(
|
||||
params: TGApp.Component.Confirm.Params,
|
||||
): Promise<string | boolean | undefined> {
|
||||
data.title = params.title;
|
||||
data.text = params.text ?? "";
|
||||
data.mode = params.mode ?? "confirm";
|
||||
data.otcancel = params.otcancel ?? true;
|
||||
if (params.mode === "input" && params.input) inputVal.value = params.input;
|
||||
show.value = true;
|
||||
// 等待确认框关闭,返回关闭后的confirmVal
|
||||
return await new Promise<string | boolean | undefined>((resolve) => {
|
||||
nextTick(() => {
|
||||
if (data.mode === "input") {
|
||||
// 等待确认框打开,聚焦输入框
|
||||
setTimeout(() => inputEl.value?.focus(), 100);
|
||||
}
|
||||
});
|
||||
watch(
|
||||
() => show.value,
|
||||
() => setTimeout(() => resolve(confirmVal.value), 500),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 确认
|
||||
function handleConfirm(): void {
|
||||
if (data.mode === "input") {
|
||||
confirmVal.value = inputVal.value;
|
||||
inputVal.value = "";
|
||||
} else {
|
||||
confirmVal.value = true;
|
||||
}
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
// 取消
|
||||
function handleCancel(): void {
|
||||
confirmVal.value = false;
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
// 点击外部事件
|
||||
function handleOuter(): void {
|
||||
if (data.otcancel) {
|
||||
confirmVal.value = undefined;
|
||||
show.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ displayBox });
|
||||
</script>
|
||||
<style scoped>
|
||||
.func-confirm-outer-enter-active,
|
||||
.func-confirm-outer-leave-active,
|
||||
.func-confirm-inner-enter-active {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.func-confirm-inner-leave-active {
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.func-confirm-inner-enter-from {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.func-confirm-inner-enter-to,
|
||||
.func-confirm-inner-leave-from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.func-confirm-outer-enter-to,
|
||||
.func-confirm-outer-leave-from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.func-confirm-outer-enter-from,
|
||||
.func-confirm-outer-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.func-confirm-inner-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.confirm-overlay {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
/* 颜色变量 */
|
||||
--confirm-title: var(--tgc-dark-7);
|
||||
--confirm-bg: var(--tgc-white-1);
|
||||
}
|
||||
|
||||
/* 深色模式 */
|
||||
.dark .confirm-overlay {
|
||||
--confirm-title: var(--tgc-white-1);
|
||||
--confirm-bg: var(--tgc-dark-7);
|
||||
}
|
||||
|
||||
.confirm-box {
|
||||
display: flex;
|
||||
width: 520px;
|
||||
height: 240px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 15px;
|
||||
background: var(--confirm-bg);
|
||||
box-shadow: 0 0 10px var(--common-shadow-t-1);
|
||||
color: var(--tgc-yellow-3);
|
||||
}
|
||||
|
||||
.confirm-title {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid var(--confirm-title);
|
||||
color: var(--confirm-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.confirm-subtitle {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
font-family: var(--font-text);
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.confirm-input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-text);
|
||||
font-size: 16px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.confirm-input-box {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
padding: 5px;
|
||||
border: 1px solid var(--confirm-title);
|
||||
border-radius: 5px;
|
||||
background: inherit;
|
||||
color: var(--confirm-title);
|
||||
}
|
||||
|
||||
.confirm-btn-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: flex-end;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 180px;
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.no-btn {
|
||||
border: 1px solid var(--tgc-yellow-1);
|
||||
}
|
||||
|
||||
.ok-btn {
|
||||
background: var(--confirm-title);
|
||||
}
|
||||
</style>
|
||||
113
src/components/func/dialog.ts
Normal file
113
src/components/func/dialog.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @file component/func/dialog.ts
|
||||
* @description dialog 组件封装,函数式调用
|
||||
* @since Beta v0.6.3
|
||||
*/
|
||||
|
||||
import { h, render } from "vue";
|
||||
import type { ComponentInternalInstance, VNode } from "vue";
|
||||
|
||||
import dialog from "./dialog.vue";
|
||||
|
||||
const dialogId = "tg-func-dialog";
|
||||
|
||||
export type DialogParams = DialogCheckParams | DialogInputParams;
|
||||
export type DialogCheckParams = {
|
||||
mode: "check";
|
||||
title: string;
|
||||
text?: string;
|
||||
otcancel?: boolean;
|
||||
};
|
||||
export type DialogInputParams = {
|
||||
mode: "input";
|
||||
title: string;
|
||||
text?: string;
|
||||
otcancel?: boolean;
|
||||
input?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 自定义 confirm 组件
|
||||
* @since Beta v0.6.3
|
||||
* @extends ComponentInternalInstance
|
||||
* @property {Function} exposeProxy.displayBox 显示 confirm
|
||||
* @return DialogInstance
|
||||
*/
|
||||
interface DialogInstance extends ComponentInternalInstance {
|
||||
exposeProxy: {
|
||||
displayCheckBox: (props: DialogCheckParams) => Promise<boolean | undefined>;
|
||||
displayInputBox: (props: DialogInputParams) => Promise<string | false | undefined>;
|
||||
};
|
||||
}
|
||||
|
||||
function renderBox(props: DialogParams): VNode {
|
||||
const container = document.createElement("div");
|
||||
container.id = dialogId;
|
||||
const boxVNode: VNode = h(dialog, props);
|
||||
render(boxVNode, container);
|
||||
document.body.appendChild(container);
|
||||
return boxVNode;
|
||||
}
|
||||
|
||||
let dialogInstance: VNode;
|
||||
|
||||
async function showDialogFull(
|
||||
mode: "check" | "input",
|
||||
title: string,
|
||||
text?: string,
|
||||
input?: string,
|
||||
otcancel?: boolean,
|
||||
): Promise<boolean | string | undefined> {
|
||||
if (mode === "check") return await showDialogCheck(title, text, otcancel);
|
||||
return await showDialogInput(title, text, input, otcancel);
|
||||
}
|
||||
|
||||
async function showDialogCheck(
|
||||
title: string,
|
||||
text?: string,
|
||||
otcancel?: boolean,
|
||||
): Promise<boolean | undefined> {
|
||||
const params: DialogCheckParams = {
|
||||
mode: "check",
|
||||
title: title,
|
||||
text: text,
|
||||
otcancel: otcancel,
|
||||
};
|
||||
if (dialogInstance !== undefined) {
|
||||
const boxVue = <DialogInstance>dialogInstance.component;
|
||||
return await boxVue.exposeProxy.displayCheckBox(params);
|
||||
} else {
|
||||
dialogInstance = renderBox(params);
|
||||
return await showDialogCheck(title, text, otcancel);
|
||||
}
|
||||
}
|
||||
|
||||
async function showDialogInput(
|
||||
title: string,
|
||||
text?: string,
|
||||
input?: string,
|
||||
otcancel?: boolean,
|
||||
): Promise<string | false | undefined> {
|
||||
const params: DialogInputParams = {
|
||||
mode: "input",
|
||||
title: title,
|
||||
text: text,
|
||||
input: input,
|
||||
otcancel: otcancel,
|
||||
};
|
||||
if (dialogInstance !== undefined) {
|
||||
const boxVue = <DialogInstance>dialogInstance.component;
|
||||
return await boxVue.exposeProxy.displayInputBox(params);
|
||||
} else {
|
||||
dialogInstance = renderBox(params);
|
||||
return await showDialogInput(title, text, input, otcancel);
|
||||
}
|
||||
}
|
||||
|
||||
const showDialog = {
|
||||
_: showDialogFull,
|
||||
check: showDialogCheck,
|
||||
input: showDialogInput,
|
||||
};
|
||||
|
||||
export default showDialog;
|
||||
294
src/components/func/dialog.vue
Normal file
294
src/components/func/dialog.vue
Normal file
@@ -0,0 +1,294 @@
|
||||
<template>
|
||||
<transition name="func-dialog-outer">
|
||||
<div v-show="show || showOuter" class="dialog-overlay" @click.self.prevent="handleOuter">
|
||||
<transition name="func-dialog-inner">
|
||||
<div v-show="showInner" class="dialog-box">
|
||||
<div class="dialog-title">{{ data.title }}</div>
|
||||
<div
|
||||
v-show="data?.text !== '' && data.mode === 'check'"
|
||||
class="dialog-subtitle"
|
||||
:title="data.text"
|
||||
>
|
||||
{{ data.text }}
|
||||
</div>
|
||||
<div v-show="data?.text !== '' && data.mode === 'input'" class="dialog-input">
|
||||
<div class="dialog-input-label">{{ data.text }}</div>
|
||||
<input
|
||||
v-model="inputDefault"
|
||||
class="dialog-input-box"
|
||||
ref="inputRef"
|
||||
@keydown.enter="handleConfirm"
|
||||
/>
|
||||
</div>
|
||||
<div class="dialog-btn-box">
|
||||
<button class="dialog-btn no-btn" @click="handleCancel">取消</button>
|
||||
<button class="dialog-btn ok-btn" @click="handleConfirm">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, reactive, ref, watch, useTemplateRef, computed } from "vue";
|
||||
|
||||
import { DialogCheckParams, DialogInputParams, DialogParams } from "./dialog.js";
|
||||
|
||||
const defaultProp: DialogParams = { title: "", text: "", mode: "check", otcancel: false };
|
||||
const props = defineProps<DialogParams>();
|
||||
|
||||
// 组件参数
|
||||
const data = reactive<DialogParams>(defaultProp);
|
||||
const show = ref<boolean>(false);
|
||||
const showOuter = ref<boolean>(false);
|
||||
const showInner = ref<boolean>(false);
|
||||
const dialogVal = ref<boolean | string | undefined>();
|
||||
|
||||
const inputDefault = ref<string>("");
|
||||
const inputEl = useTemplateRef<HTMLInputElement>("inputRef");
|
||||
|
||||
const checkVal = computed<boolean | undefined>(() => {
|
||||
if (typeof dialogVal.value === "string") return dialogVal.value !== "";
|
||||
return dialogVal.value;
|
||||
});
|
||||
const inputVal = computed<string | false | undefined>(() => {
|
||||
if (typeof dialogVal.value === "string") return dialogVal.value;
|
||||
if (dialogVal.value === undefined) return undefined;
|
||||
return false;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => show.value,
|
||||
() => {
|
||||
if (show.value) {
|
||||
showOuter.value = true;
|
||||
setTimeout(() => (showInner.value = true), 100);
|
||||
return;
|
||||
}
|
||||
setTimeout(() => (showInner.value = false), 100);
|
||||
setTimeout(() => (showOuter.value = false), 300);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
if (props.mode === "input") {
|
||||
const param: DialogInputParams = {
|
||||
mode: "input",
|
||||
title: props.title,
|
||||
text: props.text,
|
||||
input: props.input,
|
||||
otcancel: props.otcancel,
|
||||
};
|
||||
await displayInputBox(param);
|
||||
} else {
|
||||
const param: DialogCheckParams = {
|
||||
mode: "check",
|
||||
title: props.title,
|
||||
text: props.text,
|
||||
otcancel: props.otcancel,
|
||||
};
|
||||
await displayCheckBox(param);
|
||||
}
|
||||
});
|
||||
|
||||
async function displayCheckBox(params: DialogCheckParams): Promise<boolean | undefined> {
|
||||
data.title = params.title;
|
||||
data.text = params.text ?? "";
|
||||
data.mode = "check";
|
||||
data.otcancel = params.otcancel ?? true;
|
||||
show.value = true;
|
||||
return await new Promise<boolean | undefined>((resolve) => {
|
||||
watch(
|
||||
() => show.value,
|
||||
() => setTimeout(() => resolve(checkVal.value), 500),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function displayInputBox(params: DialogInputParams): Promise<string | false | undefined> {
|
||||
data.title = params.title;
|
||||
data.text = params.text ?? "";
|
||||
data.mode = "input";
|
||||
data.otcancel = params.otcancel ?? true;
|
||||
show.value = true;
|
||||
return await new Promise<string | false | undefined>((resolve) => {
|
||||
nextTick(() => setTimeout(() => inputEl.value?.focus(), 100));
|
||||
watch(
|
||||
() => show.value,
|
||||
() => setTimeout(() => resolve(inputVal.value), 500),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 确认
|
||||
function handleConfirm(): void {
|
||||
if (data.mode === "input") {
|
||||
dialogVal.value = inputDefault.value;
|
||||
inputDefault.value = "";
|
||||
} else {
|
||||
dialogVal.value = true;
|
||||
}
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
// 取消
|
||||
function handleCancel(): void {
|
||||
dialogVal.value = false;
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
// 点击外部事件
|
||||
function handleOuter(): void {
|
||||
if (data.otcancel) {
|
||||
dialogVal.value = undefined;
|
||||
show.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ displayInputBox, displayCheckBox });
|
||||
</script>
|
||||
<style scoped>
|
||||
.func-dialog-outer-enter-active,
|
||||
.func-dialog-outer-leave-active,
|
||||
.func-dialog-inner-enter-active {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.func-dialog-inner-leave-active {
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.func-dialog-inner-enter-from {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.func-dialog-inner-enter-to,
|
||||
.func-dialog-inner-leave-from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.func-dialog-outer-enter-to,
|
||||
.func-dialog-outer-leave-from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.func-dialog-outer-enter-from,
|
||||
.func-dialog-outer-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.func-dialog-inner-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.dialog-overlay {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
/* 颜色变量 */
|
||||
--dialog-title: var(--tgc-dark-7);
|
||||
--dialog-bg: var(--tgc-white-1);
|
||||
}
|
||||
|
||||
/* 深色模式 */
|
||||
.dark .dialog-overlay {
|
||||
--dialog-title: var(--tgc-white-1);
|
||||
--dialog-bg: var(--tgc-dark-7);
|
||||
}
|
||||
|
||||
.dialog-box {
|
||||
display: flex;
|
||||
width: 520px;
|
||||
height: 240px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 15px;
|
||||
background: var(--dialog-bg);
|
||||
box-shadow: 0 0 10px var(--common-shadow-t-1);
|
||||
color: var(--tgc-yellow-3);
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid var(--dialog-title);
|
||||
color: var(--dialog-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog-subtitle {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
font-family: var(--font-text);
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.dialog-input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-text);
|
||||
font-size: 16px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.dialog-input-box {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
padding: 5px;
|
||||
border: 1px solid var(--dialog-title);
|
||||
border-radius: 5px;
|
||||
background: inherit;
|
||||
color: var(--dialog-title);
|
||||
}
|
||||
|
||||
.dialog-btn-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: flex-end;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.dialog-btn {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 180px;
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.no-btn {
|
||||
border: 1px solid var(--tgc-yellow-1);
|
||||
}
|
||||
|
||||
.ok-btn {
|
||||
background: var(--dialog-title);
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file component func snackbar.ts
|
||||
* @description 封装 vuetify 的 snackbar 组件,通过函数调用的方式,简化 snackbar 的使用
|
||||
* @file component/func/snackbar.ts
|
||||
* @description snackbar 组件封装,函数式调用
|
||||
* @since Beta v0.6.3
|
||||
*/
|
||||
|
||||
@@ -11,32 +11,32 @@ import snackbar from "./snackbar.vue";
|
||||
|
||||
const snackbarId = "tg-func-snackbar";
|
||||
|
||||
export type SnackbarParams = { text: string; color: string; timeout: number };
|
||||
|
||||
/**
|
||||
* @description 自定义 snackbar 组件
|
||||
* @since Beta v0.3.3
|
||||
* @extends ComponentInternalInstance
|
||||
* @property {Function} exposeProxy.displayBox 显示 snackbar
|
||||
* @since Beta v0.6.3
|
||||
* @return SnackbarInstance
|
||||
*/
|
||||
interface SnackbarInstance extends ComponentInternalInstance {
|
||||
exposeProxy: {
|
||||
displayBox: (props: TGApp.Component.Snackbar.Params) => void;
|
||||
displayBox: (props: SnackbarParams) => void;
|
||||
};
|
||||
}
|
||||
|
||||
const renderBox = (props: TGApp.Component.Snackbar.Params): VNode => {
|
||||
function renderBox(props: SnackbarParams): VNode {
|
||||
const container = document.createElement("div");
|
||||
container.id = snackbarId;
|
||||
const boxVNode: VNode = h(snackbar, props);
|
||||
render(boxVNode, container);
|
||||
document.body.appendChild(container);
|
||||
return boxVNode;
|
||||
};
|
||||
}
|
||||
|
||||
let snackbarInstance: VNode;
|
||||
|
||||
function showSnackbarFull(text: string, color?: string, timeout?: number): void {
|
||||
const params: TGApp.Component.Snackbar.Params = {
|
||||
const params: SnackbarParams = {
|
||||
text: text,
|
||||
color: color ?? "success",
|
||||
timeout: timeout ?? 1500,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<transition name="func-snackbar">
|
||||
<div class="func-snackbar-container" v-show="show">
|
||||
<div class="func-snackbar" :style="{ backgroundColor: data.color }">
|
||||
<div class="func-snackbar">
|
||||
<slot name="text">
|
||||
<span class="func-snackbar-text">{{ data.text }}</span>
|
||||
</slot>
|
||||
@@ -10,18 +10,14 @@
|
||||
</transition>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, toRaw } from "vue";
|
||||
import { computed, onMounted, ref, toRaw } from "vue";
|
||||
|
||||
interface SnackbarProps {
|
||||
text: string;
|
||||
color: string;
|
||||
timeout: number;
|
||||
}
|
||||
import { SnackbarParams } from "./snackbar.js";
|
||||
|
||||
const props = defineProps<SnackbarProps>();
|
||||
const data = ref<TGApp.Component.Snackbar.Params>(toRaw(props));
|
||||
// 组件参数
|
||||
const props = defineProps<SnackbarParams>();
|
||||
const data = ref<SnackbarParams>(toRaw(props));
|
||||
const show = ref<boolean>(false);
|
||||
const bgColor = computed(() => data.value.color);
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let timer: NodeJS.Timeout | undefined = undefined;
|
||||
@@ -99,6 +95,7 @@ defineExpose({ displayBox });
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
background-color: v-bind(bgColor);
|
||||
box-shadow: 0 0 10px rgb(0 0 0 / 20%);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ import { useRouter } from "vue-router";
|
||||
import { AppGachaData, AppCharacterData, AppWeaponData } from "../../data/index.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import { timestampToDate } from "../../utils/toolFunc.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
@@ -90,20 +90,20 @@ onMounted(() => {
|
||||
async function toWiki(id: number): Promise<void> {
|
||||
const cFind = AppCharacterData.find((item) => item.id === id);
|
||||
const wFind = AppWeaponData.find((item) => item.id === id);
|
||||
const confirm = await showConfirm({
|
||||
title: "是否跳转到对应图鉴界面?",
|
||||
});
|
||||
if (confirm === undefined || confirm === false) {
|
||||
const jumpCheck = await showDialog.check("是否跳转到对应图鉴界面?");
|
||||
if (!jumpCheck) {
|
||||
showSnackbar.cancel("已取消");
|
||||
return;
|
||||
}
|
||||
if (cFind) {
|
||||
await router.push({ name: "角色图鉴", params: { id: id.toString() } });
|
||||
} else if (wFind) {
|
||||
await router.push({ name: "武器图鉴", params: { id: id.toString() } });
|
||||
} else {
|
||||
showSnackbar.warn("未找到对应角色或武器");
|
||||
return;
|
||||
}
|
||||
if (wFind) {
|
||||
await router.push({ name: "武器图鉴", params: { id: id.toString() } });
|
||||
return;
|
||||
}
|
||||
showSnackbar.warn("未找到对应角色或武器");
|
||||
}
|
||||
|
||||
function getType(type: TGApp.App.Gacha.WishType): string {
|
||||
|
||||
@@ -20,7 +20,7 @@ import TGClient from "../../utils/TGClient.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import TGRequest from "../../web/request/TGRequest.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import ToLivecode from "../overlay/to-livecode.vue";
|
||||
|
||||
@@ -103,16 +103,13 @@ async function toNav(item: TGApp.BBS.Navigator.Navigator): Promise<void> {
|
||||
await TGClient.open("web_act_thin", item.app_path);
|
||||
return;
|
||||
}
|
||||
const modeConfirm = await showConfirm({
|
||||
title: "是否采用宽屏模式打开?",
|
||||
text: "取消则采用竖屏模式打开",
|
||||
});
|
||||
if (modeConfirm === undefined) {
|
||||
const modeCheck = await showDialog.check("是否采用宽屏模式打开?", "取消则采用竖屏模式打开");
|
||||
if (modeCheck === undefined) {
|
||||
showSnackbar.cancel("已取消打开");
|
||||
return;
|
||||
}
|
||||
if (modeConfirm) await TGClient.open("web_act", item.app_path);
|
||||
else await TGClient.open("web_act_thin", item.app_path);
|
||||
if (!modeCheck) await TGClient.open("web_act_thin", item.app_path);
|
||||
else await TGClient.open("web_act", item.app_path);
|
||||
}
|
||||
|
||||
// 处理 protocol
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
@@ -73,10 +73,7 @@ async function onSubmit(): Promise<void> {
|
||||
}
|
||||
submit.value = true;
|
||||
let force = false;
|
||||
const forceCheck = await showConfirm({
|
||||
title: "是否保留原分类",
|
||||
text: "若否则仅保留新分类",
|
||||
});
|
||||
const forceCheck = await showDialog.check("是否保留原分类", "若否则仅保留新分类");
|
||||
if (forceCheck === false) force = true;
|
||||
const check = await TSUserCollection.updatePostsCollect(props.post, select.value, force);
|
||||
if (!check) {
|
||||
@@ -92,11 +89,7 @@ async function onSubmit(): Promise<void> {
|
||||
|
||||
async function newCollect(): Promise<void> {
|
||||
let title, desc;
|
||||
const titleC = await showConfirm({
|
||||
mode: "input",
|
||||
title: "新建分类",
|
||||
text: "请输入分类名称",
|
||||
});
|
||||
const titleC = await showDialog.input("新建分类", "请输入分类名称");
|
||||
if (titleC === undefined || titleC === false) return;
|
||||
if (titleC === "未分类") {
|
||||
showSnackbar.warn("分类名不可为未分类");
|
||||
@@ -107,11 +100,7 @@ async function newCollect(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
title = titleC;
|
||||
const descC = await showConfirm({
|
||||
mode: "input",
|
||||
title: "新建分类",
|
||||
text: "请输入分类描述",
|
||||
});
|
||||
const descC = await showDialog.input("新建分类", "请输入分类描述");
|
||||
if (descC === false) return;
|
||||
if (descC === undefined) desc = title;
|
||||
else desc = descC;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
@@ -89,11 +89,8 @@ const visible = computed({
|
||||
});
|
||||
|
||||
async function deleteCollect(item: TGApp.Sqlite.UserCollection.UFCollection): Promise<void> {
|
||||
const res = await showConfirm({
|
||||
title: "确定删除分类?",
|
||||
text: "该分类若有帖子,则会变为未分类",
|
||||
});
|
||||
if (!res) {
|
||||
const delCheck = await showDialog.check("确定删除分类?", "该分类若有帖子,则会变为未分类");
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("取消删除");
|
||||
return;
|
||||
}
|
||||
@@ -108,11 +105,7 @@ async function deleteCollect(item: TGApp.Sqlite.UserCollection.UFCollection): Pr
|
||||
|
||||
async function newCollect(): Promise<void> {
|
||||
let title, desc;
|
||||
const titleC = await showConfirm({
|
||||
mode: "input",
|
||||
title: "新建分类",
|
||||
text: "请输入分类名称",
|
||||
});
|
||||
const titleC = await showDialog.input("新建分类", "请输入分类名称");
|
||||
if (titleC === undefined || titleC === false) return;
|
||||
if (titleC === "未分类") {
|
||||
showSnackbar.warn("分类名不可为未分类");
|
||||
@@ -123,11 +116,7 @@ async function newCollect(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
title = titleC;
|
||||
const descC = await showConfirm({
|
||||
mode: "input",
|
||||
title: "新建分类",
|
||||
text: "请输入分类描述",
|
||||
});
|
||||
const descC = await showDialog.input("新建分类", "请输入分类描述");
|
||||
if (descC === false) return;
|
||||
if (descC === undefined) desc = title;
|
||||
else desc = descC;
|
||||
|
||||
@@ -17,7 +17,7 @@ import { onBeforeMount, ref, watch } from "vue";
|
||||
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import ToPostCollect from "../overlay/to-postCollect.vue";
|
||||
|
||||
@@ -82,13 +82,8 @@ async function switchCollect(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
if (collect.value.length > 1) {
|
||||
const check = await showConfirm({
|
||||
title: "确定取消收藏?",
|
||||
text: "该帖子有多个收藏分类,是否全部取消?",
|
||||
});
|
||||
if (!check) {
|
||||
return;
|
||||
}
|
||||
const check = await showDialog.check("确定取消收藏?", "该帖子有多个收藏分类,是否全部取消?");
|
||||
if (!check) return;
|
||||
}
|
||||
await TSUserCollection.deletePostCollect(props.modelValue.toString(), true);
|
||||
await event.emit("refreshCollect");
|
||||
|
||||
@@ -108,7 +108,7 @@ import { toRaw, ref, watch, computed, onMounted, onUnmounted } from "vue";
|
||||
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { generateShareImg } from "../../utils/TGShare.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TpParser from "../post/tp-parser.vue";
|
||||
|
||||
@@ -226,12 +226,9 @@ async function loadSub(): Promise<void> {
|
||||
}
|
||||
|
||||
async function exportData(): Promise<void> {
|
||||
const confirm = await showConfirm({
|
||||
title: "导出数据?",
|
||||
text: "将回复对应的JSON数据导出到文件",
|
||||
});
|
||||
if (!confirm) {
|
||||
showSnackbar.cancel("已取消");
|
||||
const exportCheck = await showDialog.check("导出数据", "是否导出回复数据?");
|
||||
if (!exportCheck) {
|
||||
showSnackbar.cancel("已取消导出该回复数据");
|
||||
return;
|
||||
}
|
||||
const data = JSON.stringify(toRaw(props.modelValue), null, 2);
|
||||
|
||||
@@ -36,7 +36,7 @@ import { toRaw, ref, watch } from "vue";
|
||||
import { AppAchievementSeriesData } from "../../data/index.js";
|
||||
import TSUserAchi from "../../plugins/Sqlite/modules/userAchi.js";
|
||||
import { timestampToDate } from "../../utils/toolFunc.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showDialog from "../func/dialog.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
interface TuaAchiProps {
|
||||
@@ -81,12 +81,7 @@ async function setAchiStat(stat: boolean): Promise<void> {
|
||||
showSnackbar.success(`已将成就 ${data.value.name}(${data.value.id}) 状态设为未完成`);
|
||||
return;
|
||||
}
|
||||
let progress: boolean | undefined | string = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入成就进度",
|
||||
text: "进度",
|
||||
input: data.value.progress,
|
||||
});
|
||||
let progress = await showDialog.input("请输入成就进度", "进度", data.value.progress.toString());
|
||||
if (progress === false) {
|
||||
showSnackbar.cancel("已取消成就编辑");
|
||||
return;
|
||||
|
||||
@@ -115,7 +115,7 @@ import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, watch, computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TSubLine from "../../components/main/t-subline.vue";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
@@ -196,20 +196,20 @@ async function refreshAbyss(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
if (uidCur.value && uidCur.value !== user.value.gameUid) {
|
||||
const confirmSwitch = await showConfirm({
|
||||
title: "是否切换游戏账户",
|
||||
text: `确认则尝试切换至 ${uidCur.value}`,
|
||||
});
|
||||
if (confirmSwitch) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至 ${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value);
|
||||
await refreshAbyss();
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定刷新?",
|
||||
text: `用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const freshCheck = await showDialog.check(
|
||||
"确定刷新?",
|
||||
`用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消深渊数据刷新");
|
||||
return;
|
||||
}
|
||||
@@ -321,11 +321,8 @@ async function deleteAbyss(): Promise<void> {
|
||||
showSnackbar.warn("未选择游戏UID");
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定删除数据?",
|
||||
text: `将清除${uidCur.value}的所有深渊数据`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const delCheck = await showDialog.check("确定删除数据?", `将清除${uidCur.value}的所有深渊数据`);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消删除");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ import { getVersion } from "@tauri-apps/api/app";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, watch, computed } from "vue";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
import TuaAvatarBox from "../../components/userAvatar/tua-avatar-box.vue";
|
||||
@@ -252,20 +252,20 @@ async function refresh(): Promise<void> {
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
}
|
||||
if (uidCur.value && uidCur.value !== user.value.gameUid) {
|
||||
const switchConfirm = await showConfirm({
|
||||
title: "是否切换游戏账户",
|
||||
text: `确认则尝试切换至${uidCur.value}`,
|
||||
});
|
||||
if (switchConfirm) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value);
|
||||
await refresh();
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定刷新?",
|
||||
text: `用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const freshCheck = await showDialog.check(
|
||||
"是否刷新角色数据",
|
||||
`用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消角色数据刷新");
|
||||
return;
|
||||
}
|
||||
@@ -353,11 +353,8 @@ async function deleteUid(): Promise<void> {
|
||||
showSnackbar.warn("未找到当前UID");
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定删除?",
|
||||
text: `将删除${uidCur.value}对应的角色数据`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const delCheck = await showDialog.check("确定删除?", `将删除${uidCur.value}对应的角色数据`);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消删除");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, watch, computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TSubLine from "../../components/main/t-subline.vue";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
@@ -167,20 +167,20 @@ async function refreshCombat(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
if (uidCur.value && uidCur.value !== user.value.gameUid) {
|
||||
const confirmSwitch = await showConfirm({
|
||||
title: "是否切换游戏账户",
|
||||
text: `确认则尝试切换至 ${uidCur.value}`,
|
||||
});
|
||||
if (confirmSwitch) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至 ${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value);
|
||||
await refreshCombat();
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定刷新?",
|
||||
text: `用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const freshCheck = await showDialog.check(
|
||||
"确定刷新?",
|
||||
`用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消剧诗数据刷新");
|
||||
return;
|
||||
}
|
||||
@@ -279,11 +279,8 @@ async function deleteCombat(): Promise<void> {
|
||||
showSnackbar.error("未找到符合条件的数据!");
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定删除数据?",
|
||||
text: `将清除${uidCur.value}的所有剧诗数据`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const delCheck = await showDialog.check("确定删除数据?", `将清除${uidCur.value}的所有剧诗数据`);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消删除");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ import { open, save } from "@tauri-apps/plugin-dialog";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, watch, computed } from "vue";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import GroEcharts from "../../components/gachaRecord/gro-echarts.vue";
|
||||
import GroHistory from "../../components/gachaRecord/gro-history.vue";
|
||||
@@ -129,20 +129,20 @@ onMounted(async () => {
|
||||
async function confirmRefresh(force: boolean): Promise<void> {
|
||||
await TGLogger.Info(`[UserGacha][${account.value.gameUid}][confirmRefresh] 刷新祈愿数据`);
|
||||
if (uidCur.value && uidCur.value !== account.value.gameUid) {
|
||||
const confirmSwitch = await showConfirm({
|
||||
title: "是否切换游戏账户",
|
||||
text: `确认则尝试切换至 ${uidCur.value}`,
|
||||
});
|
||||
if (confirmSwitch) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至 ${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value);
|
||||
await confirmRefresh(force);
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定刷新?",
|
||||
text: `用户${account.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const freshCheck = await showDialog.check(
|
||||
"确定刷新?",
|
||||
`用户${account.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消祈愿数据刷新");
|
||||
return;
|
||||
}
|
||||
@@ -297,11 +297,11 @@ async function importUigf4(filePath: string): Promise<void> {
|
||||
const remoteData = await readUigf4Data(filePath);
|
||||
const uidCount = remoteData.hk4e.length;
|
||||
const dataCount = remoteData.hk4e.reduce((acc, cur) => acc + cur.list.length, 0);
|
||||
const res = await showConfirm({
|
||||
title: "是否导入祈愿数据?",
|
||||
text: `共 ${uidCount} 个 UID,${dataCount} 条数据`,
|
||||
});
|
||||
if (!res) {
|
||||
const importCheck = await showDialog.check(
|
||||
"是否导入祈愿数据?",
|
||||
`共 ${uidCount} 个 UID,${dataCount} 条数据`,
|
||||
);
|
||||
if (!importCheck) {
|
||||
showSnackbar.cancel("已取消祈愿数据导入");
|
||||
return;
|
||||
}
|
||||
@@ -321,11 +321,11 @@ async function importUigf4(filePath: string): Promise<void> {
|
||||
|
||||
async function importUigf(filePath: string): Promise<void> {
|
||||
const remoteData = await readUigfData(filePath);
|
||||
const confirm = await showConfirm({
|
||||
title: "是否导入祈愿数据?",
|
||||
text: `UID:${remoteData.info.uid},共 ${remoteData.list.length} 条数据`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const importCheck = await showDialog.check(
|
||||
"是否导入祈愿数据?",
|
||||
`UID:${remoteData.info.uid},共 ${remoteData.list.length} 条数据`,
|
||||
);
|
||||
if (!importCheck) {
|
||||
showSnackbar.cancel("已取消祈愿数据导入");
|
||||
return;
|
||||
}
|
||||
@@ -354,11 +354,11 @@ async function exportUigf(): Promise<void> {
|
||||
showSnackbar.error(`UID ${uidCur.value} 暂无祈愿数据`);
|
||||
return;
|
||||
}
|
||||
const res = await showConfirm({
|
||||
title: "是否导出祈愿数据?",
|
||||
text: `UID:${uidCur.value},共 ${gachaList.length} 条数据`,
|
||||
});
|
||||
if (!res) {
|
||||
const exportCheck = await showDialog.check(
|
||||
"是否导出祈愿数据?",
|
||||
`UID:${uidCur.value},共 ${gachaList.length} 条数据`,
|
||||
);
|
||||
if (!exportCheck) {
|
||||
showSnackbar.cancel(`已取消 UID ${uidCur.value} 的祈愿数据导出`);
|
||||
return;
|
||||
}
|
||||
@@ -385,22 +385,22 @@ async function exportUigf(): Promise<void> {
|
||||
// 导出 UIGF v4 版本的祈愿数据
|
||||
async function exportUigf4(): Promise<void> {
|
||||
if (!uidCur.value) return;
|
||||
const checkConfirm = await showConfirm({ title: "确定导出UIGFv4格式的祈愿数据?" });
|
||||
if (!checkConfirm) {
|
||||
const exportCheck = await showDialog.check("确定导出UIGFv4格式的祈愿数据?");
|
||||
if (!exportCheck) {
|
||||
showSnackbar.cancel("已取消 UIGF v4 格式导出");
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[UserGacha][${uidCur.value}][exportUigf4] 导出祈愿数据(v4)`);
|
||||
// todo 单开一个overlay用于选取导出的UID
|
||||
const allConfirm = await showConfirm({
|
||||
title: "是否导出所有 UID 的祈愿数据?",
|
||||
text: "取消则只导出当前 UID 的祈愿数据",
|
||||
});
|
||||
if (allConfirm === undefined) {
|
||||
const exportAllCheck = await showDialog.check(
|
||||
"是否导出所有 UID 的祈愿数据?",
|
||||
"取消则只导出当前 UID 的祈愿数据",
|
||||
);
|
||||
if (exportAllCheck === undefined) {
|
||||
showSnackbar.cancel("已取消 UIGF v4 格式导出");
|
||||
return;
|
||||
}
|
||||
if (!allConfirm) {
|
||||
if (!exportAllCheck) {
|
||||
const gachaList = await TSUserGacha.getGachaRecords(uidCur.value);
|
||||
if (gachaList.length === 0) {
|
||||
showSnackbar.error(`UID ${uidCur.value} 暂无祈愿数据`);
|
||||
@@ -418,7 +418,7 @@ async function exportUigf4(): Promise<void> {
|
||||
}
|
||||
loadingTitle.value = "正在导出祈愿数据";
|
||||
loading.value = true;
|
||||
if (!allConfirm) {
|
||||
if (!exportAllCheck) {
|
||||
await exportUigf4Data(file, uidCur.value);
|
||||
} else {
|
||||
await exportUigf4Data(file);
|
||||
@@ -435,25 +435,20 @@ async function deleteGacha(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 删除祈愿数据`);
|
||||
const firstConfirm = await showConfirm({
|
||||
title: "是否删除祈愿数据?",
|
||||
text: `UID:${uidCur.value},共 ${gachaListCur.value.length} 条数据`,
|
||||
});
|
||||
if (!firstConfirm) {
|
||||
const delCheck = await showDialog.check(
|
||||
"确定删除祈愿数据?",
|
||||
`UID:${uidCur.value},共 ${gachaListCur.value.length} 条数据`,
|
||||
);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消祈愿数据删除");
|
||||
await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 已取消祈愿数据删除`);
|
||||
return;
|
||||
}
|
||||
const uidList = await TSUserGacha.getUidList();
|
||||
let secondConfirm: string | boolean | undefined;
|
||||
if (uidList.length <= 1) {
|
||||
secondConfirm = await showConfirm({
|
||||
title: "删除后数据库将为空,确定删除?",
|
||||
text: `UID:${uidCur.value},共 ${gachaListCur.value.length} 条数据`,
|
||||
});
|
||||
if (!secondConfirm) {
|
||||
const forceCheck = await showDialog.check("删除后数据库将为空,确定删除?");
|
||||
if (!forceCheck) {
|
||||
showSnackbar.cancel("已取消祈愿数据删除");
|
||||
await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 已取消祈愿数据删除`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ import { getVersion } from "@tauri-apps/api/app";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TSubLine from "../../components/main/t-subline.vue";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
@@ -125,20 +125,20 @@ async function loadRecord(): Promise<void> {
|
||||
async function refreshRecord(): Promise<void> {
|
||||
if (!user.value) return;
|
||||
if (uidCur.value && uidCur.value.toString() !== user.value.gameUid) {
|
||||
const switchConfirm = await showConfirm({
|
||||
title: "是否切换游戏账户",
|
||||
text: `确认则尝试切换至${uidCur.value}`,
|
||||
});
|
||||
if (switchConfirm) {
|
||||
const switchCheck = await showDialog.check(
|
||||
"是否切换游戏账户",
|
||||
`确认则尝试切换至${uidCur.value}`,
|
||||
);
|
||||
if (switchCheck) {
|
||||
await useUserStore().switchGameAccount(uidCur.value.toString());
|
||||
await refreshRecord();
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定刷新?",
|
||||
text: `用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const freshCheck = await showDialog.check(
|
||||
"是否刷新战绩数据",
|
||||
`用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
);
|
||||
if (!freshCheck) {
|
||||
showSnackbar.cancel("已取消战绩数据刷新");
|
||||
return;
|
||||
}
|
||||
@@ -198,11 +198,8 @@ async function deleteRecord(): Promise<void> {
|
||||
showSnackbar.warn("未找到当前UID");
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定删除?",
|
||||
text: `将删除${uidCur.value}对应的战绩数据`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const delCheck = await showDialog.check("确定删除?", `将删除${uidCur.value}对应的战绩数据`);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消删除战绩数据");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
import { onBeforeMount, ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TwcCharacter from "../../components/wiki/twc-character.vue";
|
||||
import TwcListItem from "../../components/wiki/twc-list-item.vue";
|
||||
@@ -99,11 +99,8 @@ async function toOuter(item?: TGApp.App.Character.WikiBriefInfo): Promise<void>
|
||||
showSnackbar.warn(`角色 ${item.name} 暂无观测枢页面`);
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: `角色 ${item.name} 暂无数据`,
|
||||
text: "是否打开观测枢页面?",
|
||||
});
|
||||
if (!confirm) {
|
||||
const openCheck = await showDialog.check(`角色 ${item.name} 暂无数据`, "是否打开观测枢页面?");
|
||||
if (!openCheck) {
|
||||
showSnackbar.cancel("已取消打开观测枢页面");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import { onBeforeMount, ref } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TwcListItem from "../../components/wiki/twc-list-item.vue";
|
||||
import TwcWeapon from "../../components/wiki/twc-weapon.vue";
|
||||
@@ -92,11 +92,8 @@ async function toOuter(item?: TGApp.App.Weapon.WikiBriefInfo): Promise<void> {
|
||||
showSnackbar.warn(`武器 ${item.name} 暂无观测枢页面`);
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: `武器 ${item.name} 暂无数据`,
|
||||
text: "是否打开观测枢页面?",
|
||||
});
|
||||
if (!confirm) {
|
||||
const check = await showDialog.check(`武器 ${item.name} 暂无数据`, "是否打开观测枢页面?");
|
||||
if (!check) {
|
||||
showSnackbar.cancel("已取消打开观测枢页面");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ import { writeTextFile } from "@tauri-apps/plugin-fs";
|
||||
import { onMounted, ref, watch, computed, onUnmounted } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
import TuaAchiList from "../../components/userAchi/tua-achi-list.vue";
|
||||
@@ -151,12 +151,7 @@ async function importJson(): Promise<void> {
|
||||
}
|
||||
const check = await verifyUiafData(selectedFile);
|
||||
if (!check) return;
|
||||
let uidInput = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入存档UID",
|
||||
text: "UID:",
|
||||
input: uidCur.value.toString(),
|
||||
});
|
||||
let uidInput = await showDialog.input("请输入存档UID", "UID:", uidCur.value.toString());
|
||||
if (uidInput === false) {
|
||||
showSnackbar.cancel("已取消存档导入");
|
||||
return;
|
||||
@@ -211,25 +206,16 @@ async function exportJson(): Promise<void> {
|
||||
|
||||
async function handleImportOuter(app: string): Promise<void> {
|
||||
await TGLogger.Info(`[Achievements][handleImportOuter] 导入来源:${app}`);
|
||||
const confirm = await showConfirm({
|
||||
title: "是否导入祈愿数据?",
|
||||
text: `来源APP:${app}`,
|
||||
});
|
||||
if (!confirm) {
|
||||
const importCheck = await showDialog.check("是否导入祈愿数据?", `来源APP:${app}`);
|
||||
if (!importCheck) {
|
||||
showSnackbar.cancel("已取消导入");
|
||||
await TGLogger.Info("[Achievements][handleImportOuter] 已取消导入");
|
||||
return;
|
||||
}
|
||||
// 读取 剪贴板
|
||||
const clipboard = await window.navigator.clipboard.readText();
|
||||
const check = await verifyUiafDataClipboard();
|
||||
if (!check) return;
|
||||
let uidInput = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入存档UID",
|
||||
text: "UID:",
|
||||
input: uidCur.value.toString(),
|
||||
});
|
||||
let uidInput = await showDialog.input("请输入存档UID", "UID:", uidCur.value.toString());
|
||||
if (uidInput === false) {
|
||||
showSnackbar.cancel("已取消存档导入");
|
||||
return;
|
||||
@@ -250,11 +236,7 @@ async function handleImportOuter(app: string): Promise<void> {
|
||||
}
|
||||
|
||||
async function createUid(): Promise<void> {
|
||||
const uidInput = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入新存档UID",
|
||||
text: "UID:",
|
||||
});
|
||||
const uidInput = await showDialog.input("请输入新存档UID", "UID:");
|
||||
if (uidInput === undefined || uidInput === false) {
|
||||
showSnackbar.cancel("已取消");
|
||||
return;
|
||||
@@ -273,11 +255,11 @@ async function createUid(): Promise<void> {
|
||||
}
|
||||
|
||||
async function deleteUid(): Promise<void> {
|
||||
const uidInput = await showConfirm({
|
||||
title: "确定删除该存档?",
|
||||
text: `确认则清空存档-${uidCur.value}对应数据`,
|
||||
});
|
||||
if (uidInput === undefined || !uidInput) {
|
||||
const delCheck = await showDialog.check(
|
||||
"确定删除该存档?",
|
||||
`确认则清空存档-${uidCur.value}对应数据`,
|
||||
);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消删除存档");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ import TcDataDir from "../../components/config/tc-dataDir.vue";
|
||||
import TcGameBadge from "../../components/config/tc-gameBadge.vue";
|
||||
import TcInfo from "../../components/config/tc-info.vue";
|
||||
import TcUserBadge from "../../components/config/tc-userBadge.vue";
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
@@ -162,16 +162,13 @@ onMounted(async () => {
|
||||
|
||||
// 备份数据
|
||||
async function confirmBackup(): Promise<void> {
|
||||
const res = await showConfirm({
|
||||
title: "是否备份到默认路径",
|
||||
text: "取消则自选路径,点击外部不做处理",
|
||||
});
|
||||
if (res === undefined) {
|
||||
const bcCheck = await showDialog.check("是否备份到默认路径", "取消则自选路径,点击外部不做处理");
|
||||
if (bcCheck === undefined) {
|
||||
showSnackbar.cancel("已取消备份");
|
||||
return;
|
||||
}
|
||||
let saveDir = appStore.userDir;
|
||||
if (!res) {
|
||||
if (!bcCheck) {
|
||||
const dir: string | null = await open({
|
||||
directory: true,
|
||||
defaultPath: saveDir,
|
||||
@@ -196,16 +193,13 @@ async function confirmBackup(): Promise<void> {
|
||||
|
||||
// 恢复数据
|
||||
async function confirmRestore(): Promise<void> {
|
||||
const resConfirm = await showConfirm({
|
||||
title: "是否从默认路径恢复",
|
||||
text: "取消则自选路径,点击外部不做处理",
|
||||
});
|
||||
if (resConfirm === undefined) {
|
||||
const rsCheck = await showDialog.check("是否从默认路径恢复", "取消则自选路径,点击外部不做处理");
|
||||
if (rsCheck === undefined) {
|
||||
showSnackbar.cancel("已取消恢复");
|
||||
return;
|
||||
}
|
||||
let saveDir = appStore.userDir;
|
||||
if (!resConfirm) {
|
||||
if (!rsCheck) {
|
||||
const dir: string | null = await open({
|
||||
directory: true,
|
||||
defaultPath: saveDir,
|
||||
@@ -231,8 +225,8 @@ async function confirmRestore(): Promise<void> {
|
||||
|
||||
// 更新数据
|
||||
async function confirmUpdate(title?: string): Promise<void> {
|
||||
const res = await showConfirm({ title: title ?? "确认更新数据吗?", text: "请确保存在备份数据" });
|
||||
if (!res) {
|
||||
const updateCheck = await showDialog.check(title ?? "确认更新数据吗?");
|
||||
if (!updateCheck) {
|
||||
showSnackbar.cancel("已取消更新数据库");
|
||||
return;
|
||||
}
|
||||
@@ -250,11 +244,11 @@ async function confirmUpdate(title?: string): Promise<void> {
|
||||
async function confirmUpdateDevice(force?: boolean): Promise<void> {
|
||||
if (force !== undefined && force) {
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice][force] 开始强制更新设备信息");
|
||||
const resF = await showConfirm({
|
||||
title: "确认强制更新设备信息吗?",
|
||||
text: `DeviceFp:${appStore.deviceInfo.device_fp}`,
|
||||
});
|
||||
if (!resF) {
|
||||
const forceCheck = await showDialog.check(
|
||||
"确认强制更新设备信息吗?",
|
||||
`DeviceFp:${appStore.deviceInfo.device_fp}`,
|
||||
);
|
||||
if (!forceCheck) {
|
||||
showSnackbar.cancel("已取消强制更新设备信息");
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice][force] 取消强制更新设备信息");
|
||||
return;
|
||||
@@ -274,8 +268,8 @@ async function confirmUpdateDevice(force?: boolean): Promise<void> {
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice] 开始更新设备信息");
|
||||
const localFp = getDeviceInfo("device_fp");
|
||||
if (localFp !== "0000000000000") {
|
||||
const res = await showConfirm({ title: "确认更新设备信息吗?", text: `DeviceFp:${localFp}` });
|
||||
if (!res) {
|
||||
const updateCheck = await showDialog.check("确认更新设备信息吗?", `DeviceFp:${localFp}`);
|
||||
if (!updateCheck) {
|
||||
showSnackbar.cancel("已取消更新设备信息");
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice] 取消更新设备信息");
|
||||
return;
|
||||
@@ -312,11 +306,11 @@ async function confirmDelCache(): Promise<void> {
|
||||
}
|
||||
cacheSize.value = cacheBSize;
|
||||
loading.value = false;
|
||||
const res = await showConfirm({
|
||||
title: "确认清除缓存吗?",
|
||||
text: `当前缓存大小为 ${bytesToSize(cacheBSize)}`,
|
||||
});
|
||||
if (!res) {
|
||||
const delCheck = await showDialog.check(
|
||||
"确认清除缓存吗?",
|
||||
`当前缓存大小为 ${bytesToSize(cacheBSize)}`,
|
||||
);
|
||||
if (!delCheck) {
|
||||
showSnackbar.cancel("已取消清除缓存");
|
||||
await TGLogger.Info("[Config][confirmDelCache] 取消清除缓存");
|
||||
return;
|
||||
@@ -335,8 +329,8 @@ async function confirmDelCache(): Promise<void> {
|
||||
// 恢复默认设置
|
||||
async function confirmResetApp(): Promise<void> {
|
||||
await TGLogger.Info("[Config][confirmResetApp] 开始恢复默认设置");
|
||||
const res = await showConfirm({ title: "确认恢复默认设置吗?" });
|
||||
if (!res) {
|
||||
const resetCheck = await showDialog.check("确认恢复默认设置吗?");
|
||||
if (!resetCheck) {
|
||||
showSnackbar.cancel("已取消恢复默认设置");
|
||||
await TGLogger.Info("[Config][confirmResetApp] 取消恢复默认设置");
|
||||
return;
|
||||
@@ -350,18 +344,14 @@ async function confirmResetApp(): Promise<void> {
|
||||
|
||||
// 前置
|
||||
async function tryShowReset(): Promise<void> {
|
||||
const res = await showConfirm({
|
||||
title: "请输入验证 Code",
|
||||
text: "请联系开发者获取",
|
||||
mode: "input",
|
||||
});
|
||||
if (!res) {
|
||||
const codeInput = await showDialog.input("请输入验证 Code", "请联系开发者获取");
|
||||
if (!codeInput) {
|
||||
showSnackbar.cancel("已取消");
|
||||
return;
|
||||
}
|
||||
const time = getBuildTime();
|
||||
const code = time.startsWith("dev.") ? "dev" : time;
|
||||
if (res === code || res === "reset1128") {
|
||||
if (codeInput === code || codeInput === "reset1128") {
|
||||
showReset.value = true;
|
||||
showSnackbar.success("已开启重置数据库选项");
|
||||
return;
|
||||
@@ -372,11 +362,11 @@ async function tryShowReset(): Promise<void> {
|
||||
// 重置数据库
|
||||
async function confirmResetDB(title?: string): Promise<void> {
|
||||
await TGLogger.Info("[Config][confirmResetDB] 开始重置数据库");
|
||||
const res = await showConfirm({
|
||||
title: title ?? "确认重置数据库吗?",
|
||||
text: "请确认已经备份关键数据",
|
||||
});
|
||||
if (!res) {
|
||||
const resetCheck = await showDialog.check(
|
||||
title ?? "确认重置数据库吗?",
|
||||
"请确认已经备份关键数据",
|
||||
);
|
||||
if (!resetCheck) {
|
||||
showSnackbar.cancel("已取消重置数据库");
|
||||
await TGLogger.Info("[Config][confirmResetDB] 取消重置数据库");
|
||||
return;
|
||||
|
||||
@@ -95,7 +95,7 @@ import { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TPostCard from "../../components/main/t-postcard.vue";
|
||||
import ToCollectPost from "../../components/overlay/to-collectPost.vue";
|
||||
@@ -188,11 +188,7 @@ function toSelect() {
|
||||
|
||||
async function addCollect(): Promise<void> {
|
||||
let title, desc;
|
||||
const titleC = await showConfirm({
|
||||
mode: "input",
|
||||
title: "新建分类",
|
||||
text: "请输入分类名称",
|
||||
});
|
||||
const titleC = await showDialog.input("新建分类", "分类名称:");
|
||||
if (titleC === undefined || titleC === false) return;
|
||||
if (titleC === "未分类") {
|
||||
showSnackbar.warn("分类名不可为未分类");
|
||||
@@ -203,11 +199,7 @@ async function addCollect(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
title = titleC;
|
||||
const descC = await showConfirm({
|
||||
mode: "input",
|
||||
title: "新建分类",
|
||||
text: "请输入分类描述",
|
||||
});
|
||||
const descC = await showDialog.input("新建分类", "分类描述:");
|
||||
if (descC === false) return;
|
||||
if (descC === undefined) desc = title;
|
||||
else desc = descC;
|
||||
@@ -226,12 +218,7 @@ async function toEdit(): Promise<void> {
|
||||
showSnackbar.warn("未找到合集信息");
|
||||
return;
|
||||
}
|
||||
let cTc = await showConfirm({
|
||||
title: "修改分类标题",
|
||||
mode: "input",
|
||||
text: "请输入分类标题",
|
||||
input: collect.title,
|
||||
});
|
||||
let cTc = await showDialog.input("修改分类标题", "分类标题:", collect.title);
|
||||
if (cTc === false) {
|
||||
showSnackbar.cancel("取消修改分类信息");
|
||||
return;
|
||||
@@ -245,14 +232,9 @@ async function toEdit(): Promise<void> {
|
||||
showSnackbar.warn("分类名称重复");
|
||||
return;
|
||||
}
|
||||
let cTd = await showConfirm({
|
||||
title: "修改分类描述",
|
||||
mode: "input",
|
||||
text: "请输入分类描述",
|
||||
input: collect.desc,
|
||||
});
|
||||
let cTd = await showDialog.input("修改分类描述", "分类描述:", collect.desc);
|
||||
if (typeof cTd !== "string") cTd = collect.desc;
|
||||
const cc = await showConfirm({ title: "确定修改?", text: `[${cTc}] ${cTd}` });
|
||||
const cc = await showDialog.check("确定修改?", `[${cTc}] ${cTd}`);
|
||||
if (!cc) {
|
||||
showSnackbar.cancel("取消修改分类信息");
|
||||
return;
|
||||
@@ -280,11 +262,8 @@ async function deletePost(force: boolean = false): Promise<void> {
|
||||
return;
|
||||
}
|
||||
const title = force ? "删除帖子" : "移除帖子分类";
|
||||
const res = await showConfirm({
|
||||
title: `确定${title}?`,
|
||||
text: `共 ${selectedPost.value.length} 条帖子`,
|
||||
});
|
||||
if (!res) {
|
||||
const check = await showDialog.check(`确定${title}?`, `共 ${selectedPost.value.length} 条帖子`);
|
||||
if (!check) {
|
||||
showSnackbar.cancel("取消操作");
|
||||
return;
|
||||
}
|
||||
@@ -311,11 +290,11 @@ async function deleteCollect(force: boolean): Promise<void> {
|
||||
return;
|
||||
}
|
||||
const title = force ? "删除分类" : "清空分类";
|
||||
const res = await showConfirm({
|
||||
title: `确定${title}?`,
|
||||
text: `该分类下${selected.value.length}条帖子将被${force ? "删除" : "移除分类(未分类将被删除)"}`,
|
||||
});
|
||||
if (!res) {
|
||||
const check = await showDialog.check(
|
||||
`确定${title}?`,
|
||||
`该分类下 ${selected.value.length} 条帖子将被${force ? "删除" : "移除分类(未分类将被删除)"}`,
|
||||
);
|
||||
if (!check) {
|
||||
showSnackbar.cancel("取消操作");
|
||||
return;
|
||||
}
|
||||
@@ -377,17 +356,13 @@ watch(
|
||||
);
|
||||
|
||||
async function freshOther(): Promise<void> {
|
||||
const input = await showConfirm({
|
||||
mode: "input",
|
||||
title: "导入其他用户收藏",
|
||||
text: "请输入用户米游社UID",
|
||||
});
|
||||
if (typeof input === "string") {
|
||||
if (isNaN(Number(input))) {
|
||||
const uidInput = await showDialog.input("导入其他用户收藏", "米游社UID:");
|
||||
if (typeof uidInput === "string") {
|
||||
if (isNaN(Number(uidInput))) {
|
||||
showSnackbar.warn("UID 格式错误,请输入数字");
|
||||
return;
|
||||
}
|
||||
await freshUser(input);
|
||||
await freshUser(uidInput);
|
||||
return;
|
||||
}
|
||||
showSnackbar.cancel("取消导入");
|
||||
|
||||
58
src/types/Component/Confirm.d.ts
vendored
58
src/types/Component/Confirm.d.ts
vendored
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* @file types Component Confirm.d.ts
|
||||
* @description Component Confirm 类型声明文件
|
||||
* @since Beta v0.3.4
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Component.Confirm {
|
||||
/**
|
||||
* @description Confirm 参数
|
||||
* @interface ParamsBase
|
||||
* @since Beta v0.3.3
|
||||
* @property {string} title 标题
|
||||
* @property {string} text 文本
|
||||
* @property {string} mode 模式 // normal: 正常(默认),input: 输入框
|
||||
* @property {boolean} otcancel 点击外部取消 // true: 取消(默认),false: 不取消
|
||||
* @return ParamsBase
|
||||
*/
|
||||
interface ParamsBase {
|
||||
title: string;
|
||||
text?: string;
|
||||
mode?: "confirm" | "input";
|
||||
otcancel?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Confirm 参数- confirm mode
|
||||
* @interface ParamsConfirm
|
||||
* @since Beta v0.3.3
|
||||
* @extends ParamsBase
|
||||
* @property {"confirm"|undefined} mode
|
||||
* @return ParamsConfirm
|
||||
*/
|
||||
interface ParamsConfirm extends ParamsBase {
|
||||
mode?: "confirm";
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Confirm 参数 - input mode
|
||||
* @interface ParamsInput
|
||||
* @since Beta v0.4.5
|
||||
* @extends ParamsBase
|
||||
* @property {"input"} mode
|
||||
* @property {string} input 可选的配置默认输入值
|
||||
* @return ParamsInput
|
||||
*/
|
||||
interface ParamsInput extends ParamsBase {
|
||||
mode: "input";
|
||||
input?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Confirm 参数
|
||||
* @since Beta v0.3.3
|
||||
* @type Params
|
||||
* @return Params
|
||||
*/
|
||||
type Params = ParamsConfirm | ParamsInput;
|
||||
}
|
||||
23
src/types/Component/Snackbar.d.ts
vendored
23
src/types/Component/Snackbar.d.ts
vendored
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* @file types Component Snackbar.d.ts
|
||||
* @description Component Snackbar 类型声明文件
|
||||
* @since Beta v0.6.3
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Component.Snackbar {
|
||||
/**
|
||||
* @description Snackbar 参数
|
||||
* @interface Params
|
||||
* @since Beta v0.6.3
|
||||
* @property {string} text 文本
|
||||
* @property {string} color 颜色
|
||||
* @property {number} timeout 超时时间
|
||||
* @property {boolean} show 是否显示
|
||||
* @return Params
|
||||
*/
|
||||
interface Params {
|
||||
text: string;
|
||||
color: string;
|
||||
timeout: number;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { save } from "@tauri-apps/plugin-dialog";
|
||||
import { writeFile } from "@tauri-apps/plugin-fs";
|
||||
import html2canvas from "html2canvas";
|
||||
|
||||
import showConfirm from "../components/func/confirm.js";
|
||||
import showDialog from "../components/func/dialog.js";
|
||||
import showSnackbar from "../components/func/snackbar.js";
|
||||
|
||||
import TGHttp from "./TGHttp.js";
|
||||
@@ -137,11 +137,8 @@ export async function generateShareImg(
|
||||
}
|
||||
if (size > 20000000) {
|
||||
const sizeStr = bytesToSize(size);
|
||||
const saveFile = await showConfirm({
|
||||
title: "图像过大",
|
||||
text: `图像大小为 ${sizeStr},是否保存到文件?`,
|
||||
});
|
||||
if (saveFile === true) {
|
||||
const saveCheck = await showDialog.check("图像过大", `图像大小为 ${sizeStr},是否保存到文件?`);
|
||||
if (saveCheck === true) {
|
||||
await saveCanvasImg(buffer, fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
|
||||
import showConfirm from "../components/func/confirm.js";
|
||||
import showDialog from "../components/func/dialog.js";
|
||||
import showSnackbar from "../components/func/snackbar.js";
|
||||
|
||||
import TGClient from "./TGClient.js";
|
||||
@@ -143,19 +143,13 @@ export async function parseLink(
|
||||
"mihoyo.genshinnet.com",
|
||||
];
|
||||
if (prefix.includes(url.hostname) && !useInner) {
|
||||
const openCheck = await showConfirm({
|
||||
title: "采用内置 JSBridge?",
|
||||
text: "取消则使用外部浏览器打开",
|
||||
});
|
||||
const openCheck = await showDialog.check("采用内置 JSBridge?", "取消则使用外部浏览器打开");
|
||||
if (openCheck === undefined) {
|
||||
showSnackbar.cancel("已取消打开");
|
||||
return true;
|
||||
}
|
||||
if (!openCheck) return url.href;
|
||||
const typeCheck = await showConfirm({
|
||||
title: "采用宽屏模式?",
|
||||
text: "取消则使用默认竖屏",
|
||||
});
|
||||
const typeCheck = await showDialog.check("采用宽屏模式?", "取消则使用默认竖屏");
|
||||
if (!typeCheck) await TGClient.open("web_act_thin", link);
|
||||
else await TGClient.open("web_act", link);
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user