调整,音乐模块
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { Check, Cloud, Loader2, Pencil, Plus, Power, Trash2 } from '@lucide/vue'
|
||||
import { useFeiniuStore, type FeiniuConnection } from '@/stores/feiniuStore'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle
|
||||
} from '@/components/ui/dialog'
|
||||
|
||||
const store = useFeiniuStore()
|
||||
|
||||
const editing = ref<Partial<FeiniuConnection> | null>(null)
|
||||
const editOpen = ref(false)
|
||||
const password = ref('')
|
||||
const testing = ref(false)
|
||||
const fnosPassword = ref('')
|
||||
const fnosFormOpen = ref(false)
|
||||
/** 目标 fnOS 登录连接 */
|
||||
const fnosTarget = ref<FeiniuConnection | null>(null)
|
||||
|
||||
function newForm() {
|
||||
editing.value = { name: '', kind: 'lan', baseUrl: '', username: '', accessCode: '', insecure: false, fnId: '' }
|
||||
password.value = ''
|
||||
editOpen.value = true
|
||||
}
|
||||
|
||||
function editForm(c: FeiniuConnection) {
|
||||
editing.value = { ...c }
|
||||
password.value = ''
|
||||
editOpen.value = true
|
||||
}
|
||||
|
||||
function openFnosLogin(c: FeiniuConnection) {
|
||||
fnosTarget.value = c
|
||||
fnosPassword.value = ''
|
||||
fnosFormOpen.value = true
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (!editing.value) return
|
||||
if (!editing.value.name?.trim() || !editing.value.baseUrl?.trim()) {
|
||||
toast.error('请填写名称与服务器地址')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const id = await store.saveConnection({
|
||||
id: editing.value.id || '',
|
||||
name: editing.value.name.trim(),
|
||||
kind: editing.value.kind || 'lan',
|
||||
baseUrl: editing.value.baseUrl.trim(),
|
||||
username: editing.value.username || '',
|
||||
accessCode: editing.value.accessCode || '',
|
||||
insecure: !!editing.value.insecure,
|
||||
fnId: editing.value.fnId || ''
|
||||
})
|
||||
if (password.value) {
|
||||
await store.login(id, editing.value.username || '', password.value)
|
||||
}
|
||||
editOpen.value = false
|
||||
toast.success('已保存')
|
||||
} catch (e) {
|
||||
toast.error(String(e))
|
||||
}
|
||||
}
|
||||
|
||||
async function test(c: FeiniuConnection) {
|
||||
if (!password.value) {
|
||||
toast.error('请输入密码再测试')
|
||||
return
|
||||
}
|
||||
testing.value = true
|
||||
try {
|
||||
await store.testConnection(c.id, c.username, password.value)
|
||||
toast.success('连接成功')
|
||||
} catch (e) {
|
||||
toast.error(String(e))
|
||||
} finally {
|
||||
testing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function activate(c: FeiniuConnection) {
|
||||
await store.activateConnection(c.id)
|
||||
toast.success('已切换为激活连接')
|
||||
}
|
||||
|
||||
async function logout(c: FeiniuConnection) {
|
||||
await store.logout(c.id)
|
||||
toast.success('已登出')
|
||||
}
|
||||
|
||||
async function remove(c: FeiniuConnection) {
|
||||
await store.deleteConnection(c.id)
|
||||
toast.success('已删除')
|
||||
}
|
||||
|
||||
async function fnosLogin() {
|
||||
if (!fnosTarget.value) return
|
||||
if (!fnosPassword.value) {
|
||||
toast.error('请输入 NAS 密码')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await store.fnosLogin(fnosTarget.value.username, fnosPassword.value)
|
||||
fnosFormOpen.value = false
|
||||
toast.success('NAS 文件服务已连接')
|
||||
} catch (e) {
|
||||
toast.error(String(e))
|
||||
}
|
||||
}
|
||||
|
||||
function kindLabel(k: string) {
|
||||
return k === 'lan' ? '局域网' : k === 'frp' ? 'frp 域名' : 'FnConnect'
|
||||
}
|
||||
|
||||
onMounted(() => store.refreshConnections())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<Label class="text-muted-foreground">飞牛音乐连接</Label>
|
||||
<Button variant="outline" size="sm" @click="newForm">
|
||||
<Plus class="size-4" /> 新建
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div
|
||||
v-for="c in store.connections"
|
||||
:key="c.id"
|
||||
class="flex items-center gap-3 rounded-lg border bg-card px-3 py-2"
|
||||
>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="truncate text-sm font-medium">{{ c.name }}</span>
|
||||
<Badge variant="secondary" class="text-[10px]">{{ kindLabel(c.kind) }}</Badge>
|
||||
<Badge v-if="store.activeId === c.id" variant="default" class="text-[10px]">激活</Badge>
|
||||
</div>
|
||||
<div class="truncate text-xs text-muted-foreground">
|
||||
{{ c.baseUrl }}<template v-if="c.username"> · {{ c.username }}</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-1">
|
||||
<span v-if="c.loggedIn" class="mr-1 flex items-center gap-1 text-xs text-emerald-600">
|
||||
<Check class="size-3.5" /> 已登录
|
||||
</span>
|
||||
<Button v-if="store.activeId !== c.id" variant="ghost" size="icon" class="size-8" @click="activate(c)">
|
||||
<Power class="size-4" />
|
||||
</Button>
|
||||
<Button v-if="store.activeId === c.id && !store.fnosLoggedIn" variant="ghost" size="icon" class="size-8" :title="`连接 NAS 文件服务(${c.username})`" @click="openFnosLogin(c)">
|
||||
<Cloud class="size-4" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" class="size-8" @click="editForm(c)">
|
||||
<Pencil class="size-4" />
|
||||
</Button>
|
||||
<Button v-if="c.loggedIn" variant="ghost" size="icon" class="size-8" @click="logout(c)">
|
||||
<Power class="size-4" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" class="size-8 text-destructive" @click="remove(c)">
|
||||
<Trash2 class="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!store.connections.length" class="text-xs text-muted-foreground">
|
||||
还没有连接。新建一个并填写 NAS 地址(局域网 http://192.168.x.x:5666、frp 域名或 FnConnect fnId)。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Dialog v-model:open="editOpen">
|
||||
<DialogContent class="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ editing?.id ? '编辑连接' : '新建连接' }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="space-y-1.5">
|
||||
<Label>名称</Label>
|
||||
<Input v-model="editing!.name" placeholder="如:家里 NAS / frp 远程 / FnConnect" />
|
||||
</div>
|
||||
<div class="space-y-1.5">
|
||||
<Label>类型</Label>
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
v-for="k in (['lan', 'frp', 'fnconnect'] as const)"
|
||||
:key="k"
|
||||
type="button"
|
||||
size="sm"
|
||||
:variant="editing!.kind === k ? 'default' : 'outline'"
|
||||
@click="editing!.kind = k"
|
||||
>
|
||||
{{ kindLabel(k) }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="editing!.kind === 'fnconnect'" class="space-y-1.5">
|
||||
<Label>FnConnect fnId(fnos.net/xxx 或裸 id)</Label>
|
||||
<Input v-model="editing!.fnId" placeholder="fnos.net/zy2060537" />
|
||||
<p class="text-xs text-muted-foreground">
|
||||
保存后点登录会自动解析到可达地址;服务器地址会回填。
|
||||
</p>
|
||||
</div>
|
||||
<div v-else class="space-y-1.5">
|
||||
<Label>服务器地址</Label>
|
||||
<Input v-model="editing!.baseUrl" placeholder="http://192.168.1.10:5666 或 https://xxx.xxx.com" />
|
||||
</div>
|
||||
<div class="space-y-1.5">
|
||||
<Label>账号</Label>
|
||||
<Input v-model="editing!.username" placeholder="飞牛音乐账号" />
|
||||
</div>
|
||||
<div class="space-y-1.5">
|
||||
<Label>密码{{ password ? '' : '(留空则保留已存 token)' }}</Label>
|
||||
<Input v-model="password" type="password" placeholder="登录密码" />
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<Label class="text-muted-foreground">忽略 HTTPS 证书校验(自签证书时勾选)</Label>
|
||||
<Switch v-model:model-value="editing!.insecure" />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter class="gap-2">
|
||||
<Button variant="outline" :disabled="testing" @click="test(editing as unknown as FeiniuConnection)">
|
||||
<Loader2 v-if="testing" class="size-4 animate-spin" /> 测试
|
||||
</Button>
|
||||
<Button @click="save">保存</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<!-- fnOS 文件服务登录(上传到飞牛用) -->
|
||||
<Dialog v-model:open="fnosFormOpen">
|
||||
<DialogContent class="sm:max-w-sm">
|
||||
<DialogHeader>
|
||||
<DialogTitle>连接 NAS 文件服务</DialogTitle>
|
||||
</DialogHeader>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
账号:{{ fnosTarget?.username }}。连接后即可把本地音乐上传到飞牛曲库目录、从曲库删除音乐。
|
||||
</p>
|
||||
<div class="space-y-1.5">
|
||||
<Label>NAS 密码</Label>
|
||||
<Input v-model="fnosPassword" type="password" placeholder="NAS 登录密码" @keydown.enter="fnosLogin" />
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" @click="fnosFormOpen = false">取消</Button>
|
||||
<Button @click="fnosLogin">连接</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user