feat: 为教师端应用极简 SaaS 教育风样式

fix/exam-question-access-material-excel-delete-draft
qinzhenpen 3 weeks ago
parent 569839be27
commit 3809e55d40

@ -0,0 +1,206 @@
---
name: teacher-edu-style
description: 应用教师端极简 SaaS 教育风(纯白画布 + 教育蓝 outline 按钮)到新页面或改造旧页面。Use when 用户要求教师端页面美化、统一按钮/输入框/间距、教育风格,或改 teacherEnd 下任意页面样式。Do not use for 学生端墨黑风或管理端深色风。
---
# 教师端 · 极简 SaaS 教育风
为教师端(roleId === 3)页面套用统一视觉。**只改视觉,不动业务逻辑。**
## 样式落点(先读,避免乱建文件)
| 层级 | 文件 | 责任 |
|------|------|------|
| 全局统一外观 | [teacher-light.scss](file:///d:/TZ/dianshang-qianduan/src/assets/styles/teacher-light.scss) | 按钮、输入框、弹窗、分页、表格配色。跨页通用规则写这里 |
| 页面自身布局 | 页面 `.vue` 的 `<style scoped>` | 布局、间距、卡片结构,引用令牌,不重复定义外观 |
| 旧深色残留 | [AppMain.vue](file:///d:/TZ/dianshang-qianduan/src/layout/components/AppMain.vue) | 非 scoped 块里禁止再写按钮渐变(见"覆盖陷阱") |
教师端 AppMain 根节点带 `teacher-main` 类,Navbar 带 `teacher-navbar`,可作为锚点。
## 设计令牌(页面根类下统一定义,全站引用)
完整可复制的变量块见 [references/snippets.md](file:///d:/TZ/dianshang-qianduan/.trae/skills/teacher-edu-style/references/snippets.md)。速查:
### 颜色
| 令牌 | 值 | 用途 |
|------|------|------|
| `--edu-primary` | `#3b82f6` | 链接、描边、激活文字、图标 |
| `--edu-primary-deep` | `#2563eb` | hover 文字、axisPointer 标签底 |
| `--edu-primary-soft` | `#eff6ff` | 激活浅底、hover 浅底 |
| `--text-strong` | `#1f2937` | 标题、强调正文 |
| `--text-body` | `#6b7280` | 普通正文 |
| `--text-muted` | `#9ca3af` | 辅助、占位符 |
| `--border-color` | `#e5e7eb` | 卡片、输入框、分割线 |
| 语义色 | `#ef4444` 红 / `#2ba471` 绿 / `#f59e0b` 橙 | **只**表示状态(错误/成功/警示),不做装饰 |
画布纯白 `#ffffff`。禁止深色渐变背景、彩色表头、彩色按钮堆叠。
### 字号(6 级,紧凑体系)
| 令牌 | 值 | 用途 |
|------|------|------|
| `--fs-page` | `17px` | 页面标题 |
| `--fs-card` | `14px` | 卡片标题 |
| `--fs-body` | `12px` | 正文、按钮、输入框 |
| `--fs-tag` | `11px` | 标签、辅助、轴标签 |
| `--fs-kpi` | `26px` | KPI 大数字 |
| `--fs-num` | `20px` | 行内强调数字 |
字重:标题 `700`、按钮/强调 `600`、正文 `400`。行高 1.5(标题 1.35、数字 1)。
### 圆角
卡片 `12px`(`--r-card`);控件/按钮/行 `8px`(`--r-control`)。
## 按钮规范(重点)
**统一尺寸:高 36px、横向 padding 16px、8px 圆角、12px/600、transition 0.18s。**
### 主按钮 primary —— outline 风格(唯一主操作)
全页最多一个,承载"查询/提交/保存/发布"。
| 状态 | background | border | color |
|------|-----------|--------|-------|
| 默认 | `transparent` | `1px solid #3b82f6` | `#3b82f6` |
| hover/focus | `rgba(59,130,246,0.1)` | `#3b82f6` | `#2563eb` |
| active 按下 | `rgba(59,130,246,0.18)` | `#2563eb` | `#2563eb` |
| disabled | 透明 | 蓝 | 蓝 + opacity .5 |
无阴影、无位移。plain 朴素态同样式。写法见 snippets。
### 其他按钮
| 类型 | 样式 |
|------|------|
| 默认(取消) | 白底 + `#e5e7eb` 边 + `#1f2937` 字;hover 底 `#f9fafb`、边 `#9ca3af` |
| success / warning / danger | 实色(绿/橙/红)白字,只用于对应语义 |
| 表格行内文字按钮 | 透明底;primary 蓝、danger 红,无填充 |
| is-text / is-link 的 primary | 同样收敛为 outline |
### 按钮内图标
- EP `.el-icon` 默认带间距;**自定义 SVG 必须显式 `gap: 8px`**,否则图标贴文字
- 图标尺寸 `14px`,用 `currentColor` 自动跟随文字颜色(不要写死 fill)
## 输入框规范(input / select / date 完全一致)
| 属性 | 值 |
|------|------|
| 高 | `36px`(与按钮同高) |
| 圆角 | `8px` |
| 背景/边框 | 白底 + `1px solid #e5e7eb` |
| hover 边 | `#d1d5db`;focus 边 `#3b82f6` + `0 0 0 3px rgba(59,130,246,0.12)` 光晕 |
| 文字 | 12px、`#1f2937`;placeholder `#9ca3af` |
**EP 关键坑:select 的边框在 `.el-select__wrapper` 上,不在 `.el-input__wrapper`。两个选择器必须同步覆盖**,否则下拉框和输入框对不齐。禁用态浅灰底 `#f3f4f6`。
## 间距规范(重点)
4px 基准,只允许 5 档:
| 令牌 | 值 | 用途 |
|------|------|------|
| `--sp-1` | `4px` | 图标与紧贴文字 |
| `--sp-2` | `8px` | 同组元素 gap、行内间距 |
| `--sp-3` | `12px` | 分区竖向间距、卡片内分组 |
| `--sp-4` | `16px` | 大区块 gap、卡片 padding |
| `--sp-5` | `20px` | 页面级大分区间距 |
- 卡片 padding `16px`;卡片标题与内容间距 `12px`
- 筛选条字段间距 `12px`,字段统一宽 `200px`(`--field-w`)
- KPI 卡行 gap `16px`;图表双栏 gap `16px`
### 留白责任分层(防 padding 叠加,反复踩过)
1. **app-main 自带 padding,页面根类不许再写页面级 padding/背景**
2. 卡片、分区内部才写内容 padding
3. 禁止在系统层(teacherLayout/main-container/app-main/app-container)为单个页面加 padding 覆盖
4. 不允许双层 app-main + app-container 同时留白
## 背景规范
- 全链路(teacherLayout → main-container → app-main → app-container → 页面)在教育风页面统一纯白
- 卡片:白底 + `1px #e5e7eb` 边 + 极淡阴影 `0 1px 3px rgba(0,0,0,0.06)`,hover 不上色(需要时轻微上浮可选)
- 图表:`backgroundColor: "transparent"`,tooltip 白底深字
- 图表悬停轴标签(axisPointer.label):`#2563eb` 底 + 白字,默认浅蓝底白字看不清,必须显式设置
## 表格风格规范
整体:**纯白底、灰色细线、无彩色填充、无发光**。结构与层次如下。
### 表格容器
| 属性 | 值 |
|------|------|
| `background` | `#ffffff` |
| `border` | `1px solid #e5e7eb` |
| `border-radius` | `12px`(卡片级),`overflow: hidden` |
| 阴影 | 无(表格已在卡片内时)或极淡 `0 1px 3px rgba(0,0,0,0.06)` |
| CSS 变量 | `--el-table-bg-color` / `--el-table-tr-bg-color` 均 `#ffffff` |
### 表头(不靠填充区分)
| 属性 | 值 |
|------|------|
| `--el-table-header-bg-color` | `#ffffff`(禁止 `#e3effb` 等浅蓝)|
| 表头 th 背景 | `#ffffff !important`,禁止 linear-gradient |
| 文字 | `#1f2937`、13px、600、无 text-shadow |
| border-bottom | `1px solid #e5e7eb`(表头与数据行唯一分界)|
| 表头高度 | 38px;`.cell` 文字同步样式 |
| 页面 `tableHeaderStyle` 内联对象 | 同步白底 + `#1f2937` 字 |
### 数据行
| 属性 | 值 |
|------|------|
| 行背景 | `#ffffff`(透明),禁止斑马纹彩色 |
| 文字 | `#1f2937`、12px(`--fs-body`)|
| 行分隔线 | `1px solid #e5e7eb`(`--el-table-border-color`)|
| 行 hover | `#f9fafb`(中性灰,禁止浅蓝 `#eff6ff`)|
| 单元格 padding | 纵向 12px 左右,保持紧凑 |
| 选中/当前行 | 仅在确需时用极淡灰,不引入蓝底 |
### 单元格内元素
- 状态用 `el-tag`:成功绿 / 警示橙 / 信息灰,**标签本身保留语义浅底**(小面积,不影响整表白底)
- 行内操作按钮:文字按钮透明底,primary 蓝、danger 红,按钮间 `gap: 8px`
- 空数据:居中、`#9ca3af`、12px,不额外加色块
### 分页
- 白底;页码按钮灰边,当前页教育蓝底白字(小面积强调)
- "共 N 条 / 每页条数" 文字 `#6b7280`、12px
- 分页与表格间距 `16px`,右对齐
### 落地位置
跨页通用表格外观写 teacher-light.scss;页面 scoped 只做布局与列宽。注意 EP 表格变量(`--el-table-header-bg-color` 等)是注入暗色的常见入口,必须显式覆盖。
## 实施步骤
1. 读目标页面,确认所属层级与现有类名
2. 通用外观缺什么补到 teacher-light.scss(按钮/输入框已覆盖时不要重复写)
3. 页面 scoped 里只写布局与间距,全部引用令牌,硬编码色值归零
4. 图表 tooltip / axisPointer 按本规范设置
5. 浏览器实测:getComputedStyle 同时检查 `backgroundColor` 和 `backgroundImage`(见陷阱)
6. Ctrl+F5 或确认 dev server 端口是最新进程
## 覆盖陷阱(必读,均真实发生过)
1. **background 简写污染 background-image**:旧规则 `.teacher-main .el-button--primary{background:linear-gradient(...)}` 会把渐变写进 `background-image`,只覆盖 `background-color:transparent` 无效。必须同时 `background-image:none !important`,或从源头删渐变。
2. **陈旧 dev server**:多实例时 Vite 顺延端口(147→148),旧端口不热更新全局 scss。改了没反应先核对浏览器端口对应最新进程并重启。
3. **select wrapper 独立**:见输入框坑。
4. **EP `-webkit-text-fill-color`**:select 选中值可能透明,必要时显式设置。
## 完成验证清单
- [ ] 无硬编码色值(除语义状态、3px 装饰条、图表内模板)
- [ ] 按钮:透明蓝边默认态 + 半蓝 hover + 无渐变(background-image: none)
- [ ] 输入框与按钮同高 36px,input/select/date 外观一致
- [ ] 间距只用 5 档令牌,无随意像素值
- [ ] 字号只用 6 级令牌
- [ ] 页面根类无重复 padding/背景
- [ ] GetDiagnostics 无报错
- [ ] 真实鼠标验证 hover / 轴标签可读性

@ -0,0 +1,218 @@
# 教师端教育风 · 代码片段
可直接复制。按需取用,不要整页照搬。
## 1. 页面根类令牌块(放 scoped 顶部)
```scss
.xxx-page {
/* 颜色 */
--edu-primary: #3b82f6;
--edu-primary-deep: #2563eb;
--edu-primary-soft: #eff6ff;
--text-strong: #1f2937;
--text-body: #6b7280;
--text-muted: #9ca3af;
--border-color: #e5e7eb;
/* 字号 */
--fs-page: 17px;
--fs-card: 14px;
--fs-body: 12px;
--fs-tag: 11px;
--fs-kpi: 26px;
--fs-num: 20px;
/* 间距(4px 基准)*/
--sp-1: 4px;
--sp-2: 8px;
--sp-3: 12px;
--sp-4: 16px;
--sp-5: 20px;
/* 圆角 / 控件 */
--r-card: 12px;
--r-control: 8px;
--control-h: 36px;
--field-w: 200px;
--btn-pad-x: 16px;
--btn-icon: 14px;
}
```
## 2. 主按钮 outline(页面 scoped 本地强制版)
当全局未接管或需保证单页一定生效时使用:
```scss
.search-btn {
height: var(--control-h);
padding: 0 var(--btn-pad-x);
background-color: transparent !important;
background-image: none !important; /* 关键:清渐变层 */
border: 1px solid var(--edu-primary) !important;
color: var(--edu-primary) !important;
border-radius: var(--r-control) !important;
box-shadow: none !important;
font-size: var(--fs-body);
font-weight: 600;
gap: var(--sp-2); /* 自定义 SVG 图标间距 */
transition: background-color 0.18s ease, color 0.18s ease;
&:hover,
&:focus {
background-color: rgba(59, 130, 246, 0.1) !important;
color: var(--edu-primary-deep) !important;
}
&:active {
background-color: rgba(59, 130, 246, 0.18) !important;
color: var(--edu-primary-deep) !important;
}
.btn-svg {
width: var(--btn-icon);
height: var(--btn-icon);
/* SVG 内 fill / stroke 用 currentColor */
}
}
```
## 3. 输入框 / 下拉 / 日期 统一覆盖(teacher-light.scss 通用)
```scss
.el-input__wrapper,
.el-select__wrapper {
height: 36px !important;
background-color: #ffffff !important;
border-radius: 8px !important;
box-shadow: 0 0 0 1px #e5e7eb inset !important;
padding: 0 11px !important;
transition: box-shadow 0.18s ease;
&:hover {
box-shadow: 0 0 0 1px #d1d5db inset !important;
}
&.is-focus,
&:focus-within {
box-shadow: 0 0 0 1px #3b82f6 inset,
0 0 0 3px rgba(59, 130, 246, 0.12) !important;
}
}
.el-input__inner,
.el-select__selected-item {
font-size: 12px;
color: #1f2937;
-webkit-text-fill-color: #1f2937;
}
.el-input__inner::placeholder {
color: #9ca3af;
-webkit-text-fill-color: #9ca3af;
}
```
## 4. 卡片
```scss
.card {
background: #ffffff;
border: 1px solid var(--border-color);
border-radius: var(--r-card);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
padding: var(--sp-4);
&-title {
font-size: var(--fs-card);
font-weight: 700;
color: var(--text-strong);
margin: 0 0 var(--sp-3);
}
}
```
## 5. 走势图 tooltip + axisPointer(ECharts option)
```js
tooltip: {
trigger: "axis",
backgroundColor: "rgba(255, 255, 255, 0.98)",
borderColor: "rgba(59, 130, 246, 0.2)",
borderWidth: 1,
padding: [10, 14],
textStyle: { color: "#1f2937", fontSize: 13 },
axisPointer: {
type: "cross",
lineStyle: { color: "rgba(59,130,246,0.3)", type: "dashed" },
},
},
xAxis: {
// ...
axisPointer: {
label: {
backgroundColor: "#2563eb",
color: "#ffffff",
fontSize: 11,
fontWeight: 600,
padding: [4, 8],
borderRadius: 4,
},
},
},
yAxis: {
// ...
axisPointer: {
label: { backgroundColor: "#2563eb", color: "#ffffff", fontSize: 11 },
},
},
```
## 6. 饼图 tooltip(item 触发)
```js
tooltip: {
trigger: "item",
backgroundColor: "rgba(255, 255, 255, 0.98)",
borderColor: "rgba(59, 130, 246, 0.2)",
textStyle: { color: "#1f2937", fontSize: 13 },
formatter: "{b}: {c}人 ({d}%)",
},
```
## 7. 页面骨架参考
```html
<div class="xxx-page">
<!-- 页面标题(app-main 已提供 padding,这里不加)-->
<header class="page-head">
<h1 class="page-title">页面标题</h1>
<p class="page-sub">辅助说明</p>
</header>
<!-- KPI 行 -->
<div class="kpi-row">
<div class="kpi-card"><!-- 图标 + 标签 + 大数字 --></div>
</div>
<!-- 内容区 -->
<div class="content-grid">
<section class="card">...</section>
</div>
</div>
```
## 8. 浏览器快速自检脚本(DevTools / browser_evaluate)
```js
const btn = document.querySelector(".search-btn");
const s = getComputedStyle(btn);
({
backgroundColor: s.backgroundColor, // rgba(0,0,0,0)
backgroundImage: s.backgroundImage, // 必须 none
borderColor: s.borderColor, // rgb(59,130,246)
color: s.color, // rgb(59,130,246)
height: s.height, // 36px
});
```

@ -1206,3 +1206,113 @@
} }
} }
} }
/* ========================================================================
* 教师端(role 3)极简 SaaS 教育风:纯白画布 + 教育蓝
* 覆盖前文 #app .studentLayout, #app .teacherLayout 共享的浅蓝玻璃块
* 选择器带 .teacherLayout 锚点且置于文件末尾,确保胜出
* ====================================================================== */
#app .teacherLayout {
background: #ffffff !important;
.main-container { background: #ffffff !important; }
.app-main,
.teacher-main {
background: #ffffff !important;
&::-webkit-scrollbar-track { background: transparent !important; }
&::-webkit-scrollbar-thumb { background: #d1d5db !important; }
&::-webkit-scrollbar-thumb:hover { background: #9ca3af !important; }
}
// 实训页背景一并收敛为纯白
.app-main:has(.student-training-shell) { background: #ffffff !important; }
.sidebar-container {
background: #ffffff !important;
border-right: 1px solid #e5e7eb !important;
box-shadow: none !important;
&::after { display: none !important; }
// 导航容器:去掉大圆角玻璃卡片,铺满侧栏
.student-course-nav {
width: 100%;
min-height: 100%;
margin: 0;
padding: 16px 10px;
border: 0;
border-radius: 0;
background: #ffffff !important;
box-shadow: none !important;
backdrop-filter: none;
}
// 分组标题:13px 深灰 700,不再大写拉字距
.student-course-heading {
margin: 0 0 8px;
padding: 0 8px;
color: #1f2937 !important;
font-size: 13px;
font-weight: 700;
letter-spacing: 0;
text-transform: none;
&:hover { color: #1f2937 !important; }
}
.student-course-list { margin: 0 0 16px; }
// 菜单项:纯文字行、38px 高、8px 圆角
.student-course-link {
min-height: 38px;
margin: 0 0 4px;
padding: 0 10px;
border: 0 !important;
border-radius: 8px !important;
color: #4b5563 !important;
background: transparent !important;
font-size: 13px;
font-weight: 400;
&:hover {
color: #1f2937 !important;
background: #f3f4f6 !important;
box-shadow: none !important;
transform: none !important;
}
// 激活:教育蓝浅底 + 蓝字 + 左侧 3px 蓝条
&.active {
color: #3b82f6 !important;
background: #eff6ff !important;
box-shadow: inset 3px 0 0 #3b82f6;
}
&.disabled {
color: #c0c5cd !important;
background: transparent !important;
}
}
// 图标:透明底灰图标,hover/激活变色
.student-course-icon {
width: 24px;
height: 24px;
border: 0 !important;
border-radius: 6px;
color: #9ca3af !important;
background: transparent !important;
box-shadow: none !important;
}
.student-course-icon--heading {
color: #3b82f6 !important;
background: #eff6ff !important;
}
.student-course-link:hover .student-course-icon { color: #4b5563 !important; }
.student-course-link.active .student-course-icon { color: #3b82f6 !important; }
}
}

File diff suppressed because it is too large Load Diff

@ -332,15 +332,17 @@ router.beforeEach((to, from, next) => {
color: rgba(189, 221, 244, 0.58); color: rgba(189, 221, 244, 0.58);
} }
// 按钮配色已统一由 src/assets/styles/teacher-light.scss 接管,
// 此处不再声明 background 渐变(旧深色风残留会覆盖 background-image)
.el-button--primary { .el-button--primary {
border-color: rgba(48, 185, 255, 0.85); border-color: transparent;
background: linear-gradient(135deg, #078dce, #1557d6); background: transparent;
box-shadow: 0 8px 18px rgba(0, 110, 220, 0.24); box-shadow: none;
} }
.el-button--warning { .el-button--warning {
border-color: rgba(245, 166, 35, 0.75); border-color: transparent;
background: linear-gradient(135deg, #d99620, #b76418); background: transparent;
} }
.el-button.is-text { .el-button.is-text {

@ -564,114 +564,144 @@ onMounted(() => {
} }
.teacher-navbar { .teacher-navbar {
// 教师端亮色主题:浅色玻璃质感 + 蓝色点缀,保持科技感 // 极简 SaaS 教育风:纯白 + 细底边线,与页面内容区同一画布
background: linear-gradient(135deg, #ffffff 0%, #f3f8ff 50%, #eaf2fb 100%) !important; background: #ffffff !important;
border-bottom: 1px solid rgba(30, 136, 229, 0.18); border-bottom: 1px solid #e5e7eb;
box-shadow: 0 6px 24px rgba(30, 60, 100, 0.08); box-shadow: none;
backdrop-filter: blur(20px); backdrop-filter: none;
// 蓝色光点装饰与极简白底不匹配,移除
.nav-bg-decoration { display: none; }
// 品牌区:去渐变去模糊,logo 描边收敛为教育蓝
.TnavTitle {
background: transparent;
backdrop-filter: none;
// 菜单项:浅色文字 + 轻量描边 .logo-area {
.logo-icon {
filter: none;
path, circle { stroke: #3b82f6; }
path:first-child { fill: rgba(59, 130, 246, 0.1); }
}
span {
color: #1f2937;
font-size: 15px;
font-weight: 700;
letter-spacing: 0;
}
}
}
// 顶部导航:文字式,灰字 → hover 深黑 → 激活教育蓝 + 下划线
.el-ment { .el-ment {
color: #3a5a7a; color: #6b7280;
.el-ment-item { .el-ment-item {
color: #3a5a7a; color: #6b7280;
background: rgba(30, 136, 229, 0.06); background: transparent;
border: 1px solid rgba(30, 136, 229, 0.12); border: 0;
transform: none;
.menu-indicator { .menu-indicator {
background: linear-gradient(90deg, transparent, #1e88e5, transparent); height: 2px;
background: #3b82f6;
} }
&:hover { &:hover {
color: #1e88e5; color: #1f2937;
background: rgba(30, 136, 229, 0.12); background: transparent;
border-color: rgba(30, 136, 229, 0.28); transform: none;
.menu-indicator { .menu-indicator {
background: linear-gradient(90deg, transparent, #1e88e5, transparent); transform: translateX(-50%) scaleX(0.6);
background: #3b82f6;
} }
} }
} }
.el-ment-item-active { .el-ment-item-active {
color: #1e88e5; color: #3b82f6;
background: linear-gradient(135deg, rgba(30, 136, 229, 0.18), rgba(66, 165, 245, 0.08)); background: transparent;
border-color: rgba(30, 136, 229, 0.4); border: 0;
box-shadow: 0 4px 14px rgba(30, 136, 229, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: none;
.menu-indicator { .menu-indicator {
background: linear-gradient(90deg, transparent, #1e88e5, transparent); transform: translateX(-50%) scaleX(1);
background: #3b82f6;
} }
&::before { &::before { display: none; }
background: linear-gradient(90deg, transparent, rgba(30, 136, 229, 0.7), transparent);
}
} }
// teacher-nav 定位规则保留,胶囊样式全部清除
&.teacher-nav { &.teacher-nav {
.el-ment-item { .el-ment-item {
color: #3a5a7a; color: #6b7280;
background: rgba(30, 136, 229, 0.05); background: transparent;
border: 1px solid rgba(30, 136, 229, 0.1); border: 0;
&:hover { &:hover {
color: #1e88e5; color: #1f2937;
background: rgba(30, 136, 229, 0.12); background: transparent;
border-color: rgba(30, 136, 229, 0.28);
} }
} }
.el-ment-item-active { .el-ment-item-active {
color: #1e88e5; color: #3b82f6;
background: linear-gradient(135deg, rgba(30, 136, 229, 0.2), rgba(66, 165, 245, 0.1)); background: transparent;
border-color: rgba(30, 136, 229, 0.45); border: 0;
box-shadow: 0 4px 16px rgba(30, 136, 229, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: none;
.menu-indicator { .menu-indicator { background: #3b82f6; }
background: linear-gradient(90deg, transparent, #1e88e5, transparent);
}
} }
} }
} }
// 右侧区域:浅色背景渐变 // 右侧区域:透明,与整行无缝
.right-menu { .right-menu {
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6)); background: transparent;
} }
// 搜索入口:白底灰边中性框
.search-box { .search-box {
background: rgba(30, 136, 229, 0.08) !important; background: #ffffff !important;
border-color: rgba(30, 136, 229, 0.18) !important; border-color: #e5e7eb !important;
color: rgba(30, 90, 140, 0.7) !important; color: #6b7280 !important;
transform: none;
&:hover { &:hover {
background: rgba(30, 136, 229, 0.14) !important; background: #f9fafb !important;
border-color: rgba(30, 136, 229, 0.32) !important; border-color: #d1d5db !important;
color: #1e88e5 !important; color: #1f2937 !important;
transform: none;
} }
} }
.divider { .divider {
background: linear-gradient(180deg, transparent, rgba(30, 136, 229, 0.35), transparent); background: #e5e7eb;
} }
// 头像区:白底灰边,去掉彩色渐变发光环
.avatar-container .avatar-wrapper { .avatar-container .avatar-wrapper {
background: rgba(30, 136, 229, 0.08) !important; background: #ffffff !important;
border-color: rgba(30, 136, 229, 0.18) !important; border-color: #e5e7eb !important;
&:hover { &:hover {
background: rgba(30, 136, 229, 0.16) !important; background: #f9fafb !important;
border-color: rgba(30, 136, 229, 0.32) !important; border-color: #d1d5db !important;
} }
.avatar-ring { .avatar-ring {
background: linear-gradient(135deg, #1e88e5, #42a5f5) !important; background: #ffffff !important;
box-shadow: 0 0 10px rgba(30, 136, 229, 0.35) !important; border: 1px solid #e5e7eb;
box-shadow: none !important;
} }
.dropdown-icon { .dropdown-icon {
color: rgba(30, 90, 140, 0.7); color: #6b7280;
} }
} }
} }

@ -32,8 +32,8 @@ const needTagsView = computed(() => settingsStore.tagsView);
const fixedHeader = computed(() => settingsStore.fixedHeader); const fixedHeader = computed(() => settingsStore.fixedHeader);
const useTopNavbarOnly = computed(() => role.value === 1 || role.value === 2); const useTopNavbarOnly = computed(() => role.value === 1 || role.value === 2);
// 教师端改用亮色主题:顶部标题栏使用浅色背景,与平台/学校管理员端做区分;学生端墨黑 // 教师端纯白极简:顶部标题栏与内容区同一画布;学生端墨黑
const titleBgColor = computed(() => (role.value === 3 ? "#f5f8fc" : role.value === 4 ? "#1f2937" : "#072048")); const titleBgColor = computed(() => (role.value === 3 ? "#ffffff" : role.value === 4 ? "#1f2937" : "#072048"));
const classObj = computed(() => ({ const classObj = computed(() => ({
hideSidebar: !sidebar.value.opened, hideSidebar: !sidebar.value.opened,

@ -1,18 +1,5 @@
<template> <template>
<div class="class-page"> <div class="class-page">
<!-- 页面头部 -->
<div class="page-header">
<div class="header-icon">
<el-icon>
<Grid />
</el-icon>
</div>
<div class="header-content">
<h1>班级管理</h1>
<p>维护学校班级信息,支持行政班和教学班两种模式</p>
</div>
</div>
<el-tabs v-if="adminClassManagementEnabled" v-model="activeClassType" class="class-tabs" <el-tabs v-if="adminClassManagementEnabled" v-model="activeClassType" class="class-tabs"
@tab-change="handleTabChange"> @tab-change="handleTabChange">
<el-tab-pane label="行政班" name="ADMIN" /> <el-tab-pane label="行政班" name="ADMIN" />
@ -265,7 +252,7 @@
</template> </template>
<script setup> <script setup>
import { Plus, Refresh, Search, Edit, Delete, User, Grid, Upload, Download, Close, Check } from "@element-plus/icons-vue" import { Plus, Refresh, Search, Edit, Delete, User, Upload, Download, Close, Check } from "@element-plus/icons-vue"
import { ElMessageBox } from "element-plus" import { ElMessageBox } from "element-plus"
import { formatDate } from "@/utils/index" import { formatDate } from "@/utils/index"
import useUserStore from "@/store/modules/user" import useUserStore from "@/store/modules/user"
@ -319,9 +306,10 @@ const rules = computed(() => ({
})) }))
const tableHeaderStyle = { const tableHeaderStyle = {
color: "#0f3052", color: "#1f2937",
fontSize: "14px", fontSize: "12px",
backgroundColor: "#eaf4ff", fontWeight: "600",
backgroundColor: "#ffffff",
} }
const dialogTitle = computed(() => `${isCreate.value ? "新增" : "编辑"}${activeClassType.value === "ADMIN" ? "行政班" : "教学班"}`) const dialogTitle = computed(() => `${isCreate.value ? "新增" : "编辑"}${activeClassType.value === "ADMIN" ? "行政班" : "教学班"}`)
@ -898,294 +886,150 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.class-page { .class-page {
min-height: calc(100vh - 70px); /* ===== 颜色令牌 ===== */
--edu-primary: #3b82f6;
// 页面头部卡片 --edu-primary-deep: #2563eb;
.page-header { --edu-primary-soft: #eff6ff;
display: flex; --text-strong: #1f2937;
align-items: center; --text-body: #6b7280;
gap: 20px; --text-muted: #9ca3af;
padding: 24px 28px; --border-color: #e5e7eb;
background: linear-gradient(135deg, rgba(8, 24, 39, 0.9) 0%, rgba(6, 17, 29, 0.9) 100%);
border-radius: 16px; /* ===== 字号 ===== */
margin-bottom: 20px; --fs-page: 17px;
border: 1px solid rgba(0, 200, 255, 0.2); --fs-card: 14px;
box-shadow: --fs-body: 12px;
0 8px 32px rgba(0, 0, 0, 0.4), --fs-tag: 11px;
inset 0 1px 0 rgba(255, 255, 255, 0.05);
/* ===== 间距(4px 基准)===== */
.header-icon { --sp-1: 4px;
width: 60px; --sp-2: 8px;
height: 60px; --sp-3: 12px;
display: flex; --sp-4: 16px;
align-items: center; --sp-5: 20px;
justify-content: center;
background: linear-gradient(135deg, #00d4ff 0%, #0099cc 100%); /* ===== 圆角 / 控件 ===== */
border-radius: 14px; --r-card: 12px;
font-size: 30px; --r-control: 8px;
color: #0a0f1c; --field-w: 200px;
box-shadow: 0 0 30px rgba(0, 212, 255, 0.4);
} // app-main 已提供 padding 与白底,此处不再设页面级留白/背景
.header-content { /* ===== 行政班 / 教学班 标签页(极简文字式)===== */
h1 {
margin: 0 0 6px 0;
font-size: 24px;
font-weight: 700;
color: #fff;
letter-spacing: 2px;
text-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
}
p {
margin: 0;
font-size: 14px;
color: rgba(255, 255, 255, 0.5);
}
}
.header-stats {
margin-left: auto;
display: flex;
gap: 24px;
.stat-item {
text-align: center;
padding: 12px 20px;
background: rgba(0, 212, 255, 0.08);
border-radius: 12px;
border: 1px solid rgba(0, 212, 255, 0.15);
.stat-value {
font-size: 28px;
font-weight: 700;
color: #00d4ff;
line-height: 1;
text-shadow: 0 0 15px rgba(0, 212, 255, 0.5);
}
.stat-label {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
margin-top: 4px;
}
}
}
}
// 标签页样式
.class-tabs { .class-tabs {
margin-bottom: 16px; margin-bottom: var(--sp-3);
background: rgba(6, 17, 29, 0.6);
border-radius: 14px;
padding: 6px 16px;
border: 1px solid rgba(0, 200, 255, 0.15);
:deep(.el-tabs__header) { :deep(.el-tabs__header) {
margin: 0; margin: 0 0 var(--sp-3);
} }
:deep(.el-tabs__nav-wrap::after) { :deep(.el-tabs__nav-wrap::after) {
display: none; background-color: var(--border-color);
height: 1px;
} }
:deep(.el-tabs__item) { :deep(.el-tabs__item) {
font-size: 15px; font-size: var(--fs-body);
font-weight: 500; font-weight: 400;
padding: 10px 24px; color: var(--text-body);
border-radius: 8px; height: 36px;
transition: all 0.3s ease;
color: rgba(255, 255, 255, 0.5);
background: transparent;
border: 1px solid transparent;
&:hover { &:hover {
color: #00d4ff; color: var(--text-strong);
background: rgba(0, 212, 255, 0.1);
} }
&.is-active { &.is-active {
color: #0a0f1c; color: var(--edu-primary);
background: linear-gradient(135deg, #00d4ff 0%, #0099cc 100%);
font-weight: 600; font-weight: 600;
border-color: #00d4ff;
box-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
} }
} }
:deep(.el-tabs__active-bar) { :deep(.el-tabs__active-bar) {
display: none; background-color: var(--edu-primary);
height: 2px;
} }
} }
// 搜索栏 /* ===== 筛选 / 操作条(白卡)===== */
.query-bar { .query-bar {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
gap: 12px; gap: var(--sp-3);
padding: 20px 24px; padding: var(--sp-4);
background: rgba(6, 17, 29, 0.6); background: #ffffff;
border-radius: 14px; border: 1px solid var(--border-color);
margin-bottom: 16px; border-radius: var(--r-card);
border: 1px solid rgba(0, 200, 255, 0.15); margin-bottom: var(--sp-4);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
.el-select { .el-select {
width: 150px; width: var(--field-w);
} }
.el-input { .el-input {
width: 170px; width: var(--field-w);
} }
.query-divider { .query-divider {
width: 1px; width: 1px;
height: 32px; height: 24px;
background: rgba(0, 200, 255, 0.2); background: var(--border-color);
margin: 0 4px; margin: 0 var(--sp-1);
} }
.btn-group { .btn-group {
margin-left: auto; margin-left: auto;
display: flex; display: flex;
gap: 10px; gap: var(--sp-2);
} }
} }
// 表格样式 /* ===== 数据表格(纯白 + 灰线)===== */
.el-table { .el-table {
border-radius: 14px; background: #ffffff;
border: 1px solid var(--border-color);
border-radius: var(--r-card);
overflow: hidden; overflow: hidden;
background: transparent;
border: 1px solid rgba(0, 200, 255, 0.15);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
:deep(.el-table__header-wrapper th) { :deep(.el-table__header-wrapper th) {
background: transparent; background: #ffffff;
color: #fff; color: var(--text-strong);
font-weight: 600; font-weight: 600;
border: none !important; font-size: var(--fs-body);
padding: 14px 0;
font-size: 14px;
text-shadow: 0 0 10px rgba(0, 212, 255, 0.3);
} }
:deep(.el-table__body-wrapper tr) { :deep(.el-table__body tr:hover > td) {
background: transparent; background: #f9fafb !important;
transition: all 0.3s ease;
&:hover>td {
background: rgba(0, 212, 255, 0.08) !important;
}
}
:deep(.el-table__row td) {
padding: 14px 0;
border-bottom: 1px solid rgba(0, 200, 255, 0.1) !important;
background: transparent !important;
} }
:deep(.el-table__cell) { :deep(.el-table__cell) {
font-size: 14px; font-size: var(--fs-body);
color: rgba(255, 255, 255, 0.85); color: var(--text-strong);
background: transparent !important; border-color: var(--border-color);
border: none !important;
}
:deep(.el-table__border-left),
:deep(.el-table__border-right) {
display: none;
}
}
// 操作按钮
.el-button {
display: inline-flex;
align-items: center;
gap: 5px;
border-radius: 8px;
font-weight: 500;
transition: all 0.3s ease;
padding: 8px 14px;
border: 1px solid rgba(0, 200, 255, 0.3);
background: rgba(0, 150, 200, 0.15);
color: #00d4ff;
&:hover {
transform: translateY(-1px);
box-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
background: rgba(0, 212, 255, 0.2);
}
.el-icon {
font-size: 15px;
} }
} }
// 成员工具栏 /* ===== 成员工具条(白卡)===== */
.member-toolbar { .member-toolbar {
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: wrap;
align-items: center; align-items: center;
gap: 10px; gap: var(--sp-3);
margin-bottom: 16px; margin-bottom: var(--sp-4);
padding: 16px 20px; padding: var(--sp-4);
background: rgba(6, 17, 29, 0.5); background: #ffffff;
border-radius: 12px; border: 1px solid var(--border-color);
border: 1px solid rgba(0, 200, 255, 0.15); border-radius: var(--r-card);
.el-input { .el-input {
width: 150px; width: var(--field-w);
}
}
// 弹窗样式
.el-dialog {
border-radius: 18px;
overflow: hidden;
background: linear-gradient(135deg, #07111d 0%, #03070e 100%);
border: 1px solid rgba(0, 200, 255, 0.2);
box-shadow:
0 20px 60px rgba(0, 0, 0, 0.6),
0 0 40px rgba(0, 212, 255, 0.1);
:deep(.el-dialog__header) {
background: linear-gradient(135deg, #0099cc 0%, #006699 100%);
color: #fff;
padding: 22px 28px;
margin: 0;
.el-dialog__title {
color: #fff;
font-weight: 700;
font-size: 18px;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.el-dialog__headerbtn {
.el-dialog__close {
color: rgba(255, 255, 255, 0.8);
font-size: 20px;
}
}
}
:deep(.el-dialog__body) {
padding: 28px;
background: transparent;
}
:deep(.el-dialog__footer) {
padding: 18px 28px;
border-top: 1px solid rgba(0, 200, 255, 0.15);
background: rgba(10, 15, 30, 0.5);
} }
} }
/* ===== 弹窗内辅助布局(外观由 teacher-light.scss 全局接管)===== */
.dialog-footers { .dialog-footers {
display: flex; display: flex;
gap: 12px; gap: var(--sp-3);
justify-content: flex-end; justify-content: flex-end;
} }
@ -1195,7 +1039,7 @@ onMounted(() => {
.import-create-actions { .import-create-actions {
display: flex; display: flex;
gap: 10px; gap: var(--sp-2);
align-items: center; align-items: center;
} }
} }

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save