🌱 获取上传存档

This commit is contained in:
BTMuli
2026-01-06 06:13:42 +08:00
parent 2b13f29a02
commit 49afdfc2b0
2 changed files with 247 additions and 1 deletions

View File

@@ -0,0 +1,179 @@
<!-- 胡桃悬浮层 -->
<template>
<TOverlay v-model="visible" blur-val="5px">
<div class="ugo-hutao-download">
<div class="ugo-hd-title">请选择要下载的数据</div>
<v-progress-circular v-if="loading" color="var(--tgc-od-blue)" indeterminate />
<v-item-group v-else v-model="selectedUid" class="ugo-hd-list">
<v-item
v-for="(item, idx) in uploadInfo"
:key="idx"
v-slot="{ isSelected, toggle }"
:value="item.uid"
>
<div class="ugo-hd-item" @click="toggle">
<div class="ugo-hdi-check">
<v-btn :class="{ active: isSelected }" class="ugo-hdi-btn" variant="elevated">
<v-icon>{{ isSelected ? "mdi-check" : "mdi-checkbox-blank-outline" }}</v-icon>
</v-btn>
</div>
<div class="ugo-hdi-info">
<span>UID:{{ item.uid }}</span>
<span>{{ item.cnt }}</span>
</div>
</div>
</v-item>
</v-item-group>
<div class="ugo-hd-acts">
<v-btn :rounded="true" class="ugo-hdi-btn" @click="visible = false">取消</v-btn>
<v-btn :rounded="true" class="ugo-hdi-btn" @click="handleSelected()">确定</v-btn>
</div>
</div>
</TOverlay>
</template>
<script lang="ts" setup>
import TOverlay from "@comp/app/t-overlay.vue";
import showSnackbar from "@comp/func/snackbar.js";
import hutao from "@Hutao/index.js";
import useHutaoStore from "@store/hutao.js";
import { storeToRefs } from "pinia";
import { ref, shallowRef, watch } from "vue";
type UgoHutaoDownloadUid = { uid: string; cnt: number };
type UgoHutaoDownloadEmits = (e: "selected", v: Array<string>) => void;
const visible = defineModel<boolean>();
const emits = defineEmits<UgoHutaoDownloadEmits>();
const loading = ref<boolean>(false);
const uploadInfo = shallowRef<Array<UgoHutaoDownloadUid>>([]);
const selectedUid = shallowRef<Array<string>>([]);
const hutaoStore = useHutaoStore();
const { accessToken, isLogin } = storeToRefs(hutaoStore);
watch(
() => visible.value,
async () => {
if (visible.value) {
loading.value = true;
selectedUid.value = [];
uploadInfo.value = [];
await loadOverview();
loading.value = false;
}
},
{ immediate: true },
);
async function loadOverview(): Promise<void> {
if (!isLogin.value) return;
if (!hutaoStore.checkIsValid()) await hutaoStore.tryRefreshToken();
if (!accessToken.value) return;
try {
const info = await hutao.Gacha.entry(accessToken.value);
if ("retcode" in info) {
showSnackbar.warn(`[${info.retcode}] ${info.message}`);
return;
}
uploadInfo.value = info.map((i) => ({ uid: i.Uid, cnt: i.ItemCount }));
} catch (e) {
console.error(e);
}
}
function handleSelected(): void {
if (!selectedUid.value || selectedUid.value.length == 0) {
showSnackbar.warn("请选择至少一个UID");
return;
}
emits("selected", selectedUid.value);
visible.value = false;
}
</script>
<style lang="scss" scoped>
.ugo-hutao-download {
position: relative;
display: flex;
width: 400px;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 8px;
border: 1px solid var(--common-shadow-2);
border-radius: 4px;
background: var(--app-page-bg);
row-gap: 8px;
}
.ugo-hd-title {
position: relative;
color: var(--common-text-title);
font-family: var(--font-title);
font-size: 18px;
}
.ugo-hd-list {
position: relative;
display: flex;
width: 100%;
height: 100%;
max-height: 360px;
flex-direction: column;
align-items: center;
justify-content: flex-start;
gap: 8px;
overflow-y: auto;
}
.ugo-hd-item {
position: relative;
display: flex;
width: 100%;
height: 100%;
box-sizing: border-box;
align-items: center;
justify-content: flex-start;
column-gap: 8px;
}
.ugo-hdi-info {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
span:first-child {
font-family: var(--font-title);
font-size: 14px;
line-height: 16px;
}
span:last-child {
font-size: 12px;
line-height: 16px;
}
}
.ugo-hdi-btn {
height: 40px;
border: 1px solid var(--common-shadow-2);
background: var(--tgc-btn-1);
color: var(--btn-text);
font-family: var(--font-title);
&.active {
color: var(--tgc-od-green);
}
}
.ugo-hd-acts {
position: relative;
display: flex;
width: 100%;
align-items: center;
justify-content: flex-end;
gap: 8px;
}
</style>

View File

@@ -22,6 +22,31 @@
/>
</div>
</template>
<template #append>
<div class="gacha-top-append">
<div class="gacha-hutao-box">
<span @click="tryLoginHutao()">{{ userName ?? "登录胡桃云" }}</span>
<v-btn
:disabled="!isLoginHutao"
class="gacha-top-btn"
prepend-icon="mdi-upload"
variant="elevated"
@click="tryUploadGacha()"
>
上传
</v-btn>
<v-btn
:disabled="!isLoginHutao"
class="gacha-top-btn"
prepend-icon="mdi-download"
variant="elevated"
@click="tryDownloadGacha()"
>
下载
</v-btn>
</div>
</div>
</template>
<template #extension>
<div class="gacha-top-btns">
<v-btn
@@ -120,6 +145,7 @@
</v-window>
</div>
<UgoUid v-model="ovShow" :mode="ovMode" />
<UgoHutaoDownload v-model="showHutaoD" @selected="handleHutaoDownload" />
</template>
<script lang="ts" setup>
import showDialog from "@comp/func/dialog.js";
@@ -130,11 +156,13 @@ import GroHistory from "@comp/userGacha/gro-history.vue";
import GroIframe from "@comp/userGacha/gro-iframe.vue";
import GroOverview from "@comp/userGacha/gro-overview.vue";
import GroTable from "@comp/userGacha/gro-table.vue";
import UgoHutaoDownload from "@comp/userGacha/ugo-hutao-download.vue";
import UgoUid from "@comp/userGacha/ugo-uid.vue";
import hk4eReq from "@req/hk4eReq.js";
import takumiReq from "@req/takumiReq.js";
import TSUserGacha from "@Sqlm/userGacha.js";
import useAppStore from "@store/app.js";
import useHutaoStore from "@store/hutao.js";
import useUserStore from "@store/user.js";
import { path } from "@tauri-apps/api";
import { open, save } from "@tauri-apps/plugin-dialog";
@@ -148,14 +176,17 @@ import { useRouter } from "vue-router";
import { AppCharacterData, AppWeaponData } from "@/data/index.js";
const router = useRouter();
const hutaoStore = useHutaoStore();
const { isLogin } = storeToRefs(useAppStore());
const { account, cookie } = storeToRefs(useUserStore());
const { isLogin: isLoginHutao, userName } = storeToRefs(hutaoStore);
const authkey = ref<string>("");
const uidCur = ref<string>();
const tab = ref<string>("overview");
const ovShow = ref<boolean>(false);
const showHutaoD = ref<boolean>(false);
const ovMode = ref<"export" | "import">("import");
const selectItem = shallowRef<Array<string>>([]);
const gachaListCur = shallowRef<Array<TGApp.Sqlite.Gacha.Gacha>>([]);
@@ -193,6 +224,24 @@ async function toBeyond(): Promise<void> {
await router.push({ name: "千星奇域祈愿记录" });
}
async function tryLoginHutao(): Promise<void> {
if (!userName.value) await hutaoStore.tryLogin();
}
async function tryUploadGacha(): Promise<void> {
// TODO: implement upload gacha records to hutao cloud
}
async function tryDownloadGacha(): Promise<void> {
if (!isLoginHutao.value) return;
showHutaoD.value = true;
}
async function handleHutaoDownload(uids: Array<string>): Promise<void> {
console.log(uids);
// TODO: implement download gacha records from hutao cloud
}
async function reloadUid(): Promise<void> {
selectItem.value = await TSUserGacha.getUidList();
if (selectItem.value.includes(account.value.gameUid)) uidCur.value = account.value.gameUid;
@@ -499,7 +548,7 @@ async function checkData(): Promise<void> {
}
}
</script>
<style lang="css" scoped>
<style lang="scss" scoped>
.gacha-top-title {
display: flex;
align-items: center;
@@ -531,6 +580,24 @@ async function checkData(): Promise<void> {
filter: none;
}
.gacha-top-append {
position: relative;
margin-right: 16px;
}
.gacha-hutao-box {
position: relative;
display: flex;
align-items: center;
justify-content: center;
column-gap: 8px;
span {
color: var(--tgc-od-red);
cursor: pointer;
}
}
.gacha-top-btns {
display: flex;
margin-bottom: 4px;