feat: 搭建后台管理框架
This commit is contained in:
1 parent
6d28bab72b
commit
40546bfd01
238 files changed
+18160
-3837
No files matched your search
@@ -10,14 +10,71 @@ const { can } = useRbac()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-heading"><div><div class="eyebrow">内容概览</div><h1>工作台</h1><p>查看短剧内容与近期处理事项。</p></div><el-button v-if="can('创建短剧')" type="primary" class="primary-button" @click="router.push({name:'dramas'})"><el-icon><Plus /></el-icon>上传新短剧</el-button></div>
|
||||
<div class="page-heading"
|
||||
><div><div class="eyebrow">内容概览</div><h1>工作台</h1><p>查看短剧内容与近期处理事项。</p></div
|
||||
><el-button
|
||||
v-if="can('创建短剧')"
|
||||
type="primary"
|
||||
class="primary-button"
|
||||
@click="router.push({ name: 'dramas' })"
|
||||
><el-icon><Plus /></el-icon>上传新短剧</el-button
|
||||
></div
|
||||
>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card"><div class="stat-top"><span>短剧总数</span><span class="stat-icon"><el-icon><VideoCamera /></el-icon></span></div><div class="stat-value">{{dramas.length}} <small>部</small></div></div>
|
||||
<div class="stat-card"><div class="stat-top"><span>累计播放量</span><span class="stat-icon"><el-icon><CaretRight /></el-icon></span></div><div class="stat-value">8.64 <small>千万</small></div></div>
|
||||
<div class="stat-card"><div class="stat-top"><span>待审核内容</span><span class="stat-icon"><el-icon><Clock /></el-icon></span></div><div class="stat-value">06 <small>项</small></div></div>
|
||||
<div class="stat-card"><div class="stat-top"><span>本月新增用户</span><span class="stat-icon"><el-icon><User /></el-icon></span></div><div class="stat-value">12,486 <small>人</small></div></div>
|
||||
<div class="stat-card"
|
||||
><div class="stat-top"
|
||||
><span>短剧总数</span
|
||||
><span class="stat-icon"
|
||||
><el-icon><VideoCamera /></el-icon></span></div
|
||||
><div class="stat-value">{{ dramas.length }} <small>部</small></div></div
|
||||
>
|
||||
<div class="stat-card"
|
||||
><div class="stat-top"
|
||||
><span>累计播放量</span
|
||||
><span class="stat-icon"
|
||||
><el-icon><CaretRight /></el-icon></span></div
|
||||
><div class="stat-value">8.64 <small>千万</small></div></div
|
||||
>
|
||||
<div class="stat-card"
|
||||
><div class="stat-top"
|
||||
><span>待审核内容</span
|
||||
><span class="stat-icon"
|
||||
><el-icon><Clock /></el-icon></span></div
|
||||
><div class="stat-value">06 <small>项</small></div></div
|
||||
>
|
||||
<div class="stat-card"
|
||||
><div class="stat-top"
|
||||
><span>本月新增用户</span
|
||||
><span class="stat-icon"
|
||||
><el-icon><User /></el-icon></span></div
|
||||
><div class="stat-value">12,486 <small>人</small></div></div
|
||||
>
|
||||
</div>
|
||||
<section class="panel recent-panel"><div class="panel-heading"><div><h2>最近更新</h2><p>短剧内容与发布状态</p></div><el-button text class="view-all" @click="router.push({name:'dramas'})">短剧管理</el-button></div>
|
||||
<el-table :data="dramas.slice(0,5)" row-key="id" class="dashboard-el-table"><el-table-column prop="title" label="短剧名称" min-width="280"/><el-table-column prop="genre" label="类型" width="150"/><el-table-column label="集数" width="120"><template #default="{row}">{{row.episodes}} 集</template></el-table-column><el-table-column prop="views" label="播放量" width="140"/><el-table-column label="状态" width="130"><template #default="{row}"><el-tag :class="['status-badge',statusClass(row.status)]" effect="light">{{row.status}}</el-tag></template></el-table-column><el-table-column prop="updatedAt" label="更新时间" width="160"/></el-table>
|
||||
<section class="panel recent-panel"
|
||||
><div class="panel-heading"
|
||||
><div><h2>最近更新</h2><p>短剧内容与发布状态</p></div
|
||||
><el-button text class="view-all" @click="router.push({ name: 'dramas' })"
|
||||
>短剧管理</el-button
|
||||
></div
|
||||
>
|
||||
<el-table :data="dramas.slice(0, 5)" row-key="id" class="dashboard-el-table"
|
||||
><el-table-column prop="title" label="短剧名称" min-width="280" /><el-table-column
|
||||
prop="genre"
|
||||
label="类型"
|
||||
width="150" /><el-table-column label="集数" width="120"
|
||||
><template #default="scope">{{ scope?.row?.episodes }} 集</template></el-table-column
|
||||
><el-table-column prop="views" label="播放量" width="140" /><el-table-column
|
||||
label="状态"
|
||||
width="130"
|
||||
><template #default="scope"
|
||||
><el-tag
|
||||
v-if="scope?.row"
|
||||
:class="['status-badge', statusClass(scope.row.status)]"
|
||||
effect="light"
|
||||
>{{ scope.row.status }}</el-tag
|
||||
></template
|
||||
></el-table-column
|
||||
><el-table-column prop="updatedAt" label="更新时间" width="160"
|
||||
/></el-table>
|
||||
</section>
|
||||
</template>
|
||||
@@ -1,73 +0,0 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useAuth } from '@/stores/auth'
|
||||
|
||||
const router = useRouter()
|
||||
const { login } = useAuth()
|
||||
const form = ref({ username: 'admin', password: '' })
|
||||
const error = ref('')
|
||||
function submit() {
|
||||
if (!login(form.value.username, form.value.password)) {
|
||||
error.value = '账号或密码不正确。'
|
||||
return
|
||||
}
|
||||
error.value = ''
|
||||
ElMessage.success('登录成功')
|
||||
router.replace({ name: 'dashboard' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="login-screen">
|
||||
<section class="login-cover">
|
||||
<div class="cover-decoration decoration-one"></div><div class="cover-decoration decoration-two"></div>
|
||||
<div class="cover-logo"><div class="brand-mark"><span></span><span></span><span></span></div><span>reelshort</span><small>STUDIO CONSOLE</small></div>
|
||||
<div class="cover-copy"><span>REELSHORT STUDIO</span><h2>每一个故事<br>都值得被看见</h2><p>短剧内容创作与运营管理平台</p></div>
|
||||
<div class="cover-bottom">SHORT DRAMA · CONTENT STUDIO</div>
|
||||
</section>
|
||||
<section class="login-panel">
|
||||
<div class="login-content">
|
||||
<div class="login-heading"><h1>登录管理后台</h1><p>使用工作空间账号继续</p></div>
|
||||
<el-form label-position="top" @submit.prevent="submit">
|
||||
<el-form-item label="账号"><el-input v-model="form.username" placeholder="请输入账号" autocomplete="username" /></el-form-item>
|
||||
<el-form-item label="密码"><el-input v-model="form.password" type="password" placeholder="请输入密码" autocomplete="current-password" show-password @keyup.enter="submit" /></el-form-item>
|
||||
<div v-if="error" class="login-error">{{error}}</div>
|
||||
<el-button type="primary" class="login-submit primary-button" @click="submit">登录</el-button>
|
||||
</el-form>
|
||||
<div class="demo-credentials">演示账号:admin <i></i> 密码:admin123</div>
|
||||
</div>
|
||||
<footer class="login-footer">© 2026 ReelShort Studio</footer>
|
||||
</section>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.login-screen { min-height:100vh; display:grid; grid-template-columns:1.05fr .95fr; overflow:hidden; background:#f8f9fb; }
|
||||
.login-cover { position:relative; min-height:100vh; overflow:hidden; padding:42px 7vw; color:#fff; background:radial-gradient(ellipse at 72% 42%,rgba(196,167,150,.42),transparent 31%),radial-gradient(ellipse at 77% 44%,rgba(224,191,166,.62),transparent 16%),linear-gradient(160deg,#263d59 0%,#344d6c 44%,#1c2d44 100%); }
|
||||
.login-cover::after { content:''; position:absolute; inset:0; background:linear-gradient(180deg,rgba(22,37,58,.05) 30%,rgba(16,27,42,.72)); }
|
||||
.cover-logo,.cover-copy,.cover-bottom { position:relative; z-index:1; }
|
||||
.cover-logo { display:flex; align-items:center; gap:8px; width:max-content; font:800 16px Manrope,'Noto Sans SC',sans-serif; letter-spacing:-.5px; }
|
||||
.cover-logo small { margin-left:6px; padding-left:14px; border-left:1px solid rgba(255,255,255,.32); color:rgba(255,255,255,.66); font:600 9px Manrope,sans-serif; letter-spacing:1.7px; }
|
||||
.brand-mark { width:28px; height:28px; border-radius:8px; background:rgba(255,255,255,.2); display:flex; align-items:center; justify-content:center; gap:2px; transform:rotate(-8deg); }
|
||||
.brand-mark span { width:3px; border-radius:5px; background:#fff; transform:skew(-15deg); }
|
||||
.brand-mark span:nth-child(1) { height:11px; opacity:.75; }.brand-mark span:nth-child(2) { height:17px; }.brand-mark span:nth-child(3) { height:13px; opacity:.85; }
|
||||
.cover-copy { position:absolute; left:7vw; bottom:15%; }
|
||||
.cover-copy span { color:#d9b49d; font:600 10px Manrope,sans-serif; letter-spacing:2.4px; }
|
||||
.cover-copy h2 { margin:15px 0 12px; color:#fff; font-size:clamp(34px,4.1vw,56px); font-weight:700; line-height:1.35; letter-spacing:2px; }
|
||||
.cover-copy p { margin:0; color:rgba(255,255,255,.7); font-size:15px; letter-spacing:1px; }
|
||||
.cover-bottom { position:absolute; left:7vw; bottom:38px; color:rgba(255,255,255,.4); font:600 9px Manrope,sans-serif; letter-spacing:2px; }
|
||||
.cover-decoration { position:absolute; pointer-events:none; width:min(39vw,520px); aspect-ratio:.72; right:7%; top:14%; border:1px solid rgba(255,255,255,.13); border-radius:48% 48% 18px 18px; transform:rotate(7deg); background:linear-gradient(150deg,rgba(231,190,163,.14),rgba(25,42,64,.2) 62%); }
|
||||
.decoration-two { width:min(32vw,430px); right:12%; top:18%; transform:rotate(-7deg); opacity:.8; }
|
||||
.login-panel { position:relative; min-height:100vh; display:flex; flex-direction:column; justify-content:center; padding:64px clamp(42px,7vw,110px); background:#f8f9fb; }
|
||||
.login-content { width:min(100%,390px); align-self:center; }
|
||||
.login-heading { margin:0 0 27px; }.login-heading h1 { margin:0; color:#252d38; font-size:24px; font-weight:700; letter-spacing:-.5px; }.login-heading p { margin:8px 0 0; color:#7f8998; font-size:13px; }
|
||||
.login-panel :deep(.el-form-item) { margin-bottom:19px; }.login-panel :deep(.el-form-item__label) { padding-bottom:8px; color:#424c5a; font-size:14px; font-weight:600; }
|
||||
.login-panel :deep(.el-input__wrapper) { min-height:44px; border-radius:7px; background:#fff; box-shadow:0 0 0 1px #dce2e9 inset; }.login-panel :deep(.el-input__wrapper.is-focus) { box-shadow:0 0 0 1px #4773b3 inset; }.login-panel :deep(.el-input__inner) { font-size:15px; }
|
||||
.login-error { margin:-7px 0 14px; color:#d94b4b; font-size:13px; }.login-submit { width:100%; height:46px; margin-top:3px; border-radius:7px; background:#4773b3; border-color:#4773b3; font-size:15px; font-weight:600; }.login-submit:hover { background:#3d669f; border-color:#3d669f; }
|
||||
.demo-credentials { display:flex; align-items:center; justify-content:center; gap:8px; margin-top:18px; color:#8791a0; font-size:12px; }.demo-credentials i { width:3px; height:3px; border-radius:50%; background:#b6bec8; }
|
||||
.login-footer { position:absolute; left:clamp(42px,7vw,110px); bottom:32px; color:#a5acb7; font-size:11px; }
|
||||
@media(max-width:700px) { .login-screen { grid-template-columns:1fr; }.login-cover { min-height:250px; padding:24px 26px; }.cover-copy { left:26px; bottom:38px; }.cover-copy h2 { margin:9px 0 5px; font-size:30px; }.cover-copy p { font-size:12px; }.cover-bottom { display:none; }.cover-decoration { width:160px; right:10%; top:8%; }.decoration-two { width:135px; right:14%; top:12%; }.login-panel { min-height:auto; padding:42px 28px 72px; }.login-footer { left:28px; bottom:25px; } }
|
||||
@media(max-width:480px) { .login-cover { min-height:220px; padding:20px 22px; }.cover-copy { left:22px; bottom:30px; }.cover-copy h2 { font-size:26px; }.cover-logo small { display:none; }.login-panel { padding:34px 22px 68px; }.login-footer { left:22px; } }
|
||||
</style>
|
||||
Reference in new issue
Block a user