release: v0.4.0

This commit is contained in:
2026-05-18 05:11:57 +08:00
parent b758391861
commit da5bd01535
147 changed files with 8876 additions and 6941 deletions

View File

@@ -28,14 +28,6 @@
<el-button type="primary" size="large" @click="handleSearch" class="result-search-btn"> </el-button>
</div>
</div>
<!-- 右上角登录/用户信息独立于搜索栏 -->
<div class="top-right-user">
<template v-if="userInfo">
<span class="user-badge">{{ userInfo.username }}</span>
<el-button size="small" text @click="handleLogout">退出</el-button>
</template>
<el-button v-else size="small" @click="showLogin = true">登录</el-button>
</div>
</div>
<!-- 滚动通知条跑马灯 -->
@@ -151,7 +143,7 @@
:data="item"
:fallbackTags="contentTags"
:fallbackImage="fallbackImage"
:loggedIn="userInfo !== null"
:loggedIn="false"
:cloudTypeMap="cloudTypeMap"
@save="handleSave"
/>
@@ -183,7 +175,7 @@
:data="item"
:fallbackTags="contentTags"
:fallbackImage="fallbackImage"
:loggedIn="userInfo !== null"
:loggedIn="false"
:cloudTypeMap="cloudTypeMap"
@save="handleSave"
/>
@@ -346,21 +338,6 @@
</el-dialog>
</div>
<!-- 登录弹窗 -->
<el-dialog v-model="showLogin" title="登录" width="380px" :close-on-click-modal="false" top="25vh">
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" label-width="0" @keyup.enter="handleLogin">
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="用户名" prefix-icon="User" />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" placeholder="密码" prefix-icon="Lock" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loginLoading" style="width: 100%" @click="handleLogin">登录</el-button>
</el-form-item>
</el-form>
<p v-if="loginError" class="login-error">{{ loginError }}</p>
</el-dialog>
<div v-if="siteDisclaimer" class="site-footer">
<div class="footer-inner">{{ siteDisclaimer }}</div>
<div class="footer-actions">
@@ -376,7 +353,7 @@ import { Search, Loading, CircleCheckFilled } from '@element-plus/icons-vue'
import QRCode from 'qrcode'
import ResultCard from '../components/ResultCard.vue'
import VideoResultCard from '../components/VideoResultCard.vue'
import { query as searchQuery, saveToCloud, saveVideoToCloud, getSystemConfigs, getCloudTypes, streamSearch, adminLogin, getMe } from '../api'
import { query as searchQuery, saveToCloud, saveVideoToCloud, getSystemConfigs, getCloudTypes, streamSearch, getSiteConfig } from '../api'
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import type { SearchResult, VideoParseResult, SaveResult, IntentType, CloudType, ChannelGroup } from '../types'
@@ -417,17 +394,6 @@ const siteDisclaimer = ref('')
const siteMarquee = ref('')
const coverError = ref(false)
// 登录状态
const userInfo = ref<{ username: string } | null>(null)
const showLogin = ref(false)
const loginFormRef = ref<FormInstance>()
const loginForm = reactive({ username: '', password: '' })
const loginLoading = ref(false)
const loginError = ref('')
const loginRules = {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
}
const allResultsMap = ref(new Map<string, any>())
const validResults = ref<any[]>([])
@@ -456,43 +422,22 @@ async function loadCloudTypes() {
}
onMounted(async () => {
// 预加载网站配置logo/名称/公告等)
try {
const sc = await getSiteConfig()
if (sc.site_logo) siteLogo.value = sc.site_logo
if (sc.site_name) siteName.value = sc.site_name
if (sc.site_disclaimer) siteDisclaimer.value = sc.site_disclaimer
if (sc.site_marquee) siteMarquee.value = sc.site_marquee
} catch {}
const q = (route.query.q as string) || ''
if (q) {
query.value = q
doSearch(q)
}
// 检查登录状态
const me: any = await getMe().catch(() => ({ loggedIn: false }))
if (me.loggedIn && me.username) {
userInfo.value = { username: me.username }
}
loadCloudTypes()
})
async function handleLogin() {
const valid = await loginFormRef.value?.validate().catch(() => false)
if (!valid) return
loginLoading.value = true
loginError.value = ''
try {
const res = await adminLogin(loginForm.username, loginForm.password)
localStorage.setItem('admin_token', res.token)
userInfo.value = { username: loginForm.username }
showLogin.value = false
loginForm.password = ''
ElMessage.success('登录成功')
} catch (e: any) {
loginError.value = e?.response?.data?.error || e?.message || '登录失败'
} finally {
loginLoading.value = false
}
}
function handleLogout() {
localStorage.removeItem('admin_token')
userInfo.value = null
ElMessage.success('已退出')
}
// 网盘分类标签 — 始终展示所有已知云盘类型0 也显示)
const cloudTabs = computed(() => {