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.
584 lines
18 KiB
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>
|