diff --git a/components.d.ts b/components.d.ts index bee6347..bd09d52 100644 --- a/components.d.ts +++ b/components.d.ts @@ -8,12 +8,14 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { + FloatLabelInput: typeof import('./src/components/FloatLabelInput.vue')['default'] NA: typeof import('naive-ui')['NA'] NButton: typeof import('naive-ui')['NButton'] NCheckbox: typeof import('naive-ui')['NCheckbox'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NDialog: typeof import('naive-ui')['NDialog'] NDialogProvider: typeof import('naive-ui')['NDialogProvider'] + NEl: typeof import('naive-ui')['NEl'] NIcon: typeof import('naive-ui')['NIcon'] NInput: typeof import('naive-ui')['NInput'] NInputGroup: typeof import('naive-ui')['NInputGroup'] @@ -21,7 +23,10 @@ declare module 'vue' { NModal: typeof import('naive-ui')['NModal'] NModalProvider: typeof import('naive-ui')['NModalProvider'] NNotificationProvider: typeof import('naive-ui')['NNotificationProvider'] + NQrCode: typeof import('naive-ui')['NQrCode'] NSelect: typeof import('naive-ui')['NSelect'] + NTabPane: typeof import('naive-ui')['NTabPane'] + NTabs: typeof import('naive-ui')['NTabs'] NTooltip: typeof import('naive-ui')['NTooltip'] NVirtualList: typeof import('naive-ui')['NVirtualList'] TitleBar: typeof import('./src/components/TitleBar.vue')['default'] diff --git a/index.html b/index.html index 99f203f..85c3a16 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,7 @@ + Tauri + Vue + Typescript App diff --git a/src/components/FloatLabelInput.vue b/src/components/FloatLabelInput.vue new file mode 100644 index 0000000..62547db --- /dev/null +++ b/src/components/FloatLabelInput.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/components/TitleBar.vue b/src/components/TitleBar.vue index 8907395..3881aff 100644 --- a/src/components/TitleBar.vue +++ b/src/components/TitleBar.vue @@ -3,7 +3,12 @@ import icon from '../../src-tauri/icons/128x128.png' import { PhCopySimple, PhMinus, PhSquare, PhX } from '@phosphor-icons/vue' import { getCurrentWindow } from '@tauri-apps/api/window' import { onMounted, ref } from 'vue' +import { useStore } from '../store.ts' import { platform } from '@tauri-apps/plugin-os' +import { ensureHttps } from '../utils.tsx' +import LoginDialog from '../dialogs/LoginDialog.vue' + +const store = useStore() const appWindow = getCurrentWindow() const windowMaximised = ref(false) @@ -15,7 +20,6 @@ const loginDialogShowing = ref(false) onMounted(async () => { windowMaximised.value = await appWindow.isMaximized() - windowFullscreen.value = await appWindow.isFullscreen() await appWindow.onResized(async () => { windowMaximised.value = await appWindow.isMaximized() @@ -32,7 +36,24 @@ onMounted(async () => { icon 哔哩哔哩视频下载器 -
+
+
+ +
{{ store.userInfo.uname }}
+
+
+ +
未登录
+
+
+import { commands, QrcodeData, QrcodeStatus } from '../bindings.ts' +import { ref, watch } from 'vue' +import { useMessage } from 'naive-ui' +import { useStore } from '../store.ts' +import icon from '../../src-tauri/icons/128x128.png' +import FloatLabelInput from '../components/FloatLabelInput.vue' + +const store = useStore() + +const message = useMessage() + +const showing = defineModel('showing', { required: true }) + +const currentTabName = ref<'cookie' | 'qrcode'>('cookie') + +// 只要showing有任何变动,currentTabName就改为cookie +watch(showing, () => { + currentTabName.value = 'cookie' +}) + +watch( + () => store.config?.sessdata, + async (value, oldValue) => { + if (store.config === undefined) { + return + } + if (oldValue !== undefined && oldValue !== '' && value === '') { + // 如果旧的 sessdata 不为空,新的 sessdata 为空,相当于退出登录 + store.userInfo = undefined + message.success('已退出登录') + return + } else if (value === undefined || value === '') { + // 如果 sessdata 为空,说明用户没有登录 + return + } + const result = await commands.getUserInfo(value) + if (result.status === 'error') { + console.error(result.error) + store.userInfo = undefined + return + } + store.userInfo = result.data + message.success('获取用户信息成功') + showing.value = false + }, +) + +watch([showing, currentTabName], async () => { + if (currentTabName.value !== 'qrcode' || !showing.value) { + return + } + // 如果当前选项卡是二维码,并且dialog正在显示,则生成二维码 + await generateQrcode() +}) + +const qrcodeData = ref() +const qrcodeStatus = ref() + +async function generateQrcode() { + const result = await commands.generateQrcode() + if (result.status === 'error') { + console.error(result.error) + return + } + qrcodeData.value = result.data + // 每隔一秒获取一次二维码状态,直到showing为false + const interval = setInterval(async () => { + if (!showing.value) { + clearInterval(interval) + return + } + await getQrcodeStatus() + handleQrcodeStatus() + }, 1000) +} + +async function getQrcodeStatus() { + if (qrcodeData.value === undefined) { + return + } + const result = await commands.getQrcodeStatus(qrcodeData.value?.qrcode_key) + if (result.status === 'error') { + console.error(result.error) + return + } + qrcodeStatus.value = result.data +} + +function handleQrcodeStatus() { + if (qrcodeStatus.value === undefined || store.config === undefined) { + return + } + + if (qrcodeStatus.value.code === 0) { + const sessdata = qrcodeStatus.value.url.split('SESSDATA=')[1].split('&')[0] + store.config.sessdata = encodeURIComponent(sessdata) + showing.value = false + message.success('登录成功') + } +} + + + diff --git a/src/store.ts b/src/store.ts index 986b160..be68477 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,9 +1,10 @@ import { defineStore } from 'pinia' import { ref } from 'vue' -import { Config } from './bindings.ts' +import { Config, UserInfo } from './bindings.ts' export const useStore = defineStore('store', () => { const config = ref() + const userInfo = ref() - return { config } + return { config, userInfo } }) diff --git a/src/utils.tsx b/src/utils.tsx new file mode 100644 index 0000000..f5c3425 --- /dev/null +++ b/src/utils.tsx @@ -0,0 +1,6 @@ +export function ensureHttps(url: string): string { + if (url.startsWith('http://')) { + return url.replace('http://', 'https://') + } + return url +}