You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/src/views/index.vue

584 lines
18 KiB
Vue

<template>
<div class="index">
<div v-if="role == '1'" class="school-admin-workbench">
<!-- 英雄区 -->
<section class="admin-hero">
<!-- 装饰背景 -->
<svg class="hero-decoration" viewBox="0 0 400 200" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#00aaff;stop-opacity:0.15" />
<stop offset="100%" style="stop-color:#00aaff;stop-opacity:0" />
</linearGradient>
<linearGradient id="grad2" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#00aaff;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:transparent;stop-opacity:0" />
</linearGradient>
</defs>
<!-- 圆形装饰 -->
<circle cx="350" cy="30" r="80" fill="url(#grad1)" />
<circle cx="380" cy="60" r="50" fill="none" stroke="#00aaff" stroke-width="0.5" opacity="0.3" />
<circle cx="380" cy="60" r="70" fill="none" stroke="#00aaff" stroke-width="0.3" opacity="0.2" />
<!-- 网格线 -->
<line x1="0" y1="100" x2="400" y2="100" stroke="url(#grad2)" stroke-width="0.5" />
<line x1="200" y1="0" x2="200" y2="200" stroke="url(#grad2)" stroke-width="0.5" />
<!-- 数据点 -->
<circle cx="50" cy="150" r="3" fill="#00aaff" opacity="0.6" />
<circle cx="100" cy="120" r="2" fill="#00aaff" opacity="0.4" />
<circle cx="150" cy="160" r="2.5" fill="#00aaff" opacity="0.5" />
<circle cx="300" cy="140" r="2" fill="#00aaff" opacity="0.4" />
<!-- 连接线 -->
<path d="M50 150 L100 120 L150 160 L300 140" fill="none" stroke="#00aaff" stroke-width="0.5" opacity="0.3" stroke-dasharray="4,4" />
</svg>
<div class="admin-badge">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>
Platform Admin / Console
</div>
<h1 class="admin-title">平台超管工作台</h1>
<p class="admin-subtitle">统一维护学校档案和教师账号,管理型老师由平台超管指定。</p>
<!-- 顶部装饰图标 -->
<div class="hero-icons">
<div class="hero-icon-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="1.5">
<rect x="3" y="3" width="7" height="7" rx="1"/>
<rect x="14" y="3" width="7" height="7" rx="1"/>
<rect x="3" y="14" width="7" height="7" rx="1"/>
<rect x="14" y="14" width="7" height="7" rx="1"/>
</svg>
</div>
<div class="hero-icon-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="1.5">
<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
</svg>
</div>
<div class="hero-icon-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="1.5">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
</svg>
</div>
</div>
</section>
<!-- 主面板 -->
<section class="admin-panel">
<div class="panel-header">
<div class="panel-title-group">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="2">
<rect x="3" y="3" width="7" height="7"/>
<rect x="14" y="3" width="7" height="7"/>
<rect x="14" y="14" width="7" height="7"/>
<rect x="3" y="14" width="7" height="7"/>
</svg>
<span class="admin-panel-title">快捷入口</span>
</div>
</div>
<div class="quick-grid">
<!-- 学校管理卡片 -->
<div class="quick-card" @click="go('/platform-schools/index')">
<div class="card-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M3 21h18"/>
<path d="M5 21V7l8-4v18"/>
<path d="M19 21V11l-6-4"/>
<path d="M9 9v.01M9 12v.01M9 15v.01M9 18v.01"/>
</svg>
</div>
<div class="quick-label">Schools</div>
<h2>学校管理</h2>
<p>新增、编辑、删除学校基础信息。</p>
<el-button type="primary">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
进入管理
</el-button>
</div>
<!-- 教师管理卡片 -->
<div class="quick-card" @click="go('/platform-teachers/index')">
<div class="card-icon teacher">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
</div>
<div class="quick-label">Teachers</div>
<h2>教师管理</h2>
<p>维护教师账号,并指定是否为管理型老师。</p>
<el-button type="primary">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
进入管理
</el-button>
</div>
</div>
</section>
<!-- 新增:数据统计区 -->
<section class="admin-panel stats-panel">
<div class="panel-header">
<div class="panel-title-group">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="2">
<path d="M18 20V10"/>
<path d="M12 20V4"/>
<path d="M6 20v-6"/>
</svg>
<span class="admin-panel-title">数据概览</span>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="1.5">
<path d="M3 21h18"/>
<path d="M5 21V7l8-4v18"/>
</svg>
</div>
<div class="stat-info">
<span class="stat-value">28</span>
<span class="stat-label">入驻学校</span>
</div>
<div class="stat-trend up">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 15l-6-6-6 6"/>
</svg>
+2
</div>
</div>
<div class="stat-card">
<div class="stat-icon accent">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ff6b35" stroke-width="1.5">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
</svg>
</div>
<div class="stat-info">
<span class="stat-value">156</span>
<span class="stat-label">认证教师</span>
</div>
<div class="stat-trend up">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 15l-6-6-6 6"/>
</svg>
+12
</div>
</div>
<div class="stat-card">
<div class="stat-icon success">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#00ff9d" stroke-width="1.5">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
<path d="M22 4L12 14.01l-3-3"/>
</svg>
</div>
<div class="stat-info">
<span class="stat-value">4,820</span>
<span class="stat-label">注册学生</span>
</div>
<div class="stat-trend up">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 15l-6-6-6 6"/>
</svg>
+156
</div>
</div>
<div class="stat-card">
<div class="stat-icon warning">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffbe00" stroke-width="1.5">
<circle cx="12" cy="12" r="10"/>
<path d="M12 6v6l4 2"/>
</svg>
</div>
<div class="stat-info">
<span class="stat-value">3</span>
<span class="stat-label">待审核</span>
</div>
<div class="stat-trend down">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
-5
</div>
</div>
</div>
</section>
<!-- 新增:最近动态 -->
<section class="admin-panel activity-panel">
<div class="panel-header">
<div class="panel-title-group">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<path d="M12 6v6l4 2"/>
</svg>
<span class="admin-panel-title">最近动态</span>
</div>
</div>
<div class="activity-list">
<div class="activity-item">
<div class="activity-dot school"></div>
<div class="activity-content">
<p class="activity-text"><strong>华东理工大学</strong> 提交入驻申请</p>
<span class="activity-time">10 分钟前</span>
</div>
</div>
<div class="activity-item">
<div class="activity-dot teacher"></div>
<div class="activity-content">
<p class="activity-text"><strong>张老师</strong> 申请成为管理教师</p>
<span class="activity-time">25 分钟前</span>
</div>
</div>
<div class="activity-item">
<div class="activity-dot success"></div>
<div class="activity-content">
<p class="activity-text"><strong>清华大学</strong> 资质审核通过</p>
<span class="activity-time">1 小时前</span>
</div>
</div>
<div class="activity-item">
<div class="activity-dot teacher"></div>
<div class="activity-content">
<p class="activity-text"><strong>李老师</strong> 完成教师认证</p>
<span class="activity-time">2 小时前</span>
</div>
</div>
</div>
</section>
</div>
<div v-else-if="role == '2'" class="school-admin-workbench">
<section class="admin-hero">
<div class="admin-badge">School Admin / Console</div>
<h1 class="admin-title">学校管理员工作台</h1>
<p class="admin-subtitle">维护本校组织架构、教师和学生账号,所有数据限定在当前学校。</p>
</section>
<section class="admin-panel">
<div class="quick-grid">
<div v-for="item in schoolAdminLinks" :key="item.path" class="quick-card" @click="go(item.path)">
<div class="quick-label">{{ item.label }}</div>
<h2>{{ item.title }}</h2>
<p>{{ item.desc }}</p>
<el-button type="primary">进入管理</el-button>
</div>
</div>
</section>
</div>
<teacher v-else-if="role == '3'" />
<student v-else />
</div>
</template>
<script setup>
import "@/views/schoolAdmin/admin-theme.scss";
import student from "./student/index.vue";
import teacher from "./teacherEnd/index.vue";
import useUserStore from "@/store/modules/user";
import { computed } from "vue";
const userStore = useUserStore();
const router = useRouter();
const role = computed(() => userStore.userInfo.roleId);
const go = (path) => {
router.push(path);
};
const schoolAdminLinks = [
{ label: "Faculty", title: "院系管理", desc: "维护院系数据。", path: "/admin-faculty/index" },
{ label: "Major", title: "专业管理", desc: "维护专业数据。", path: "/admin-major/index" },
{ label: "Class", title: "班级管理", desc: "维护班级数据。", path: "/admin-class/index" },
{ label: "Teacher", title: "教师管理", desc: "维护教师账号。", path: "/admin-teacher/index" },
{ label: "Student", title: "学生管理", desc: "维护学生账号。", path: "/admin-student/index" },
];
</script>
<style lang='scss' scoped>
.index {
margin: 10px;
}
// 英雄区增强
.admin-hero {
position: relative;
overflow: hidden;
.hero-decoration {
position: absolute;
top: 0;
right: 0;
width: 400px;
height: 200px;
opacity: 0.6;
pointer-events: none;
}
.hero-icons {
position: absolute;
top: 20px;
right: 20px;
display: flex;
gap: 12px;
}
.hero-icon-item {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.2);
}
.admin-badge {
display: inline-flex;
align-items: center;
gap: 8px;
}
}
// 面板标题组
.panel-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 18px;
}
.panel-title-group {
display: flex;
align-items: center;
gap: 10px;
}
// 快捷卡片增强
.quick-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.quick-card {
position: relative;
display: flex;
flex-direction: column;
padding: 24px;
.card-icon {
width: 56px;
height: 56px;
margin-bottom: 14px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 14px;
background: rgba(0, 170, 255, 0.12);
border: 1px solid rgba(0, 170, 255, 0.25);
color: #00aaff;
&.teacher {
background: rgba(255, 107, 53, 0.12);
border-color: rgba(255, 107, 53, 0.25);
color: #ff6b35;
}
}
h2 {
margin: 8px 0;
font-size: 18px;
}
p {
flex: 1;
margin-bottom: 16px;
}
.el-button {
align-self: flex-start;
display: inline-flex;
align-items: center;
}
}
// 统计面板
.stats-panel {
margin-top: 20px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
@media (max-width: 1000px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 600px) {
.stats-grid {
grid-template-columns: 1fr;
}
}
.stat-card {
display: flex;
align-items: center;
gap: 14px;
padding: 18px;
border-radius: 12px;
background: rgba(0, 35, 55, 0.44);
border: 1px solid rgba(0, 170, 255, 0.18);
transition: all 0.2s;
&:hover {
border-color: rgba(0, 170, 255, 0.4);
background: rgba(0, 35, 55, 0.6);
}
}
.stat-icon {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px;
background: rgba(0, 170, 255, 0.12);
border: 1px solid rgba(0, 170, 255, 0.2);
&.accent {
background: rgba(255, 107, 53, 0.12);
border-color: rgba(255, 107, 53, 0.2);
}
&.success {
background: rgba(0, 255, 157, 0.1);
border-color: rgba(0, 255, 157, 0.2);
}
&.warning {
background: rgba(255, 190, 0, 0.1);
border-color: rgba(255, 190, 0, 0.2);
}
}
.stat-info {
flex: 1;
display: flex;
flex-direction: column;
}
.stat-value {
font-size: 24px;
font-weight: 700;
color: #f7fbff;
line-height: 1.2;
font-family: "JetBrains Mono", "SF Mono", monospace;
}
.stat-label {
font-size: 13px;
color: rgba(221, 236, 255, 0.6);
margin-top: 2px;
}
.stat-trend {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
font-weight: 600;
padding: 4px 8px;
border-radius: 6px;
&.up {
color: #00ff9d;
background: rgba(0, 255, 157, 0.1);
}
&.down {
color: #ff6b35;
background: rgba(255, 107, 53, 0.1);
}
}
// 动态面板
.activity-panel {
margin-top: 20px;
}
.activity-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.activity-item {
display: flex;
align-items: flex-start;
gap: 14px;
padding: 14px;
border-radius: 10px;
background: rgba(0, 35, 55, 0.3);
border: 1px solid rgba(0, 170, 255, 0.1);
transition: all 0.2s;
&:hover {
background: rgba(0, 35, 55, 0.5);
border-color: rgba(0, 170, 255, 0.2);
}
}
.activity-dot {
width: 10px;
height: 10px;
border-radius: 50%;
margin-top: 5px;
flex-shrink: 0;
&.school {
background: #00aaff;
box-shadow: 0 0 8px rgba(0, 170, 255, 0.5);
}
&.teacher {
background: #ff6b35;
box-shadow: 0 0 8px rgba(255, 107, 53, 0.5);
}
&.success {
background: #00ff9d;
box-shadow: 0 0 8px rgba(0, 255, 157, 0.5);
}
}
.activity-content {
flex: 1;
}
.activity-text {
margin: 0 0 4px;
font-size: 14px;
color: #dceeff;
line-height: 1.4;
strong {
color: #00aaff;
font-weight: 600;
}
}
.activity-time {
font-size: 12px;
color: rgba(221, 236, 255, 0.5);
}
</style>