修复权限验证问题:普通用户无法访问后台管理页面
This commit is contained in:
@@ -1,6 +1,74 @@
|
||||
<template>
|
||||
<div class="works-page">
|
||||
<div class="toolbar">
|
||||
<!-- 左侧导航栏 -->
|
||||
<aside class="sidebar">
|
||||
<!-- Logo -->
|
||||
<div class="logo">logo</div>
|
||||
|
||||
<!-- 导航菜单 -->
|
||||
<nav class="nav-menu">
|
||||
<div class="nav-item" @click="goToProfile">
|
||||
<el-icon><User /></el-icon>
|
||||
<span>个人主页</span>
|
||||
</div>
|
||||
<div class="nav-item" @click="goToSubscription">
|
||||
<el-icon><Compass /></el-icon>
|
||||
<span>会员订阅</span>
|
||||
</div>
|
||||
<div class="nav-item active">
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>我的作品</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 工具分隔线 -->
|
||||
<div class="divider">
|
||||
<span>工具</span>
|
||||
</div>
|
||||
|
||||
<!-- 工具菜单 -->
|
||||
<nav class="tools-menu">
|
||||
<div class="nav-item" @click="goToTextToVideo">
|
||||
<el-icon><VideoPlay /></el-icon>
|
||||
<span>文生视频</span>
|
||||
</div>
|
||||
<div class="nav-item" @click="goToImageToVideo">
|
||||
<el-icon><Picture /></el-icon>
|
||||
<span>图生视频</span>
|
||||
</div>
|
||||
<div class="nav-item" @click="goToStoryboardVideo">
|
||||
<el-icon><Film /></el-icon>
|
||||
<span>分镜视频</span>
|
||||
<el-tag size="small" type="primary" class="sora-tag">Sora2.0</el-tag>
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
<main class="main-content">
|
||||
<!-- 顶部栏 -->
|
||||
<header class="top-header">
|
||||
<div class="header-right">
|
||||
<div class="discount-badge">
|
||||
<span class="discount-icon">+ 25</span>
|
||||
<span class="discount-text">首购优惠</span>
|
||||
</div>
|
||||
<div class="notification-bell">
|
||||
<el-icon><Bell /></el-icon>
|
||||
<span class="notification-badge">5</span>
|
||||
</div>
|
||||
<div class="user-avatar">
|
||||
<el-icon><User /></el-icon>
|
||||
</div>
|
||||
<div class="settings-icon">
|
||||
<el-icon><Setting /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="content-area">
|
||||
<div class="toolbar">
|
||||
<el-radio-group v-model="activeTab" size="small" class="seg-control">
|
||||
<el-radio-button label="all">全部</el-radio-button>
|
||||
<el-radio-button label="video">视频</el-radio-button>
|
||||
@@ -8,44 +76,55 @@
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<div class="filters-bar">
|
||||
<el-space wrap size="small" class="filters">
|
||||
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" size="small" />
|
||||
<el-select v-model="category" placeholder="任务类型" size="small" style="width: 120px" @change="onFilterChange">
|
||||
<el-option label="全部" value="all" />
|
||||
<el-option label="文生视频" value="text2video" />
|
||||
<el-option label="图生视频" value="image2video" />
|
||||
<el-option label="分镜视频" value="storyboard" />
|
||||
<el-option label="参考图" value="reference" />
|
||||
</el-select>
|
||||
<el-select v-model="resolution" placeholder="清晰度" clearable size="small" style="width: 120px">
|
||||
<el-option label="标清" value="sd" />
|
||||
<el-option label="高清" value="hd" />
|
||||
<el-option label="超清" value="uhd" />
|
||||
</el-select>
|
||||
<el-select v-model="sortBy" size="small" style="width: 120px">
|
||||
<el-option label="比例" value="ratio" />
|
||||
<el-option label="时间" value="date" />
|
||||
<el-option label="热门" value="hot" />
|
||||
</el-select>
|
||||
<el-select v-model="order" size="small" style="width: 100px">
|
||||
<el-option label="升序" value="asc" />
|
||||
<el-option label="降序" value="desc" />
|
||||
</el-select>
|
||||
</el-space>
|
||||
<div class="right">
|
||||
<el-input v-model="keyword" placeholder="名字/提示词/ID" size="small" clearable style="width: 220px" @keyup.enter.native="reload" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="filters-bar">
|
||||
<div class="filters-left">
|
||||
<el-select v-model="dateFilter" placeholder="日期" size="small" style="width: 100px">
|
||||
<el-option label="今天" value="today" />
|
||||
<el-option label="本周" value="week" />
|
||||
<el-option label="本月" value="month" />
|
||||
</el-select>
|
||||
<el-select v-model="category" placeholder="任务类型" size="small" style="width: 100px" @change="onFilterChange">
|
||||
<el-option label="全部" value="all" />
|
||||
<el-option label="文生视频" value="text2video" />
|
||||
<el-option label="图生视频" value="image2video" />
|
||||
<el-option label="分镜视频" value="storyboard" />
|
||||
</el-select>
|
||||
<el-select v-model="resolution" placeholder="清晰度" clearable size="small" style="width: 100px">
|
||||
<el-option label="标清" value="sd" />
|
||||
<el-option label="高清" value="hd" />
|
||||
<el-option label="超清" value="uhd" />
|
||||
</el-select>
|
||||
<el-select v-model="sortBy" placeholder="比例" size="small" style="width: 100px">
|
||||
<el-option label="比例" value="ratio" />
|
||||
<el-option label="时间" value="date" />
|
||||
<el-option label="热门" value="hot" />
|
||||
</el-select>
|
||||
<el-button size="small" @click="resetFilters">重置</el-button>
|
||||
</div>
|
||||
<div class="filters-right">
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
placeholder="名字/提示词/ID"
|
||||
size="small"
|
||||
clearable
|
||||
style="width: 220px"
|
||||
@keyup.enter.native="reload"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="select-row">
|
||||
<el-checkbox v-model="multiSelect" size="small">选择多个</el-checkbox>
|
||||
<template v-if="multiSelect && selectedIds.size">
|
||||
<el-tag type="success" size="small">已选 {{ selectedIds.size }} 个项目</el-tag>
|
||||
<el-button size="small" type="primary" @click="bulkDownload" plain>下载</el-button>
|
||||
<el-button size="small" type="danger" @click="bulkDelete" plain>删除</el-button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="select-row">
|
||||
<el-checkbox v-model="multiSelect" size="small">选择{{ selectedIds.size || 6 }}个项目</el-checkbox>
|
||||
<template v-if="multiSelect && selectedIds.size">
|
||||
<el-tag type="success" size="small">已选 {{ selectedIds.size }} 个项目</el-tag>
|
||||
<el-button size="small" type="primary" @click="bulkDownload" plain>下载</el-button>
|
||||
<el-button size="small" type="danger" @click="bulkDelete" plain>删除</el-button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<el-row :gutter="16" class="works-grid">
|
||||
<el-col v-for="item in filteredItems" :key="item.id" :xs="24" :sm="12" :md="8" :lg="6">
|
||||
@@ -223,9 +302,11 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<div class="finished" v-if="!hasMore && filteredItems.length>0">已加载全部内容</div>
|
||||
<el-empty v-if="!loading && filteredItems.length===0" description="没有找到相关内容" />
|
||||
</div>
|
||||
<div class="finished" v-if="!hasMore && filteredItems.length>0">已加载全部内容</div>
|
||||
<el-empty v-if="!loading && filteredItems.length===0" description="没有找到相关内容" />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@@ -233,12 +314,13 @@
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Star, MoreFilled, User } from '@element-plus/icons-vue'
|
||||
import { Star, User, Compass, Document, VideoPlay, Picture, Film, Bell, Setting, Search } from '@element-plus/icons-vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const activeTab = ref('all')
|
||||
const dateRange = ref([])
|
||||
const dateFilter = ref('')
|
||||
const category = ref('all')
|
||||
const resolution = ref('')
|
||||
const sortBy = ref('date')
|
||||
@@ -443,6 +525,42 @@ const bulkDelete = async () => {
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
// 导航方法
|
||||
const goToProfile = () => {
|
||||
console.log('导航到个人主页')
|
||||
router.push('/profile')
|
||||
}
|
||||
|
||||
const goToSubscription = () => {
|
||||
console.log('导航到会员订阅')
|
||||
router.push('/subscription')
|
||||
}
|
||||
|
||||
const goToTextToVideo = () => {
|
||||
console.log('导航到文生视频')
|
||||
router.push('/text-to-video')
|
||||
}
|
||||
|
||||
const goToImageToVideo = () => {
|
||||
console.log('导航到图生视频')
|
||||
router.push('/image-to-video')
|
||||
}
|
||||
|
||||
const goToStoryboardVideo = () => {
|
||||
console.log('导航到分镜视频')
|
||||
router.push('/storyboard-video')
|
||||
}
|
||||
|
||||
// 重置筛选器
|
||||
const resetFilters = () => {
|
||||
dateFilter.value = ''
|
||||
category.value = 'all'
|
||||
resolution.value = ''
|
||||
sortBy.value = 'date'
|
||||
keyword.value = ''
|
||||
ElMessage.success('筛选器已重置')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadList()
|
||||
})
|
||||
@@ -450,8 +568,189 @@ onMounted(() => {
|
||||
|
||||
<style scoped>
|
||||
.works-page {
|
||||
padding: 16px 20px;
|
||||
min-height: 100vh;
|
||||
background: #0a0a0a;
|
||||
color: white;
|
||||
display: flex;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 页面特殊效果 */
|
||||
.works-page::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background:
|
||||
radial-gradient(circle at 10% 20%, rgba(64, 158, 255, 0.1) 0%, transparent 50%),
|
||||
radial-gradient(circle at 90% 80%, rgba(103, 194, 58, 0.1) 0%, transparent 50%),
|
||||
radial-gradient(circle at 50% 50%, rgba(230, 162, 60, 0.05) 0%, transparent 50%);
|
||||
animation: profileGlow 6s ease-in-out infinite alternate;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@keyframes profileGlow {
|
||||
0% { opacity: 0.3; }
|
||||
100% { opacity: 0.6; }
|
||||
}
|
||||
|
||||
.works-page > * {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* 左侧导航栏 */
|
||||
.sidebar {
|
||||
width: 280px !important;
|
||||
background: #1a1a1a !important;
|
||||
padding: 24px 0 !important;
|
||||
border-right: 1px solid #1a1a1a !important;
|
||||
flex-shrink: 0 !important;
|
||||
z-index: 100 !important;
|
||||
display: block !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.logo {
|
||||
padding: 0 24px 32px;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-menu, .tools-menu {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 14px 18px;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
background: #1e3a8a;
|
||||
}
|
||||
|
||||
.nav-item .el-icon {
|
||||
margin-right: 14px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.nav-item span {
|
||||
font-size: 15px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sora-tag {
|
||||
margin-left: 8px;
|
||||
font-size: 10px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 30px 20px 20px;
|
||||
padding: 0 16px;
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
/* 主内容区域 */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.top-header {
|
||||
padding: 20px 30px;
|
||||
border-bottom: 1px solid #333;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.discount-badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
padding: 6px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.discount-icon {
|
||||
background: #1e40af;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.notification-bell {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: #9ca3af;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
min-width: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-avatar, .settings-icon {
|
||||
cursor: pointer;
|
||||
color: #9ca3af;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.user-avatar:hover, .settings-icon:hover, .notification-bell:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.content-area {
|
||||
flex: 1;
|
||||
padding: 20px 24px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -477,16 +776,30 @@ onMounted(() => {
|
||||
}
|
||||
.filters { margin-left: 10px; }
|
||||
.filters-bar {
|
||||
display:flex;
|
||||
align-items:center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4px 0 2px;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #333;
|
||||
margin-bottom: 16px;
|
||||
background: #1a1a1a;
|
||||
/* 覆盖 Element Plus 变量,确保与页面背景一致 */
|
||||
--el-input-bg-color: #0a0a0a;
|
||||
--el-fill-color-blank: #0a0a0a;
|
||||
--el-border-color: #2a2a2a;
|
||||
--el-text-color-regular: #cbd5e1;
|
||||
}
|
||||
|
||||
.filters-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filters-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
:deep(.filters .el-select .el-input__wrapper),
|
||||
:deep(.filters .el-date-editor.el-input__wrapper),
|
||||
:deep(.filters .el-input__wrapper) {
|
||||
|
||||
Reference in New Issue
Block a user