Compare commits

...

6 Commits

@ -249,6 +249,7 @@
}
}
/* 超管端主区域:与教师端一致改浅色(body.teacher-light-mode 时),保留暗色作为无亮色主题时的兜底 */
.platform-admin-main {
height: calc(100vh - 50px);
overflow: auto !important;
@ -270,6 +271,22 @@
}
}
/* @at-root 跳出 #app 并提升特异性(压过 #app .platform-admin-main 的 ID 权重深色规则) */
@at-root body.teacher-light-mode #app .platform-admin-main {
background:
radial-gradient(circle at 12% 18%, rgba(30, 136, 229, 0.05), transparent 34%),
radial-gradient(circle at 78% 6%, rgba(66, 165, 245, 0.04), transparent 28%),
linear-gradient(135deg, #f7fafd 0%, #eef4fb 48%, #f5f8fc 100%) !important;
&::-webkit-scrollbar-track {
background: rgba(30, 60, 100, 0.06);
}
&::-webkit-scrollbar-thumb {
background: rgba(59, 130, 246, 0.35);
}
}
.studentLayout,
.teacherLayout {
background: radial-gradient(circle at 10% 20%, rgba(11, 42, 74, 0.74), transparent 34%), radial-gradient(circle at 88% 8%, rgba(0, 136, 210, 0.24), transparent 28%), linear-gradient(135deg, #02050c 0%, #07101d 52%, #02060d 100%);

@ -2956,3 +2956,28 @@ body.student-light-mode {
font-weight: 600;
}
}
/* =============================================================
* 超管工作台(views/index.vue 引入 admin-theme.scss 的暗色按钮)
* 在浅色模式下改为主题蓝实心白字;#app 前缀压过教师端 outline 规则
* ============================================================= */
body.teacher-light-mode #app .school-admin-workbench .el-button--primary,
body.teacher-light-mode #app .school-admin-workbench .el-button--success {
background: #2563eb !important;
border-color: #2563eb !important;
color: #ffffff !important;
box-shadow: 0 1px 2px rgba(37, 99, 235, 0.35) !important;
&:hover,
&:focus {
background: #1d4ed8 !important;
border-color: #1d4ed8 !important;
color: #ffffff !important;
}
&.is-disabled {
background: #93c5fd !important;
border-color: #93c5fd !important;
color: #ffffff !important;
}
}

@ -33,14 +33,14 @@ const fixedHeader = computed(() => settingsStore.fixedHeader);
const useTopNavbarOnly = computed(() => role.value === 1 || role.value === 2);
// 教师端纯白极简:顶部标题栏与内容区同一画布;学生端墨黑
const titleBgColor = computed(() => (role.value === 3 ? "#ffffff" : role.value === 4 ? "#1f2937" : "#072048"));
const titleBgColor = computed(() => (role.value === 3 || role.value === 1 ? "#ffffff" : role.value === 4 ? "#1f2937" : "#072048"));
const classObj = computed(() => ({
hideSidebar: !sidebar.value.opened,
openSidebar: sidebar.value.opened,
withoutAnimation: sidebar.value.withoutAnimation,
mobile: device.value === "mobile",
teacherLayout: role.value === 3,
teacherLayout: role.value === 3 || role.value === 1,
studentLayout: role.value !== 1 && role.value !== 2 && role.value !== 3,
}));
@ -68,11 +68,12 @@ function setLayout() {
settingRef.value.openSetting();
}
// 教师端亮色模式标识:挂在 body 上,使 teleport 到 body 的弹层(下拉、日期选择器、弹窗等)也能命中亮色样式
// 亮色模式标识:挂在 body 上,使 teleport 到 body 的弹层(下拉、日期选择器、弹窗等)也能命中亮色样式
// 平台管理员(超管端)与教师共用同一套浅色主题
const TEACHER_LIGHT_CLASS = "teacher-light-mode";
const STUDENT_LIGHT_CLASS = "student-light-mode";
watchEffect(() => {
if (role.value === 3) {
if (role.value === 3 || role.value === 1) {
document.body.classList.add(TEACHER_LIGHT_CLASS);
document.body.classList.remove(STUDENT_LIGHT_CLASS);
} else if (role.value === 4) {

@ -1,5 +1,6 @@
<template>
<div class="five">
<TrainingTaskToolbar />
<el-scrollbar :height="`${height - 100}px`">
<TrainingIntro title="五维四率模型">
<template #background>
@ -177,6 +178,7 @@ import TrainingIntro from '@/views/components/TrainingIntro.vue';
import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
import * as analysisAPI from "@/api/market-demand-mining.js";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const { proxy } = getCurrentInstance();
const height = ref(800);
const liveRoomDataWithConversion = [

@ -1,5 +1,6 @@
<template>
<div class="kano">
<TrainingTaskToolbar />
<el-scrollbar :height="`${height - 100}px`">
<TrainingIntro title="KANO模型">
<template #background>
@ -320,6 +321,7 @@ import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
import * as analysisAPI from "@/api/market-demand-mining.js";
import { ref } from "vue";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const { proxy } = getCurrentInstance();
const height = ref(800);
const form = ref({

@ -8,6 +8,7 @@
-->
<template>
<div class="market">
<TrainingTaskToolbar />
<el-scrollbar :height="`${height - 100}px`">
<TrainingIntro title="市场机会矩阵">
<template #background>
@ -215,6 +216,7 @@ import TrainingIntro from '@/views/components/TrainingIntro.vue';
import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
import * as analysisAPI from "@/api/market-demand-mining.js";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const { proxy } = getCurrentInstance();
const height = ref(800);
const salesData = [

@ -8,6 +8,7 @@
-->
<template>
<div class="traffic">
<TrainingTaskToolbar />
<el-scrollbar :height="`${height - 100}px`">
<TrainingIntro title="流量问题诊断">
<template #background>
@ -107,6 +108,7 @@ import TrainingIntro from '@/views/components/TrainingIntro.vue';
import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
import * as analysisAPI from "@/api/market-demand-mining.js";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const { proxy } = getCurrentInstance();
const height = ref(800);
const from = ref({

@ -8,6 +8,7 @@
-->
<template>
<div class="purchase-page student-training-shell">
<TrainingTaskToolbar />
<main class="purchase-core">
<section class="task-header">
<div class="task-head-main">
@ -142,6 +143,7 @@ import TrainingAiSidebar from "@/views/components/TrainingAiSidebar.vue";
import * as analysisAPI from "@/api/market-demand-mining.js";
import * as echarts from "echarts";
import useUserStore from "@/store/modules/user";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const briefOpen = ref(false);

@ -10,6 +10,9 @@
:ai-manual-name="resolvedAiManual.name"
:ai-manual-url="resolvedAiManual.url"
/>
<el-button class="task-toolbar-button task-toolbar-button--save" :loading="savingProgress" @click="triggerExistingAction('save')">
<el-icon><CircleCheck /></el-icon>保存当前进度
</el-button>
<el-button class="task-toolbar-button task-toolbar-button--submit" @click="triggerExistingAction('submit')">
<el-icon><CircleCheck /></el-icon>提交任务
</el-button>
@ -60,6 +63,7 @@ const loadedMaterial = ref({
});
const loadedTask = ref(null);
const exporting = ref(false);
const savingProgress = ref(false);
const resolvedTaskKey = computed(() => resolveTrainingTaskKey(route, props.taskKey));
const resolvedMaterial = computed(() => ({
name: String(props.materialName || loadedMaterial.value.name || ""),
@ -139,6 +143,11 @@ function triggerExistingAction(action) {
reset: props.onReset,
};
if (action === "save") {
saveProgress();
return;
}
if (directActions[action]) {
directActions[action]();
return;
@ -201,6 +210,50 @@ function collectLegacyFields() {
}));
}
async function saveProgress() {
if (savingProgress.value) return;
// 优先触发页面自身的保存逻辑(保留各页面的校验与状态文案)
const saveLabelPriority = [[/保存当前进度/], [/保存进度/], [/保存(?!成功|失败|中)/]];
const buttons = getCurrentTaskActionButtons();
const target = saveLabelPriority
.map((matchers) => buttons.find((button) => matchers.some((matcher) => matcher.test(button.innerText || ""))))
.find(Boolean);
if (target) {
savingProgress.value = true;
try {
target.click();
await new Promise((resolve) => setTimeout(resolve, 600));
ElMessage.success("进度已保存");
} finally {
savingProgress.value = false;
}
return;
}
// 页面没有保存按钮时保存表单快照(SAVE 不等于提交)
if (!resolvedTaskKey.value) {
ElMessage.warning("当前任务暂未配置,无法保存。");
return;
}
savingProgress.value = true;
try {
await saveStudentTrainingAnswer(resolvedTaskKey.value, {
saveAction: "SAVE",
currentStep: 1,
step1Answer: JSON.stringify({
type: "legacy-training-snapshot-v3",
route: route.path,
savedAt: new Date().toISOString(),
fields: collectLegacyFields(),
}),
});
ElMessage.success("进度已保存");
} catch {
ElMessage.error("保存失败,请稍后重试。");
} finally {
savingProgress.value = false;
}
}
async function saveLegacyTraining() {
if (!resolvedTaskKey.value) {
ElMessage.warning("当前任务暂未配置,无法提交。");
@ -263,6 +316,8 @@ function exportLegacyTraining() {
.training-task-toolbar { display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end; gap:8px; }
.task-toolbar-button { min-height:34px; height:34px; padding:0 14px; border-color:rgba(37,99,235,.35); border-radius:8px; color:#2563eb; background:#fff; font-size:13px; font-weight:600; }
.task-toolbar-button:hover { border-color:#2563eb; color:#1d4ed8; background:#eff6ff; }
.task-toolbar-button--save { border-color:rgba(43,164,113,.45); color:#2ba471; }
.task-toolbar-button--save:hover { border-color:#2ba471; color:#1f8f62; background:#f0fbf6; }
.task-toolbar-button--submit { border-color:#2563eb; color:#fff; background:#2563eb; }
.task-toolbar-button--submit:hover { border-color:#1d4ed8; color:#fff; background:#1d4ed8; }
@media (max-width:768px) { .training-task-toolbar { justify-content:stretch; } .training-task-toolbar > * { flex:1 1 auto; } }

@ -25,6 +25,10 @@
<TrainingTaskToolbar :task-key="TASK_KEY" :on-submit="saveStepThree" :on-export="exportOutcome" />
</section>
<section class="task-action-strip">
<TrainingTaskToolbar :task-key="TASK_KEY" :on-submit="saveStepThree" :on-export="exportOutcome" />
</section>
<section class="workbench">
<nav class="step-indicator" aria-label="商业可行性论证步骤">
@ -372,8 +376,7 @@ import { checkBusinessFeasibilityStepOne, checkBusinessFeasibilityStepTwo, check
import { getTrainingTaskByKey } from "@/api/trainingTask"
import { parseTrainingArray } from "@/views/training/taskKeyMap"
import TrainingAiSidebar from "@/views/components/TrainingAiSidebar.vue"
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue"
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const TASK_KEY = "business-feasibility"
const DEFAULT_STEPS = ["商业可行性论证", "项目初步决策", "可行性论证报告", "决策结论"]
const overviewFields = [

@ -1,5 +1,6 @@
<template>
<div class="competitive-page student-training-shell">
<TrainingTaskToolbar />
<main class="training-core">
<section class="task-header">
<h1 class="task-title">{{ taskTitle }}</h1>
@ -149,6 +150,7 @@ import { getTrainingTaskByKey } from "@/api/trainingTask";
import { parseTrainingArray } from "@/views/training/taskKeyMap";
import { getStudentTrainingAnswer, saveStudentTrainingAnswer } from "@/api/studentTrainingAnswer";
import { ArrowLeft, ArrowRight, CircleCheck, Download } from "@element-plus/icons-vue";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const TASK_KEY = "competitive-environment-analysis";
const { proxy } = getCurrentInstance();

@ -1,5 +1,6 @@
<template>
<div class="industry-demand-page student-training-shell">
<TrainingTaskToolbar />
<main class="training-core">
<section class="task-header">
<h1 class="task-title">{{ taskTitle }}</h1>
@ -137,6 +138,7 @@ import { getTrainingTaskByKey } from "@/api/trainingTask";
import { parseTrainingArray } from "@/views/training/taskKeyMap";
import { getStudentTrainingAnswer, saveStudentTrainingAnswer } from "@/api/studentTrainingAnswer";
import { ArrowLeft, ArrowRight, CircleCheck, Download } from "@element-plus/icons-vue";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const TASK_KEY = "industry-demand-analysis";
const { proxy } = getCurrentInstance();

@ -8,6 +8,7 @@
-->
<template>
<div class="rgzn_top app-container2 student-training-shell legacy-training-page" v-loading="loading" element-loading-text="Loading..." :element-loading-spinner="svg" element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(122, 122, 122, 0.8)">
<TrainingTaskToolbar />
<div class="top_item">
<div>
<template v-for="(item, index) in tabsList" :key="item.id">
@ -59,6 +60,7 @@ import { getAssetsFile, isModuleUnique } from "@/utils/index.js";
import useAlgorithmStore from "@/store/modules/algorithm.js";
import { getUserInfo } from "@/utils/auth";
import { onMounted } from "vue";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const { proxy } = getCurrentInstance();
const algorithmStore = useAlgorithmStore();
const userInfo = JSON.parse(getUserInfo());

@ -7,18 +7,18 @@
<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" />
<stop offset="0%" style="stop-color:#2563eb;stop-opacity:0.15" />
<stop offset="100%" style="stop-color:#2563eb;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="0%" style="stop-color:#2563eb;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" />
<circle cx="380" cy="60" r="50" fill="none" stroke="#2563eb" stroke-width="0.5" opacity="0.3" />
<circle cx="380" cy="60" r="70" fill="none" stroke="#2563eb" 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" />
@ -28,7 +28,7 @@
<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" />
<path d="M50 150 L100 120 L150 160 L300 140" fill="none" stroke="#2563eb" stroke-width="0.5" opacity="0.3" stroke-dasharray="4,4" />
</svg>
<div class="admin-badge">
@ -43,7 +43,7 @@
<!-- 顶部装饰图标 -->
<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">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" 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"/>
@ -51,12 +51,12 @@
</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">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" 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">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" 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>
@ -68,7 +68,7 @@
<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">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#2563eb" 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"/>
@ -127,7 +127,7 @@
<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">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2">
<path d="M18 20V10"/>
<path d="M12 20V4"/>
<path d="M6 20v-6"/>
@ -138,7 +138,7 @@
<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">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="1.5">
<path d="M3 21h18"/>
<path d="M5 21V7l8-4v18"/>
</svg>
@ -174,7 +174,7 @@
</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">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2ba471" 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>
@ -215,7 +215,7 @@
<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">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<path d="M12 6v6l4 2"/>
</svg>
@ -331,8 +331,8 @@ const schoolAdminLinks = [
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);
background: #e5e7eb;
border: 1px solid #e5e7eb;
}
.admin-badge {
@ -377,14 +377,14 @@ const schoolAdminLinks = [
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;
background: #eff6ff;
border: 1px solid #dbeafe;
color: #2563eb;
&.teacher {
background: rgba(255, 107, 53, 0.12);
border-color: rgba(255, 107, 53, 0.25);
color: #ff6b35;
background: rgba(234, 88, 12, 0.08);
border-color: rgba(234, 88, 12, 0.25);
color: #ea580c;
}
}
@ -434,13 +434,13 @@ const schoolAdminLinks = [
gap: 14px;
padding: 18px;
border-radius: 12px;
background: rgba(0, 35, 55, 0.44);
border: 1px solid rgba(0, 170, 255, 0.18);
background: #ffffff;
border: 1px solid #e5e7eb;
transition: all 0.2s;
&:hover {
border-color: rgba(0, 170, 255, 0.4);
background: rgba(0, 35, 55, 0.6);
border-color: #3b82f6;
background: #f9fafb;
}
}
@ -451,22 +451,22 @@ const schoolAdminLinks = [
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);
background: #eff6ff;
border: 1px solid #e5e7eb;
&.accent {
background: rgba(255, 107, 53, 0.12);
border-color: rgba(255, 107, 53, 0.2);
background: rgba(234, 88, 12, 0.08);
border-color: rgba(234, 88, 12, 0.25);
}
&.success {
background: rgba(0, 255, 157, 0.1);
border-color: rgba(0, 255, 157, 0.2);
background: rgba(43, 164, 113, 0.1);
border-color: rgba(43, 164, 113, 0.3);
}
&.warning {
background: rgba(255, 190, 0, 0.1);
border-color: rgba(255, 190, 0, 0.2);
background: rgba(232, 163, 61, 0.12);
border-color: rgba(232, 163, 61, 0.3);
}
}
@ -479,14 +479,14 @@ const schoolAdminLinks = [
.stat-value {
font-size: 24px;
font-weight: 700;
color: #f7fbff;
color: #1f2937;
line-height: 1.2;
font-family: "JetBrains Mono", "SF Mono", monospace;
}
.stat-label {
font-size: 13px;
color: rgba(221, 236, 255, 0.6);
color: #6b7280;
margin-top: 2px;
}
@ -500,13 +500,13 @@ const schoolAdminLinks = [
border-radius: 6px;
&.up {
color: #00ff9d;
background: rgba(0, 255, 157, 0.1);
color: #2ba471;
background: rgba(43, 164, 113, 0.1);
}
&.down {
color: #ff6b35;
background: rgba(255, 107, 53, 0.1);
color: #ea580c;
background: rgba(234, 88, 12, 0.08);
}
}
@ -527,13 +527,13 @@ const schoolAdminLinks = [
gap: 14px;
padding: 14px;
border-radius: 10px;
background: rgba(0, 35, 55, 0.3);
border: 1px solid rgba(0, 170, 255, 0.1);
background: #ffffff;
border: 1px solid #e5e7eb;
transition: all 0.2s;
&:hover {
background: rgba(0, 35, 55, 0.5);
border-color: rgba(0, 170, 255, 0.2);
background: #f9fafb;
border-color: #e5e7eb;
}
}
@ -545,18 +545,18 @@ const schoolAdminLinks = [
flex-shrink: 0;
&.school {
background: #00aaff;
box-shadow: 0 0 8px rgba(0, 170, 255, 0.5);
background: #2563eb;
box-shadow: 0 0 8px rgba(37, 99, 235, 0.35);
}
&.teacher {
background: #ff6b35;
box-shadow: 0 0 8px rgba(255, 107, 53, 0.5);
background: #ea580c;
box-shadow: none;
}
&.success {
background: #00ff9d;
box-shadow: 0 0 8px rgba(0, 255, 157, 0.5);
background: #2ba471;
box-shadow: none;
}
}
@ -567,17 +567,17 @@ const schoolAdminLinks = [
.activity-text {
margin: 0 0 4px;
font-size: 14px;
color: #dceeff;
color: #374151;
line-height: 1.4;
strong {
color: #00aaff;
color: #2563eb;
font-weight: 600;
}
}
.activity-time {
font-size: 12px;
color: rgba(221, 236, 255, 0.5);
color: #9ca3af;
}
</style>

@ -1,5 +1,6 @@
<template>
<div class="market-selection-page student-training-shell">
<TrainingTaskToolbar />
<main class="training-core">
<section class="task-header">
<div class="task-head-main">
@ -228,6 +229,7 @@ import TrainingMaterialButton from "@/views/components/TrainingMaterialButton.vu
import { getTrainingTaskByKey } from "@/api/trainingTask";
import { parseTrainingArray } from "@/views/training/taskKeyMap";
import { getStudentTrainingAnswer, saveStudentTrainingAnswer } from "@/api/studentTrainingAnswer";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const TASK_KEY = "market-opportunity-selection";
const { proxy } = getCurrentInstance();

@ -6,23 +6,23 @@
<svg class="decoration-lines" viewBox="0 0 400 60" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="headerGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#00aaff;stop-opacity:0" />
<stop offset="50%" style="stop-color:#00aaff;stop-opacity:0.3" />
<stop offset="100%" style="stop-color:#00ff9d;stop-opacity:0" />
<stop offset="0%" style="stop-color:#2563eb;stop-opacity:0" />
<stop offset="50%" style="stop-color:#2563eb;stop-opacity:0.3" />
<stop offset="100%" style="stop-color:#2ba471;stop-opacity:0" />
</linearGradient>
</defs>
<line x1="0" y1="58" x2="400" y2="58" stroke="url(#headerGrad)" stroke-width="1"/>
<circle cx="50" cy="30" r="3" fill="#00aaff" opacity="0.2"/>
<circle cx="150" cy="20" r="2" fill="#00ff9d" opacity="0.2"/>
<circle cx="250" cy="40" r="2.5" fill="#00aaff" opacity="0.15"/>
<circle cx="350" cy="25" r="2" fill="#00ff9d" opacity="0.2"/>
<circle cx="50" cy="30" r="3" fill="#2563eb" opacity="0.2"/>
<circle cx="150" cy="20" r="2" fill="#2ba471" opacity="0.2"/>
<circle cx="250" cy="40" r="2.5" fill="#2563eb" opacity="0.15"/>
<circle cx="350" cy="25" r="2" fill="#2ba471" opacity="0.2"/>
</svg>
</div>
<div class="header-content">
<div class="header-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none">
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" stroke="#00aaff" stroke-width="1.5" stroke-linecap="round"/>
<path d="M9 12h6M9 16h6" stroke="#00aaff" stroke-width="1.5" stroke-linecap="round"/>
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" stroke="#2563eb" stroke-width="1.5" stroke-linecap="round"/>
<path d="M9 12h6M9 16h6" stroke="#2563eb" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</div>
<div class="header-text">
@ -139,16 +139,16 @@
>
<div class="card-decoration">
<svg class="corner-decoration top-left" width="24" height="24" viewBox="0 0 24 24">
<path d="M2 8V2h6" stroke="#00aaff" stroke-width="2" fill="none" opacity="0.6"/>
<path d="M2 8V2h6" stroke="#2563eb" stroke-width="2" fill="none" opacity="0.6"/>
</svg>
<svg class="corner-decoration top-right" width="24" height="24" viewBox="0 0 24 24">
<path d="M22 8V2h-6" stroke="#00aaff" stroke-width="2" fill="none" opacity="0.6"/>
<path d="M22 8V2h-6" stroke="#2563eb" stroke-width="2" fill="none" opacity="0.6"/>
</svg>
<svg class="corner-decoration bottom-left" width="24" height="24" viewBox="0 0 24 24">
<path d="M2 16v6h6" stroke="#00ff9d" stroke-width="2" fill="none" opacity="0.4"/>
<path d="M2 16v6h6" stroke="#2ba471" stroke-width="2" fill="none" opacity="0.4"/>
</svg>
<svg class="corner-decoration bottom-right" width="24" height="24" viewBox="0 0 24 24">
<path d="M22 16v6h-6" stroke="#00ff9d" stroke-width="2" fill="none" opacity="0.4"/>
<path d="M22 16v6h-6" stroke="#2ba471" stroke-width="2" fill="none" opacity="0.4"/>
</svg>
</div>
@ -203,7 +203,7 @@
<el-empty v-if="!filteredTasks.length && !loading" class="task-empty" description="暂无匹配的实训任务">
<template #image>
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="#00aaff" stroke-width="1" opacity="0.3">
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="1" opacity="0.3">
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2"/>
<rect x="9" y="3" width="6" height="4" rx="1"/>
</svg>
@ -403,7 +403,7 @@
<div v-for="(step, index) in taskForm.steps" :key="step.id" class="step-item">
<div class="step-connector" v-if="index > 0">
<svg width="20" height="12" viewBox="0 0 20 12">
<path d="M0 6h16M12 1l4 5-4 5" stroke="#00aaff" stroke-width="1.5" fill="none" opacity="0.5"/>
<path d="M0 6h16M12 1l4 5-4 5" stroke="#2563eb" stroke-width="1.5" fill="none" opacity="0.5"/>
</svg>
</div>
<div class="step-content">
@ -824,9 +824,9 @@ function buildPayload() {
position: relative;
margin-bottom: 24px;
padding: 28px 32px 24px;
border: 1px solid rgba(0, 170, 255, 0.2);
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 16px;
background: linear-gradient(135deg, rgba(0, 20, 40, 0.9), rgba(0, 40, 60, 0.8));
background: #ffffff;
overflow: hidden;
.header-decoration {
@ -858,9 +858,9 @@ function buildPayload() {
width: 64px;
height: 64px;
border-radius: 16px;
background: linear-gradient(135deg, rgba(0, 170, 255, 0.2), rgba(0, 255, 157, 0.1));
border: 1px solid rgba(0, 170, 255, 0.3);
box-shadow: 0 0 30px rgba(0, 170, 255, 0.2);
background: linear-gradient(135deg, rgba(37, 99, 235, 0.2), rgba(43, 164, 113, 0.1));
border: 1px solid rgba(37, 99, 235, 0.3);
box-shadow: 0 0 30px rgba(37, 99, 235, 0.2);
}
.header-text {
@ -871,12 +871,12 @@ function buildPayload() {
font-size: 24px;
font-weight: 700;
color: #ffffff;
text-shadow: 0 2px 10px rgba(0, 170, 255, 0.3);
text-shadow: 0 2px 10px rgba(37, 99, 235, 0.3);
}
.page-subtitle {
margin: 0;
color: rgba(200, 230, 255, 0.7);
color: #4b5563;
font-size: 14px;
line-height: 1.6;
}
@ -892,19 +892,19 @@ function buildPayload() {
align-items: center;
padding: 12px 20px;
border-radius: 12px;
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.2);
background: rgba(37, 99, 235, 0.1);
border: 1px solid rgba(37, 99, 235, 0.2);
.stat-value {
font-size: 28px;
font-weight: 700;
color: #00ff9d;
text-shadow: 0 0 20px rgba(0, 255, 157, 0.5);
color: #2ba471;
text-shadow: 0 0 20px rgba(43, 164, 113, 0.4);
}
.stat-label {
font-size: 12px;
color: rgba(200, 230, 255, 0.6);
color: #6b7280;
margin-top: 4px;
}
}
@ -915,9 +915,9 @@ function buildPayload() {
.task-filter {
padding: 20px 24px;
margin-bottom: 24px;
border: 1px solid rgba(0, 170, 255, 0.2);
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 12px;
background: linear-gradient(135deg, rgba(0, 20, 40, 0.8), rgba(0, 30, 50, 0.7));
background: #ffffff;
}
.filter-top {
@ -943,18 +943,18 @@ function buildPayload() {
height: 40px;
padding: 0 16px;
border-radius: 10px;
background: rgba(0, 10, 20, 0.6);
border: 1px solid rgba(0, 170, 255, 0.3);
background: #f9fafb;
border: 1px solid rgba(37, 99, 235, 0.3);
transition: all 0.3s ease;
&:focus-within {
border-color: rgba(0, 170, 255, 0.6);
box-shadow: 0 0 20px rgba(0, 170, 255, 0.15);
border-color: rgba(37, 99, 235, 0.6);
box-shadow: 0 0 20px rgba(37, 99, 235, 0.15);
}
.search-icon {
flex-shrink: 0;
color: rgba(0, 170, 255, 0.6);
color: rgba(37, 99, 235, 0.6);
}
.search-input {
@ -968,7 +968,7 @@ function buildPayload() {
outline: none;
&::placeholder {
color: rgba(200, 230, 255, 0.4);
color: #9ca3af;
}
}
@ -979,9 +979,9 @@ function buildPayload() {
display: flex;
align-items: center;
justify-content: center;
color: rgba(200, 230, 255, 0.5);
color: #6b7280;
font-size: 16px;
background: rgba(0, 170, 255, 0.1);
background: rgba(37, 99, 235, 0.1);
border: none;
border-radius: 50%;
cursor: pointer;
@ -989,7 +989,7 @@ function buildPayload() {
&:hover {
color: #fff;
background: rgba(0, 170, 255, 0.3);
background: rgba(37, 99, 235, 0.3);
}
}
}
@ -1002,16 +1002,16 @@ function buildPayload() {
padding: 0 20px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #00aaff, #0088dd);
background: linear-gradient(135deg, #2563eb, #1d4ed8);
color: #fff;
font-size: 14px;
font-weight: 600;
box-shadow: 0 4px 15px rgba(0, 170, 255, 0.3);
box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 170, 255, 0.4);
box-shadow: 0 6px 20px rgba(37, 99, 235, 0.4);
}
}
@ -1027,19 +1027,19 @@ function buildPayload() {
gap: 8px;
height: 36px;
padding: 0 16px;
color: rgba(200, 230, 255, 0.8);
color: #374151;
font-size: 13px;
font-weight: 500;
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.2);
background: rgba(37, 99, 235, 0.1);
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
color: #fff;
background: rgba(0, 170, 255, 0.2);
border-color: rgba(0, 170, 255, 0.4);
background: rgba(37, 99, 235, 0.2);
border-color: rgba(37, 99, 235, 0.4);
}
}
@ -1054,7 +1054,7 @@ function buildPayload() {
display: flex;
align-items: center;
gap: 6px;
color: rgba(200, 230, 255, 0.7);
color: #4b5563;
font-size: 13px;
font-weight: 600;
}
@ -1072,11 +1072,11 @@ function buildPayload() {
gap: 8px;
height: 34px;
padding: 0 14px;
color: rgba(200, 230, 255, 0.7);
color: #4b5563;
font-size: 13px;
font-weight: 500;
background: rgba(0, 10, 20, 0.4);
border: 1px solid rgba(0, 170, 255, 0.15);
background: #f9fafb;
border: 1px solid rgba(37, 99, 235, 0.15);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
@ -1085,25 +1085,25 @@ function buildPayload() {
padding: 2px 8px;
font-size: 11px;
font-weight: 700;
background: rgba(0, 170, 255, 0.15);
background: rgba(37, 99, 235, 0.15);
border-radius: 999px;
}
&:hover {
color: #fff;
border-color: rgba(0, 170, 255, 0.4);
background: rgba(0, 170, 255, 0.1);
border-color: rgba(37, 99, 235, 0.4);
background: rgba(37, 99, 235, 0.1);
}
&.active {
color: #fff;
border-color: rgba(0, 170, 255, 0.6);
background: linear-gradient(135deg, rgba(0, 170, 255, 0.25), rgba(0, 100, 180, 0.15));
box-shadow: 0 0 15px rgba(0, 170, 255, 0.2);
border-color: rgba(37, 99, 235, 0.6);
background: linear-gradient(135deg, rgba(37, 99, 235, 0.25), rgba(37, 99, 235, 0.08));
box-shadow: 0 0 15px rgba(37, 99, 235, 0.2);
.tab-count {
background: #00ff9d;
color: #001529;
background: #2ba471;
color: #1f2937;
}
}
}
@ -1114,11 +1114,11 @@ function buildPayload() {
gap: 6px;
margin-left: auto;
padding: 6px 14px;
color: rgba(0, 255, 157, 0.8);
color: #2ba471;
font-size: 12px;
font-weight: 600;
background: rgba(0, 255, 157, 0.1);
border: 1px solid rgba(0, 255, 157, 0.2);
background: rgba(43, 164, 113, 0.1);
border: 1px solid rgba(43, 164, 113, 0.2);
border-radius: 999px;
}
@ -1134,16 +1134,16 @@ function buildPayload() {
position: relative;
padding: 24px;
border-radius: 16px;
background: linear-gradient(145deg, rgba(0, 30, 50, 0.9), rgba(0, 15, 30, 0.95));
border: 1px solid rgba(0, 170, 255, 0.25);
background: #ffffff;
border: 1px solid rgba(37, 99, 235, 0.25);
cursor: pointer;
transition: all 0.3s ease;
overflow: hidden;
&:hover {
border-color: rgba(0, 170, 255, 0.5);
border-color: rgba(37, 99, 235, 0.45);
transform: translateY(-4px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(0, 170, 255, 0.15);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(37, 99, 235, 0.15);
.card-glow {
opacity: 1;
@ -1174,7 +1174,7 @@ function buildPayload() {
right: 20px;
font-size: 48px;
font-weight: 800;
color: rgba(0, 170, 255, 0.08);
color: rgba(37, 99, 235, 0.08);
line-height: 1;
user-select: none;
}
@ -1196,11 +1196,11 @@ function buildPayload() {
align-items: center;
gap: 6px;
padding: 4px 12px;
color: #00aaff;
color: #2563eb;
font-size: 12px;
font-weight: 600;
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.2);
background: rgba(37, 99, 235, 0.1);
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 999px;
}
@ -1214,9 +1214,9 @@ function buildPayload() {
border-radius: 999px;
&.enabled {
color: rgba(0, 255, 157, 0.9);
background: rgba(0, 255, 157, 0.1);
border-color: rgba(0, 255, 157, 0.2);
color: #2ba471;
background: rgba(43, 164, 113, 0.1);
border-color: rgba(43, 164, 113, 0.2);
}
}
@ -1238,7 +1238,7 @@ function buildPayload() {
display: flex;
align-items: center;
gap: 6px;
color: rgba(200, 230, 255, 0.5);
color: #6b7280;
font-size: 12px;
}
@ -1247,7 +1247,7 @@ function buildPayload() {
z-index: 1;
margin-top: 20px;
padding-top: 16px;
border-top: 1px solid rgba(0, 170, 255, 0.1);
border-top: 1px solid rgba(37, 99, 235, 0.1);
}
.edit-btn {
@ -1259,16 +1259,16 @@ function buildPayload() {
height: 38px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #00aaff, #0088dd);
background: linear-gradient(135deg, #2563eb, #1d4ed8);
color: #fff;
font-size: 13px;
font-weight: 600;
box-shadow: 0 4px 15px rgba(0, 170, 255, 0.25);
box-shadow: 0 4px 15px rgba(37, 99, 235, 0.25);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 170, 255, 0.35);
box-shadow: 0 6px 20px rgba(37, 99, 235, 0.18);
}
}
@ -1278,7 +1278,7 @@ function buildPayload() {
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(circle at 30% 0%, rgba(0, 170, 255, 0.15), transparent 60%);
background: radial-gradient(circle at 30% 0%, rgba(37, 99, 235, 0.15), transparent 60%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
@ -1290,7 +1290,7 @@ function buildPayload() {
left: -100%;
width: 50%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(0, 170, 255, 0.1), transparent);
background: linear-gradient(90deg, transparent, rgba(37, 99, 235, 0.1), transparent);
pointer-events: none;
}
@ -1306,20 +1306,20 @@ function buildPayload() {
// 抽屉样式
.training-task-drawer {
// 覆盖 Element Plus 默认白色样式
--el-drawer-bg-color: #081827 !important;
--el-drawer-bg-color: #1f2937 !important;
.el-drawer__body {
height: 100%;
padding: 0;
overflow: hidden;
background: linear-gradient(160deg, #081827 0%, #06111d 58%, #071b2a 100%) !important;
background: linear-gradient(160deg, #1f2937 0%, #f9fafb 58%, #f9fafb 100%) !important;
}
// 移除白色边框
&.el-drawer {
border: none !important;
box-shadow: -10px 0 40px rgba(0, 0, 0, 0.5) !important;
background: linear-gradient(160deg, #081827 0%, #06111d 58%, #071b2a 100%) !important;
background: linear-gradient(160deg, #1f2937 0%, #f9fafb 58%, #f9fafb 100%) !important;
}
}
@ -1328,7 +1328,7 @@ function buildPayload() {
background: rgba(0, 0, 0, 0.7) !important;
.training-task-drawer {
background: linear-gradient(160deg, #081827 0%, #06111d 58%, #071b2a 100%) !important;
background: linear-gradient(160deg, #1f2937 0%, #f9fafb 58%, #f9fafb 100%) !important;
}
}
@ -1336,7 +1336,7 @@ function buildPayload() {
display: flex;
flex-direction: column;
height: 100%;
background: linear-gradient(160deg, #081827 0%, #06111d 58%, #071b2a 100%);
background: linear-gradient(160deg, #1f2937 0%, #f9fafb 58%, #f9fafb 100%);
}
.drawer-header {
@ -1345,8 +1345,8 @@ function buildPayload() {
justify-content: space-between;
gap: 24px;
padding: 28px 32px 22px;
border-bottom: 1px solid rgba(0, 170, 255, 0.2);
background: linear-gradient(90deg, rgba(13, 65, 96, 0.5), rgba(8, 36, 58, 0.3));
border-bottom: 1px solid rgba(37, 99, 235, 0.2);
background: linear-gradient(90deg, #dbeafe, #f3f4f6);
}
.drawer-heading {
@ -1355,11 +1355,11 @@ function buildPayload() {
align-items: center;
gap: 8px;
padding: 6px 14px;
color: #00aaff;
color: #2563eb;
font-size: 12px;
font-weight: 700;
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.3);
background: rgba(37, 99, 235, 0.1);
border: 1px solid rgba(37, 99, 235, 0.3);
border-radius: 999px;
}
@ -1372,7 +1372,7 @@ function buildPayload() {
p {
margin: 0;
color: rgba(200, 230, 255, 0.6);
color: #6b7280;
font-size: 13px;
line-height: 1.6;
}
@ -1384,17 +1384,17 @@ function buildPayload() {
justify-content: center;
width: 36px;
height: 36px;
color: rgba(200, 230, 255, 0.7);
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.2);
color: #4b5563;
background: rgba(37, 99, 235, 0.1);
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 10px;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
color: #fff;
background: rgba(0, 170, 255, 0.25);
border-color: rgba(0, 170, 255, 0.4);
background: rgba(37, 99, 235, 0.25);
border-color: rgba(37, 99, 235, 0.4);
}
}
@ -1403,8 +1403,8 @@ function buildPayload() {
grid-template-columns: 1fr 1.5fr 120px;
gap: 16px;
padding: 20px 32px;
border-bottom: 1px solid rgba(0, 170, 255, 0.15);
background: rgba(0, 10, 20, 0.3);
border-bottom: 1px solid rgba(37, 99, 235, 0.15);
background: #f9fafb;
}
.identity-item {
@ -1412,13 +1412,13 @@ function buildPayload() {
align-items: center;
gap: 12px;
padding: 14px 16px;
background: rgba(0, 30, 50, 0.6);
border: 1px solid rgba(0, 170, 255, 0.2);
background: #f9fafb;
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 12px;
> svg {
flex-shrink: 0;
color: #00aaff;
color: #2563eb;
opacity: 0.7;
}
@ -1429,7 +1429,7 @@ function buildPayload() {
.identity-label {
display: block;
margin-bottom: 4px;
color: rgba(200, 230, 255, 0.5);
color: #6b7280;
font-size: 11px;
font-weight: 600;
}
@ -1446,7 +1446,7 @@ function buildPayload() {
.status-value {
color: #ff6b6b;
&.enabled { color: #00ff9d; }
&.enabled { color: #2ba471; }
}
}
@ -1468,19 +1468,19 @@ function buildPayload() {
// 覆盖 Element Plus 输入框默认白色背景
.el-input__wrapper {
background-color: rgba(0, 10, 20, 0.9) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
background-color: #f3f4f6 !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
border-radius: 8px !important;
box-shadow: none !important;
padding: 2px 12px !important;
&:hover {
border-color: rgba(0, 170, 255, 0.6) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
}
&.is-focus {
border-color: #00aaff !important;
box-shadow: 0 0 12px rgba(0, 170, 255, 0.3) !important;
border-color: #2563eb !important;
box-shadow: 0 0 12px rgba(37, 99, 235, 0.3) !important;
}
}
@ -1490,7 +1490,7 @@ function buildPayload() {
font-weight: 500;
&::placeholder {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
&:hover {
@ -1500,8 +1500,8 @@ function buildPayload() {
// 文本域样式
.el-textarea__inner {
background-color: rgba(0, 10, 20, 0.9) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
background-color: #f3f4f6 !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
border-radius: 8px !important;
box-shadow: none !important;
color: #ffffff !important;
@ -1510,16 +1510,16 @@ function buildPayload() {
padding: 12px !important;
&:hover {
border-color: rgba(0, 170, 255, 0.6) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
}
&.is-focus {
border-color: #00aaff !important;
box-shadow: 0 0 12px rgba(0, 170, 255, 0.3) !important;
border-color: #2563eb !important;
box-shadow: 0 0 12px rgba(37, 99, 235, 0.3) !important;
}
&::placeholder {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
}
}
@ -1527,8 +1527,8 @@ function buildPayload() {
.drawer-section {
padding: 24px;
margin-bottom: 20px;
background: rgba(0, 20, 40, 0.5);
border: 1px solid rgba(0, 170, 255, 0.2);
background: #f9fafb;
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 16px;
}
@ -1546,9 +1546,9 @@ function buildPayload() {
height: 40px;
font-size: 16px;
font-weight: 800;
color: #00aaff;
background: rgba(0, 170, 255, 0.15);
border: 1px solid rgba(0, 170, 255, 0.3);
color: #2563eb;
background: rgba(37, 99, 235, 0.15);
border: 1px solid rgba(37, 99, 235, 0.3);
border-radius: 10px;
}
@ -1562,7 +1562,7 @@ function buildPayload() {
p {
margin: 0;
color: rgba(200, 230, 255, 0.5);
color: #6b7280;
font-size: 12px;
}
}
@ -1580,18 +1580,18 @@ function buildPayload() {
gap: 12px;
.switch-label {
color: rgba(200, 230, 255, 0.7);
color: #4b5563;
font-size: 13px;
}
// Switch 组件暗色化
.el-switch {
--el-switch-off-color: rgba(255, 107, 107, 0.4);
--el-switch-on-color: rgba(0, 255, 157, 0.5);
--el-switch-border-color: rgba(0, 170, 255, 0.3);
--el-switch-on-color: rgba(43, 164, 113, 0.4);
--el-switch-border-color: rgba(37, 99, 235, 0.3);
&.is-checked {
--el-switch-border-color: rgba(0, 255, 157, 0.6);
--el-switch-border-color: rgba(43, 164, 113, 0.5);
}
}
}
@ -1601,12 +1601,12 @@ function buildPayload() {
.el-input {
.el-input__wrapper {
background-color: rgba(0, 10, 20, 0.9) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
background-color: #f3f4f6 !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
box-shadow: none !important;
&:hover, &.is-focus {
border-color: rgba(0, 170, 255, 0.6) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
}
}
@ -1615,7 +1615,7 @@ function buildPayload() {
font-weight: 500;
&::placeholder {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
}
}
@ -1636,9 +1636,9 @@ function buildPayload() {
height: 28px;
font-size: 12px;
font-weight: 700;
color: #00aaff;
background: rgba(0, 170, 255, 0.1);
border: 1px solid rgba(0, 170, 255, 0.2);
color: #2563eb;
background: rgba(37, 99, 235, 0.1);
border: 1px solid rgba(37, 99, 235, 0.2);
border-radius: 6px;
}
@ -1681,19 +1681,19 @@ function buildPayload() {
gap: 8px;
height: 38px;
padding: 0 18px;
color: #00aaff;
color: #2563eb;
font-size: 13px;
font-weight: 600;
background: rgba(0, 170, 255, 0.08);
border: 1px dashed rgba(0, 170, 255, 0.3);
background: rgba(37, 99, 235, 0.08);
border: 1px dashed rgba(37, 99, 235, 0.3);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
color: #fff;
background: rgba(0, 170, 255, 0.15);
border-color: rgba(0, 170, 255, 0.5);
background: rgba(37, 99, 235, 0.15);
border-color: rgba(37, 99, 235, 0.45);
}
}
@ -1704,8 +1704,8 @@ function buildPayload() {
gap: 20px;
padding: 16px;
margin-bottom: 16px;
background: rgba(0, 10, 20, 0.4);
border: 1px solid rgba(0, 170, 255, 0.15);
background: #f9fafb;
border: 1px solid rgba(37, 99, 235, 0.15);
border-radius: 12px;
}
@ -1717,7 +1717,7 @@ function buildPayload() {
> svg {
flex-shrink: 0;
color: #00aaff;
color: #2563eb;
}
.material-text {
@ -1735,14 +1735,14 @@ function buildPayload() {
.material-link {
overflow: hidden;
color: #00aaff;
color: #2563eb;
font-weight: 600;
text-overflow: ellipsis;
white-space: nowrap;
}
.material-placeholder {
color: rgba(200, 230, 255, 0.4);
color: #9ca3af;
font-style: italic;
}
}
@ -1763,13 +1763,13 @@ function buildPayload() {
display: flex;
align-items: center;
gap: 8px;
background: linear-gradient(135deg, rgba(0, 170, 255, 0.2), rgba(0, 100, 180, 0.15)) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
color: #00aaff !important;
background: linear-gradient(135deg, rgba(37, 99, 235, 0.2), rgba(37, 99, 235, 0.08)) !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
color: #2563eb !important;
&:hover {
background: linear-gradient(135deg, rgba(0, 170, 255, 0.3), rgba(0, 100, 180, 0.25)) !important;
border-color: rgba(0, 170, 255, 0.6) !important;
background: linear-gradient(135deg, rgba(37, 99, 235, 0.3), rgba(37, 99, 235, 0.15)) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
color: #ffffff !important;
}
}
@ -1805,9 +1805,9 @@ function buildPayload() {
height: 32px;
font-size: 13px;
font-weight: 700;
color: #00ff9d;
background: rgba(0, 255, 157, 0.1);
border: 1px solid rgba(0, 255, 157, 0.2);
color: #2ba471;
background: rgba(43, 164, 113, 0.1);
border: 1px solid rgba(43, 164, 113, 0.2);
border-radius: 8px;
}
@ -1819,7 +1819,7 @@ function buildPayload() {
.step-question-tag {
flex-shrink: 0;
color: rgba(200, 230, 255, 0.6);
color: #6b7280;
font-size: 12px;
white-space: nowrap;
}
@ -1828,12 +1828,12 @@ function buildPayload() {
flex: 1;
.el-input__wrapper {
background-color: rgba(0, 10, 20, 0.9) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
background-color: #f3f4f6 !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
box-shadow: none !important;
&:hover, &.is-focus {
border-color: rgba(0, 170, 255, 0.6) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
}
}
@ -1842,7 +1842,7 @@ function buildPayload() {
font-weight: 500;
&::placeholder {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
}
}
@ -1857,22 +1857,22 @@ function buildPayload() {
justify-content: flex-end;
gap: 14px;
padding: 18px 32px;
background: rgba(0, 10, 20, 0.95);
border-top: 1px solid rgba(0, 170, 255, 0.2);
background: #ffffff;
border-top: 1px solid rgba(37, 99, 235, 0.2);
}
.cancel-btn {
height: 40px;
padding: 0 24px;
color: rgba(200, 230, 255, 0.8) !important;
background: rgba(0, 170, 255, 0.1) !important;
border: 1px solid rgba(0, 170, 255, 0.25) !important;
color: #374151 !important;
background: rgba(37, 99, 235, 0.1) !important;
border: 1px solid rgba(37, 99, 235, 0.25) !important;
border-radius: 10px;
&:hover {
color: #ffffff !important;
background: rgba(0, 170, 255, 0.2) !important;
border-color: rgba(0, 170, 255, 0.4) !important;
background: rgba(37, 99, 235, 0.2) !important;
border-color: rgba(37, 99, 235, 0.4) !important;
}
}
@ -1884,8 +1884,8 @@ function buildPayload() {
padding: 0 24px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #00aaff, #0088dd);
box-shadow: 0 4px 15px rgba(0, 170, 255, 0.3);
background: linear-gradient(135deg, #2563eb, #1d4ed8);
box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3);
}
@media (max-width: 1280px) {
@ -1951,23 +1951,23 @@ function buildPayload() {
height: calc(100vh - 50px);
overflow-x: hidden;
overflow-y: auto !important;
background: linear-gradient(135deg, #03070e 0%, #061827 48%, #02060d 100%) !important;
background: linear-gradient(135deg, #f7fafd 0%, #eef4fb 48%, #f5f8fc 100%) !important;
}
// 全局覆盖 Element Plus 抽屉白色边框
.el-drawer.training-task-drawer {
background: linear-gradient(160deg, #081827 0%, #06111d 58%, #071b2a 100%) !important;
background: linear-gradient(160deg, #1f2937 0%, #f9fafb 58%, #f9fafb 100%) !important;
border: none !important;
.el-drawer__body {
background: linear-gradient(160deg, #081827 0%, #06111d 58%, #071b2a 100%) !important;
background: linear-gradient(160deg, #1f2937 0%, #f9fafb 58%, #f9fafb 100%) !important;
}
}
// Element Plus 抽屉暗色化
.el-drawer {
--el-drawer-bg-color: #081827 !important;
background-color: #081827 !important;
--el-drawer-bg-color: #1f2937 !important;
background-color: #1f2937 !important;
}
// ===== 输入框全面暗色化覆盖 =====
@ -1975,39 +1975,39 @@ function buildPayload() {
.el-input__inner {
color: #ffffff !important;
&::placeholder {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
}
// 输入框包装器背景
.el-input__wrapper {
background-color: rgba(0, 10, 20, 0.9) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
background-color: #f3f4f6 !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
box-shadow: none !important;
&:hover {
border-color: rgba(0, 170, 255, 0.6) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
}
&.is-focus {
border-color: #00aaff !important;
box-shadow: 0 0 12px rgba(0, 170, 255, 0.3) !important;
border-color: #2563eb !important;
box-shadow: 0 0 12px rgba(37, 99, 235, 0.3) !important;
}
}
// 文本域暗色化
.el-textarea__inner {
background-color: rgba(0, 10, 20, 0.9) !important;
border: 1px solid rgba(0, 170, 255, 0.4) !important;
background-color: #f3f4f6 !important;
border: 1px solid rgba(37, 99, 235, 0.4) !important;
box-shadow: none !important;
color: #ffffff !important;
&::placeholder {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
&:hover {
border-color: rgba(0, 170, 255, 0.6) !important;
border-color: rgba(37, 99, 235, 0.6) !important;
}
&.is-focus {
border-color: #00aaff !important;
box-shadow: 0 0 12px rgba(0, 170, 255, 0.3) !important;
border-color: #2563eb !important;
box-shadow: 0 0 12px rgba(37, 99, 235, 0.3) !important;
}
}
@ -2019,23 +2019,23 @@ function buildPayload() {
// 输入框禁用状态暗色化
.el-input.is-disabled .el-input__wrapper {
background-color: rgba(0, 10, 20, 0.6) !important;
border-color: rgba(0, 170, 255, 0.25) !important;
background-color: #f9fafb !important;
border-color: rgba(37, 99, 235, 0.25) !important;
.el-input__inner {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
}
// 文本域禁用状态
.el-textarea.is-disabled .el-textarea__inner {
background-color: rgba(0, 10, 20, 0.6) !important;
border-color: rgba(0, 170, 255, 0.25) !important;
color: rgba(200, 230, 255, 0.5) !important;
background-color: #f9fafb !important;
border-color: rgba(37, 99, 235, 0.25) !important;
color: #6b7280 !important;
}
// 表单禁用标签
.el-form-item.is-disabled .el-form-item__label {
color: rgba(200, 230, 255, 0.5) !important;
color: #6b7280 !important;
}
</style>

@ -8,6 +8,7 @@
-->
<template>
<div class="marketing app-container student-training-shell legacy-training-page">
<TrainingTaskToolbar />
<TrainingIntro title="四象限法则">
<template #background>
<p>
@ -103,6 +104,7 @@ import popModel from "@/views/components/popModal.vue";
import * as analysisAPI from "@/api/market-demand-mining.js";
import * as echarts from "echarts";
import { onMounted } from "vue";
import TrainingTaskToolbar from "@/views/components/TrainingTaskToolbar.vue";
const textarea = ref("");
const dialogVisible = ref(false);
const { proxy } = getCurrentInstance();

Loading…
Cancel
Save