mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-07 00:36:41 +08:00
fix 115
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "moviepilot",
|
"name": "moviepilot",
|
||||||
"version": "1.9.6",
|
"version": "1.9.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"bin": "dist/service.js",
|
"bin": "dist/service.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -763,6 +763,8 @@ export interface FileItem {
|
|||||||
parent_fileid?: string
|
parent_fileid?: string
|
||||||
// 缩略图
|
// 缩略图
|
||||||
thumbnail?: string
|
thumbnail?: string
|
||||||
|
// pickcode
|
||||||
|
pickcode?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 媒体服务器播放条目
|
// 媒体服务器播放条目
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import FileToolbar from './filebrowser/FileToolbar.vue'
|
|||||||
import type { EndPoints, FileItem } from '@/api/types'
|
import type { EndPoints, FileItem } from '@/api/types'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import AliyunAuthDialog from './dialog/AliyunAuthDialog.vue'
|
import AliyunAuthDialog from './dialog/AliyunAuthDialog.vue'
|
||||||
|
import U115AuthDialog from './dialog/U115AuthDialog.vue'
|
||||||
import { isNullOrEmptyObject } from '@/@core/utils'
|
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
@@ -12,6 +13,7 @@ const props = defineProps({
|
|||||||
storages: String,
|
storages: String,
|
||||||
path: String,
|
path: String,
|
||||||
fileid: String,
|
fileid: String,
|
||||||
|
pickcode: String,
|
||||||
fileidstack: Array as PropType<string[]>,
|
fileidstack: Array as PropType<string[]>,
|
||||||
tree: Boolean,
|
tree: Boolean,
|
||||||
endpoints: Object as PropType<EndPoints>,
|
endpoints: Object as PropType<EndPoints>,
|
||||||
@@ -77,6 +79,10 @@ const sort = ref('name')
|
|||||||
const aliyunAuthDialog = ref(false)
|
const aliyunAuthDialog = ref(false)
|
||||||
// 阿里云盘用户信息
|
// 阿里云盘用户信息
|
||||||
const aliyunUserInfo = ref<{ [key: string]: any }>({})
|
const aliyunUserInfo = ref<{ [key: string]: any }>({})
|
||||||
|
// 115网盘认证对话框
|
||||||
|
const u115AuthDialog = ref(false)
|
||||||
|
// 115网盘用户信息
|
||||||
|
const u115UserInfo = ref<{ [key: string]: any }>({})
|
||||||
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const storagesArray = computed(() => {
|
const storagesArray = computed(() => {
|
||||||
@@ -90,7 +96,7 @@ function loadingChanged(loading: number) {
|
|||||||
else if (loading > 0) loading--
|
else if (loading > 0) loading--
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询阿里云token
|
// 查询阿里云
|
||||||
async function loadAliyunUserInfo() {
|
async function loadAliyunUserInfo() {
|
||||||
try {
|
try {
|
||||||
const result: { [key: string]: any } = await api.get('aliyun/userinfo')
|
const result: { [key: string]: any } = await api.get('aliyun/userinfo')
|
||||||
@@ -102,6 +108,18 @@ async function loadAliyunUserInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询115
|
||||||
|
async function loadU115UserInfo() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('u115/storage')
|
||||||
|
if (result.success) {
|
||||||
|
u115UserInfo.value = result
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 存储切换
|
// 存储切换
|
||||||
async function storageChanged(storage: string) {
|
async function storageChanged(storage: string) {
|
||||||
if (storage == 'aliyun') {
|
if (storage == 'aliyun') {
|
||||||
@@ -110,6 +128,12 @@ async function storageChanged(storage: string) {
|
|||||||
aliyunAuthDialog.value = true
|
aliyunAuthDialog.value = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if (storage == 'u115') {
|
||||||
|
await loadU115UserInfo()
|
||||||
|
if (isNullOrEmptyObject(u115UserInfo.value)) {
|
||||||
|
u115AuthDialog.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activeStorage.value = storage
|
activeStorage.value = storage
|
||||||
emit('pathchanged', { path: '/', fileid: 'root' })
|
emit('pathchanged', { path: '/', fileid: 'root' })
|
||||||
@@ -131,6 +155,12 @@ function aliyunAuthDone() {
|
|||||||
aliyunAuthDialog.value = false
|
aliyunAuthDialog.value = false
|
||||||
activeStorage.value = 'aliyun'
|
activeStorage.value = 'aliyun'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// u115认证完成
|
||||||
|
function u115AuthDone() {
|
||||||
|
u115AuthDialog.value = false
|
||||||
|
activeStorage.value = 'u115'
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -152,6 +182,7 @@ function aliyunAuthDone() {
|
|||||||
<FileList
|
<FileList
|
||||||
:path="path"
|
:path="path"
|
||||||
:fileid="fileid"
|
:fileid="fileid"
|
||||||
|
:pickcode="pickcode"
|
||||||
:storage="activeStorage"
|
:storage="activeStorage"
|
||||||
:icons="fileIcons"
|
:icons="fileIcons"
|
||||||
:endpoints="endpoints"
|
:endpoints="endpoints"
|
||||||
@@ -172,4 +203,5 @@ function aliyunAuthDone() {
|
|||||||
@close="aliyunAuthDialog = false"
|
@close="aliyunAuthDialog = false"
|
||||||
@done="aliyunAuthDone"
|
@done="aliyunAuthDone"
|
||||||
/>
|
/>
|
||||||
|
<U115AuthDialog v-if="u115AuthDialog" v-model="u115AuthDialog" @close="u115AuthDialog = false" @done="u115AuthDone" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import QrcodeVue from 'qrcode.vue'
|
import QrcodeVue from 'qrcode.vue'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { isNullOrEmptyObject } from '@/@core/utils'
|
|
||||||
|
|
||||||
// 定义事件
|
// 定义事件
|
||||||
const emit = defineEmits(['done', 'close'])
|
const emit = defineEmits(['done', 'close'])
|
||||||
@@ -21,9 +20,6 @@ const text = ref('请用阿里云盘 App 扫码')
|
|||||||
// 提醒类型
|
// 提醒类型
|
||||||
const alertType = ref<'success' | 'info' | 'error' | 'warning' | undefined>('info')
|
const alertType = ref<'success' | 'info' | 'error' | 'warning' | undefined>('info')
|
||||||
|
|
||||||
// 认证数据
|
|
||||||
const UserAliyunParams = ref({})
|
|
||||||
|
|
||||||
// timeout定时器
|
// timeout定时器
|
||||||
let timeoutTimer: NodeJS.Timeout | undefined = undefined
|
let timeoutTimer: NodeJS.Timeout | undefined = undefined
|
||||||
|
|
||||||
@@ -63,7 +59,6 @@ async function checkQrcode() {
|
|||||||
if (qrCodeStatus == 'CONFIRMED') {
|
if (qrCodeStatus == 'CONFIRMED') {
|
||||||
// 已确认完成
|
// 已确认完成
|
||||||
alertType.value = 'success'
|
alertType.value = 'success'
|
||||||
UserAliyunParams.value = result.data
|
|
||||||
handleDone()
|
handleDone()
|
||||||
} else if (qrCodeStatus == 'NEW' || qrCodeStatus == 'SCANED') {
|
} else if (qrCodeStatus == 'NEW' || qrCodeStatus == 'SCANED') {
|
||||||
alertType.value = 'info'
|
alertType.value = 'info'
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import QrcodeVue from 'qrcode.vue'
|
||||||
|
import api from '@/api'
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emit = defineEmits(['done', 'close'])
|
||||||
|
|
||||||
|
// 二维码内容
|
||||||
|
const qrCodeContent = ref('')
|
||||||
|
|
||||||
|
// 下方的提示信息
|
||||||
|
const text = ref('请使用微信或115客户端扫码')
|
||||||
|
|
||||||
|
// 提醒类型
|
||||||
|
const alertType = ref<'success' | 'info' | 'error' | 'warning' | undefined>('info')
|
||||||
|
|
||||||
|
// timeout定时器
|
||||||
|
let timeoutTimer: NodeJS.Timeout | undefined = undefined
|
||||||
|
|
||||||
|
// 完成
|
||||||
|
async function handleDone() {
|
||||||
|
emit('done')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用/aliyun/qrcode api生成二维码
|
||||||
|
async function getQrcode() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('/u115/qrcode')
|
||||||
|
if (result.success && result.data) {
|
||||||
|
qrCodeContent.value = result.data.codeContent
|
||||||
|
} else {
|
||||||
|
text.value = result.message
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用/aliyun/check api验证二维码
|
||||||
|
async function checkQrcode() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('/u115/check')
|
||||||
|
if (result.success && result.data) {
|
||||||
|
const status = result.data.status
|
||||||
|
text.value = result.data.tip
|
||||||
|
if (status == 1) {
|
||||||
|
// 已确认完成
|
||||||
|
alertType.value = 'success'
|
||||||
|
handleDone()
|
||||||
|
} else if (status == 0) {
|
||||||
|
alertType.value = 'info'
|
||||||
|
// 新建、待扫码
|
||||||
|
clearTimeout(timeoutTimer)
|
||||||
|
timeoutTimer = setTimeout(checkQrcode, 3000)
|
||||||
|
} else {
|
||||||
|
// 过期或者已取消
|
||||||
|
alertType.value = 'error'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alertType.value = 'error'
|
||||||
|
text.value = result.message
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getQrcode()
|
||||||
|
timeoutTimer = setTimeout(checkQrcode, 3000)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timeoutTimer) clearTimeout(timeoutTimer)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<VDialog width="40rem" scrollable max-height="85vh">
|
||||||
|
<VCard title="115网盘登录" class="rounded-t">
|
||||||
|
<DialogCloseBtn @click="emit('close')" />
|
||||||
|
<VCardText class="pt-2">
|
||||||
|
<div class="my-6">
|
||||||
|
<VImg class="mx-auto" :src="qrCodeContent" :size="200" max-width="25rem" />
|
||||||
|
</div>
|
||||||
|
<VAlert variant="tonal" :type="alertType" class="my-4 text-center" :text="text">
|
||||||
|
<template #prepend />
|
||||||
|
</VAlert>
|
||||||
|
</VCardText>
|
||||||
|
<VCardActions>
|
||||||
|
<VSpacer />
|
||||||
|
<VBtn variant="elevated" @click="handleDone" prepend-icon="mdi-check" class="px-5 me-3"> 完成 </VBtn>
|
||||||
|
</VCardActions>
|
||||||
|
</VCard>
|
||||||
|
</VDialog>
|
||||||
|
</template>
|
||||||
@@ -26,6 +26,7 @@ const inProps = defineProps({
|
|||||||
storage: String,
|
storage: String,
|
||||||
path: String,
|
path: String,
|
||||||
fileid: String,
|
fileid: String,
|
||||||
|
pickcode: String,
|
||||||
endpoints: Object as PropType<EndPoints>,
|
endpoints: Object as PropType<EndPoints>,
|
||||||
axios: {
|
axios: {
|
||||||
type: Object as PropType<Axios>,
|
type: Object as PropType<Axios>,
|
||||||
@@ -118,6 +119,7 @@ async function load() {
|
|||||||
.replace(/{sort}/g, inProps.sort || 'name')
|
.replace(/{sort}/g, inProps.sort || 'name')
|
||||||
.replace(/{fileid}/g, inProps.fileid || '')
|
.replace(/{fileid}/g, inProps.fileid || '')
|
||||||
.replace(/{filetype}/g, isDir.value ? 'dir' : 'file')
|
.replace(/{filetype}/g, isDir.value ? 'dir' : 'file')
|
||||||
|
.replace(/{pickcode}/g, inProps.pickcode || '')
|
||||||
const config = {
|
const config = {
|
||||||
url,
|
url,
|
||||||
method: inProps.endpoints?.list.method || 'get',
|
method: inProps.endpoints?.list.method || 'get',
|
||||||
@@ -162,26 +164,26 @@ function changePath(item: FileItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 新窗口中下载文件
|
// 新窗口中下载文件
|
||||||
function download(path: string) {
|
function download(item: FileItem) {
|
||||||
if (!path) return
|
|
||||||
const token = store.state.auth.token
|
const token = store.state.auth.token
|
||||||
const url_path = inProps.endpoints?.download.url
|
const url_path = inProps.endpoints?.download.url
|
||||||
.replace(/{storage}/g, inProps.storage)
|
.replace(/{storage}/g, inProps.storage)
|
||||||
.replace(/{path}/g, encodeURIComponent(path))
|
.replace(/{path}/g, encodeURIComponent(item.path))
|
||||||
.replace(/{fileid}/g, inProps.fileid || '')
|
.replace(/{fileid}/g, item.fileid || '')
|
||||||
|
.replace(/{pickcode}/g, item.pickcode || '')
|
||||||
const url = `${import.meta.env.VITE_API_BASE_URL}${url_path.slice(1)}&token=${token}`
|
const url = `${import.meta.env.VITE_API_BASE_URL}${url_path.slice(1)}&token=${token}`
|
||||||
// 下载文件
|
// 下载文件
|
||||||
window.open(url, '_blank')
|
window.open(url, '_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示图片
|
// 显示图片
|
||||||
function getImgLink(path: string) {
|
function getImgLink(item: FileItem) {
|
||||||
if (!path) return ''
|
|
||||||
const token = store.state.auth.token
|
const token = store.state.auth.token
|
||||||
const url_path = inProps.endpoints?.image.url
|
const url_path = inProps.endpoints?.image.url
|
||||||
.replace(/{storage}/g, inProps.storage)
|
.replace(/{storage}/g, inProps.storage)
|
||||||
.replace(/{path}/g, encodeURIComponent(path))
|
.replace(/{path}/g, encodeURIComponent(item.path))
|
||||||
.replace(/{fileid}/g, inProps.fileid || '')
|
.replace(/{fileid}/g, item.fileid || '')
|
||||||
|
.replace(/{pickcode}/g, item.pickcode || '')
|
||||||
return `${import.meta.env.VITE_API_BASE_URL}${url_path.slice(1)}&token=${token}`
|
return `${import.meta.env.VITE_API_BASE_URL}${url_path.slice(1)}&token=${token}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +414,7 @@ onMounted(() => {
|
|||||||
<IconBtn v-if="isFile" @click="recognize(inProps.path || '')">
|
<IconBtn v-if="isFile" @click="recognize(inProps.path || '')">
|
||||||
<VIcon color="primary"> mdi-text-recognition </VIcon>
|
<VIcon color="primary"> mdi-text-recognition </VIcon>
|
||||||
</IconBtn>
|
</IconBtn>
|
||||||
<IconBtn v-if="isFile" @click="download(inProps.path || '')">
|
<IconBtn v-if="isFile && items.length > 0" @click="download(items[0])">
|
||||||
<VIcon color="primary"> mdi-download </VIcon>
|
<VIcon color="primary"> mdi-download </VIcon>
|
||||||
</IconBtn>
|
</IconBtn>
|
||||||
<IconBtn v-if="!isFile" @click="load">
|
<IconBtn v-if="!isFile" @click="load">
|
||||||
@@ -422,10 +424,8 @@ onMounted(() => {
|
|||||||
<VCardText v-if="loading" class="text-center flex flex-col items-center">
|
<VCardText v-if="loading" class="text-center flex flex-col items-center">
|
||||||
<VProgressCircular size="48" indeterminate color="primary" />
|
<VProgressCircular size="48" indeterminate color="primary" />
|
||||||
</VCardText>
|
</VCardText>
|
||||||
<VCardText v-if="!inProps.path" class="grow d-flex justify-center align-center grey--text">
|
<!-- 文件详情 -->
|
||||||
选择目录或文件
|
<VCardText v-else-if="isFile && !isImage && items.length > 0" class="text-center break-all">
|
||||||
</VCardText>
|
|
||||||
<VCardText v-else-if="isFile && !isImage && items[0]" class="text-center break-all">
|
|
||||||
<div v-if="items[0]?.thumbnail" class="flex justify-center">
|
<div v-if="items[0]?.thumbnail" class="flex justify-center">
|
||||||
<VImg max-width="15rem" cover :src="items[0]?.thumbnail" class="rounded border shadow-lg">
|
<VImg max-width="15rem" cover :src="items[0]?.thumbnail" class="rounded border shadow-lg">
|
||||||
<template #placeholder>
|
<template #placeholder>
|
||||||
@@ -434,14 +434,16 @@ onMounted(() => {
|
|||||||
</VImg>
|
</VImg>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xl text-high-emphasis mt-3">{{ items[0]?.name }}</div>
|
<div class="text-xl text-high-emphasis mt-3">{{ items[0]?.name }}</div>
|
||||||
<p class="mt-2">
|
<p class="mt-2" v-if="items[0]?.size && items[0].modify_time">
|
||||||
大小:{{ formatBytes(items[0]?.size || 0) }}<br />
|
大小:{{ formatBytes(items[0]?.size || 0) }}<br />
|
||||||
修改时间:{{ formatTime(items[0]?.modify_time || 0) }}
|
修改时间:{{ formatTime(items[0]?.modify_time || 0) }}
|
||||||
</p>
|
</p>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
<VCardText v-else-if="isFile && isImage" class="grow d-flex justify-center align-center">
|
<!-- 图片 -->
|
||||||
<VImg :src="getImgLink(inProps.path)" max-width="100%" max-height="100%" />
|
<VCardText v-else-if="isFile && isImage && items.length > 0" class="grow d-flex justify-center align-center">
|
||||||
|
<VImg :src="getImgLink(items[0])" max-width="100%" max-height="100%" />
|
||||||
</VCardText>
|
</VCardText>
|
||||||
|
<!-- 目录和文件列表 -->
|
||||||
<VCardText v-else-if="dirs.length || files.length" class="p-0">
|
<VCardText v-else-if="dirs.length || files.length" class="p-0">
|
||||||
<VList subheader>
|
<VList subheader>
|
||||||
<VVirtualScroll
|
<VVirtualScroll
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import FileBrowser from '@/components/FileBrowser.vue'
|
|||||||
|
|
||||||
const endpoints = {
|
const endpoints = {
|
||||||
list: {
|
list: {
|
||||||
url: '/{storage}/list?path={path}&sort={sort}&fileid={fileid}&filetype={filetype}',
|
url: '/{storage}/list?path={path}&sort={sort}&fileid={fileid}&filetype={filetype}&pickcode={pickcode}',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
},
|
},
|
||||||
mkdir: {
|
mkdir: {
|
||||||
@@ -17,11 +17,11 @@ const endpoints = {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
},
|
},
|
||||||
download: {
|
download: {
|
||||||
url: '/{storage}/download?path={path}&fileid={fileid}',
|
url: '/{storage}/download?path={path}&fileid={fileid}&pickcode={pickcode}',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
url: '/{storage}/image?path={path}&fileid={fileid}',
|
url: '/{storage}/image?path={path}&fileid={fileid}&pickcode={pickcode}',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
},
|
},
|
||||||
rename: {
|
rename: {
|
||||||
@@ -36,6 +36,9 @@ const path = ref<string>('')
|
|||||||
// 当前fileid
|
// 当前fileid
|
||||||
const fileid = ref<string>('root')
|
const fileid = ref<string>('root')
|
||||||
|
|
||||||
|
// 当前pickcode
|
||||||
|
const pickcode = ref<string>('')
|
||||||
|
|
||||||
// fileid的堆栈
|
// fileid的堆栈
|
||||||
const fileidstack = ref<string[]>(['root'])
|
const fileidstack = ref<string[]>(['root'])
|
||||||
|
|
||||||
@@ -92,6 +95,7 @@ async function loadDownloadDirectories() {
|
|||||||
// 目录变化
|
// 目录变化
|
||||||
function pathChanged(item: FileItem) {
|
function pathChanged(item: FileItem) {
|
||||||
path.value = item.path
|
path.value = item.path
|
||||||
|
pickcode.value = item.pickcode || ''
|
||||||
if (item.fileid) {
|
if (item.fileid) {
|
||||||
fileid.value = item.fileid
|
fileid.value = item.fileid
|
||||||
if (fileidstack.value.includes(item.fileid)) {
|
if (fileidstack.value.includes(item.fileid)) {
|
||||||
@@ -108,10 +112,11 @@ onBeforeMount(loadDownloadDirectories)
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<FileBrowser
|
<FileBrowser
|
||||||
storages="local,aliyun"
|
storages="local,aliyun,u115"
|
||||||
:tree="false"
|
:tree="false"
|
||||||
:path="path"
|
:path="path"
|
||||||
:fileid="fileid"
|
:fileid="fileid"
|
||||||
|
:pickcode="pickcode"
|
||||||
:fileidstack="fileidstack"
|
:fileidstack="fileidstack"
|
||||||
:endpoints="endpoints"
|
:endpoints="endpoints"
|
||||||
:axios="api"
|
:axios="api"
|
||||||
|
|||||||
Reference in New Issue
Block a user