feat(admin): 实现管理员登录认证和页面权限控制

- 添加管理员密码验证登录功能
- 实现登录状态管理和用户界面显示
- 集成权限检查确保页面访问安全
- 添加登录/登出流程处理
- 重构AdminView组件结构和样式
- 集成Element Plus图标和UI组件
- 添加设置页面路由配置
- 优化Token管理页面折叠表单设计
- 移除旧的响应式布局相关代码
- 更新应用标题动态渲染逻辑
This commit is contained in:
2026-06-19 17:36:50 +08:00
parent 4100a51eb8
commit fc640407d9
10 changed files with 246 additions and 308 deletions
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
TODO
</template>
<style scoped>
</style>
+1 -36
View File
@@ -143,19 +143,8 @@ const statCards = [
<template>
<div class="token-detail">
<!-- 检查权限 -->
<div v-if="!store.isAdmin" class="no-permission">
<div class="no-permission-card">
<el-icon size="64" color="#f56c6c">
<InfoFilled/>
</el-icon>
<div class="no-permission-title">无权限访问</div>
<div class="no-permission-text">您没有权限访问此页面</div>
</div>
</div>
<!-- 管理页面 -->
<div v-else class="detail-page">
<div class="detail-page">
<div class="content-card">
<div class="page-title">Token 详情</div>
@@ -321,30 +310,6 @@ const statCards = [
padding: 0;
}
/* 无权限 */
.no-permission {
display: flex;
justify-content: center;
align-items: center;
min-height: 60vh;
}
.no-permission-card {
text-align: center;
padding: 48px;
}
.no-permission-title {
font-size: 24px;
font-weight: 600;
margin-top: 24px;
margin-bottom: 8px;
}
.no-permission-text {
color: var(--el-text-color-secondary);
}
/* Token 选择 */
.token-select {
display: flex;
+39 -127
View File
@@ -1,7 +1,7 @@
<script setup lang="ts">
import api from "@/api"
import {useCounterStore} from "@/stores/counter.ts"
import {Delete, Edit, Key, Lock, Memo, Plus, View} from '@element-plus/icons-vue'
import {Delete, Edit, Key, Memo, Plus, View} from '@element-plus/icons-vue'
const store = useCounterStore()
const router = useRouter()
@@ -12,8 +12,7 @@ const input = ref('')
const value = ref('')
const dataFormat = ref('')
const inputNotes = ref('')
const inputPassWord = ref('')
const passwordVisible = ref(true)
const activeNames = ref(['1'])
const rowOut = ref<any>(null)
const addDataDialogVisible = ref(false)
@@ -46,24 +45,11 @@ const fetchTokens = async () => {
}
onMounted(() => {
if (!store.isAdmin) {
passwordVisible.value = true
} else {
if (store.isAdmin) {
fetchTokens()
}
})
const checkPassword = () => {
if (inputPassWord.value === "haha") {
ElMessage({message: '登录成功', type: 'success'})
store.isAdmin = true
passwordVisible.value = false
fetchTokens()
} else {
ElMessage.error('密码错误')
}
}
const addToken = async () => {
if (!input.value || !value.value || !dataFormat.value) {
ElMessage.warning('请填写完整信息')
@@ -176,79 +162,49 @@ const deleteToken = async (row: any) => {
<template>
<div class="token-manage">
<!-- 登录页面 -->
<div v-if="!store.isAdmin" class="login-page">
<div class="login-card">
<div class="login-icon">
<el-icon size="48" color="#409eff">
<Lock/>
</el-icon>
</div>
<div class="login-title">管理员登录</div>
<div class="login-subtitle">请输入管理员密码访问管理后台</div>
<el-input
v-model="inputPassWord"
type="password"
placeholder="请输入管理员密码"
size="large"
show-password
@keyup.enter="checkPassword"
>
<template #prefix>
<el-icon>
<Lock/>
</el-icon>
</template>
</el-input>
<el-button type="primary" size="large" class="login-btn" @click="checkPassword">
登录
</el-button>
</div>
</div>
<!-- 管理页面 -->
<div v-else class="manage-page">
<div class="manage-page">
<div class="content-card">
<div class="page-title">Token 管理</div>
<!-- 添加表单 -->
<div class="add-form">
<div class="form-title">添加新 Token</div>
<div class="form-grid">
<el-input v-model="input" placeholder="Token 名称" clearable>
<template #prefix>
<el-collapse class="add-form" v-model="activeNames">
<el-collapse-item title="添加新 Token" name="1">
<div class="form-grid">
<el-input v-model="input" placeholder="Token 名称" clearable>
<template #prefix>
<el-icon>
<Key/>
</el-icon>
</template>
</el-input>
<el-select v-model="value" placeholder="去重对象" clearable>
<el-option v-for="item in options" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-select v-model="dataFormat" placeholder="数据格式" clearable>
<el-option v-for="item in dataFormatOptions" :key="item.value" :value="item.value"
:label="item.label"/>
</el-select>
<el-input v-model="inputNotes" placeholder="备注(可选)" clearable>
<template #prefix>
<el-icon>
<Memo/>
</el-icon>
</template>
</el-input>
<el-button type="primary" @click="addToken">
<el-icon>
<Key/>
<Plus/>
</el-icon>
</template>
</el-input>
<el-select v-model="value" placeholder="去重对象" clearable>
<el-option v-for="item in options" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-select v-model="dataFormat" placeholder="数据格式" clearable>
<el-option v-for="item in dataFormatOptions" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-input v-model="inputNotes" placeholder="备注(可选)" clearable>
<template #prefix>
<el-icon>
<Memo/>
</el-icon>
</template>
</el-input>
<el-button type="primary" @click="addToken">
<el-icon>
<Plus/>
</el-icon>
添加
</el-button>
</div>
</div>
添加
</el-button>
</div>
</el-collapse-item>
</el-collapse>
<!-- Token 列表 -->
<div class="table-section">
@@ -387,50 +343,6 @@ const deleteToken = async (row: any) => {
padding: 0;
}
/* 登录页面 */
.login-page {
display: flex;
justify-content: center;
align-items: center;
min-height: 60vh;
}
.login-card {
width: 100%;
max-width: 400px;
text-align: center;
padding: 48px 40px;
background: var(--bg-card);
border-radius: 16px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
}
.login-icon {
margin-bottom: 24px;
}
.login-title {
font-size: 24px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 8px;
}
.login-subtitle {
font-size: 14px;
color: var(--el-text-color-secondary);
margin-bottom: 32px;
}
.login-card :deep(.el-input) {
margin-bottom: 16px;
}
.login-btn {
width: 100%;
margin-top: 8px;
}
/* 管理页面 */
.add-form {
margin-bottom: 32px;