|
|
@@ -0,0 +1,608 @@
|
|
|
+<!-- 新建考试 -->
|
|
|
+<template>
|
|
|
+ <div class="page-container examinationArrange-addPage">
|
|
|
+ <div class="top-max-big-box">
|
|
|
+ <p class="top-1-p">{{newData.id ? '编辑考试' : '新建考试'}}</p>
|
|
|
+ <p class="top-2-p" @click="backPage()">返回</p>
|
|
|
+ <p class="top-3-p" v-if="newData.id" @click="resetButton()">重置</p>
|
|
|
+ <p class="top-4-p" @click="submitButton()">保存</p>
|
|
|
+ </div>
|
|
|
+ <div class="content-box">
|
|
|
+ <div class="layout-box">
|
|
|
+ <!-- 左侧导航 -->
|
|
|
+ <div class="side-nav">
|
|
|
+ <div
|
|
|
+ v-for="tab in tabs"
|
|
|
+ :key="tab.key"
|
|
|
+ class="nav-item"
|
|
|
+ :class="{ active: activeTab === tab.key }"
|
|
|
+ @click="activeTab = tab.key"
|
|
|
+ >{{ tab.label }}</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧内容 -->
|
|
|
+ <div class="tab-content scrollbar-box">
|
|
|
+
|
|
|
+ <!-- ==================== 基本设置 ==================== -->
|
|
|
+ <div v-show="activeTab === 'basic'">
|
|
|
+ <el-form :model="newData" ref="basicForm" label-width="100px" :rules="rules">
|
|
|
+ <div class="section-block">
|
|
|
+ <div class="flex-row-box">
|
|
|
+ <el-form-item label="考试类型" prop="examType">
|
|
|
+ <el-select v-model="newData.examType" placeholder="分级分类" style="width:200px;">
|
|
|
+ <el-option v-for="item in optionExamType" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="风险等级" prop="riskLevel">
|
|
|
+ <el-select v-model="newData.riskLevel" placeholder="I级" style="width:200px;">
|
|
|
+ <el-option v-for="item in optionRiskLevel" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-form-item label="考试名称" prop="examName">
|
|
|
+ <el-input v-model="newData.examName" placeholder="请输入课程名称" style="width:100%;" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="答卷次数" prop="answerCount">
|
|
|
+ <div class="stepper-row">
|
|
|
+ <div class="number-stepper">
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('answerCount', -1)">-</button>
|
|
|
+ <span class="stepper-val">{{ newData.answerCount }}</span>
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('answerCount', 1)">+</button>
|
|
|
+ </div>
|
|
|
+ <span class="unit-text">次</span>
|
|
|
+ <el-radio v-model="newData.answerUnlimited" :label="true" style="margin-left:20px;">无限制</el-radio>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="是否共享">
|
|
|
+ <el-switch v-model="newData.isShare" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <span class="tip-text" v-if="newData.isShare">共享开启,全校所有学院单位都可见</span>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="启用" prop="enabled">
|
|
|
+ <el-switch v-model="newData.enabled" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="考卷" prop="paperId">
|
|
|
+ <div class="paper-select-row">
|
|
|
+ <el-button type="primary" @click="openPaperDrawer">选择试卷</el-button>
|
|
|
+ <div class="selected-tag" v-if="newData.paperName">
|
|
|
+ <span>{{ newData.paperName }}</span>
|
|
|
+ <i class="el-icon-close" @click="newData.paperId = null; newData.paperName = ''"></i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section-divider"></div>
|
|
|
+
|
|
|
+ <div class="section-block">
|
|
|
+ <div class="flex-row-box">
|
|
|
+ <el-form-item label="考试时间" prop="examTimeRange">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="newData.examTimeRange"
|
|
|
+ type="datetimerange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ style="width:320px;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="考试时长" prop="examDuration">
|
|
|
+ <div class="stepper-row">
|
|
|
+ <div class="number-stepper">
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('examDuration', -1)">-</button>
|
|
|
+ <span class="stepper-val">{{ newData.examDuration }}</span>
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('examDuration', 1)">+</button>
|
|
|
+ </div>
|
|
|
+ <span class="unit-text">分钟</span>
|
|
|
+ <span class="tip-text" style="margin-left:12px;">限制答卷最大时长</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-form-item label="考试范围" prop="examScope">
|
|
|
+ <div class="scope-btn-group">
|
|
|
+ <button
|
|
|
+ v-for="item in scopeOptions"
|
|
|
+ :key="item.value"
|
|
|
+ class="scope-btn"
|
|
|
+ :class="{ active: newData.examScope === item.value }"
|
|
|
+ @click.prevent="newData.examScope = item.value"
|
|
|
+ >
|
|
|
+ <i v-if="newData.examScope === item.value" class="el-icon-check" style="color:#0183fa;margin-right:4px;"></i>
|
|
|
+ {{ item.label }}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <!-- 考试范围表格(非全校时显示) -->
|
|
|
+ <div v-if="newData.examScope !== 'all'" class="scope-table-box">
|
|
|
+ <div class="scope-table-header">已选取:{{ scopeList.length }}组</div>
|
|
|
+ <el-table :data="scopeList" size="small" style="width:100%;">
|
|
|
+ <el-table-column label="学院" prop="college" />
|
|
|
+ <el-table-column label="专业" prop="major" width="160" />
|
|
|
+ <el-table-column label="角色" prop="role" width="120" />
|
|
|
+ <el-table-column label="年级" prop="grade" width="120" />
|
|
|
+ <el-table-column label="操作" width="80" align="center">
|
|
|
+ <template slot-scope="{ $index }">
|
|
|
+ <el-button size="mini" @click="scopeList.splice($index, 1)">移除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- ==================== 考前配置 ==================== -->
|
|
|
+ <div v-show="activeTab === 'preExam'">
|
|
|
+ <el-form :model="newData" label-width="100px">
|
|
|
+ <div class="section-block">
|
|
|
+ <el-form-item label="学时要求">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.creditRequired" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <div class="number-stepper" style="margin-left:12px;">
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('creditHours', -1)">-</button>
|
|
|
+ <span class="stepper-val">{{ newData.creditHours }}</span>
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('creditHours', 1)">+</button>
|
|
|
+ </div>
|
|
|
+ <span class="unit-text">学时</span>
|
|
|
+ <span class="tip-text" style="margin-left:12px;" v-if="newData.creditRequired">开启后,需完成相应学时才能参加考试</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="考前学习">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.preStudy" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <el-button type="primary" style="margin-left:12px;" @click="openCourseDrawer">选择课程</el-button>
|
|
|
+ </div>
|
|
|
+ <div class="selected-tag" v-if="newData.preStudyCourseName" style="margin-top:8px;max-width:400px;">
|
|
|
+ <span>{{ newData.preStudyCourseName }}</span>
|
|
|
+ <i class="el-icon-close" @click="newData.preStudyCourseId = null; newData.preStudyCourseName = ''"></i>
|
|
|
+ </div>
|
|
|
+ <div class="tip-text" v-if="newData.preStudy" style="margin-top:6px;">开启后,需完成学习才能参加考试</div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="模拟练习">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.mockPractice" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <el-button type="primary" style="margin-left:12px;" @click="reuseExamPaper">复用试卷</el-button>
|
|
|
+ <el-button style="margin-left:8px;" @click="openMockPaperDrawer">选择试题</el-button>
|
|
|
+ <span class="tip-text" style="margin-left:12px;" v-if="newData.mockPractice">开启后,需完成模拟练习任务才能参加考试</span>
|
|
|
+ </div>
|
|
|
+ <div class="mock-stat-bar" v-if="newData.mockPaperId">
|
|
|
+ <span>总题目数:<b>{{ newData.mockTotalCount || 0 }}</b></span>
|
|
|
+ <span style="margin-left:20px;">总分:<b>{{ newData.mockTotalScore || 0 }}</b></span>
|
|
|
+ <span style="margin-left:20px;">及格分:<b>{{ newData.mockPassScore || 0 }}</b></span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="考试承诺书">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.pledge" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <span class="tip-text" style="margin-left:12px;" v-if="newData.pledge">开启后,考生需要阅读考试承诺内容并做出承诺才可开始考试</span>
|
|
|
+ <span style="margin-left:30px;font-weight:600;color:#333;">承诺书打印</span>
|
|
|
+ <el-switch v-model="newData.pledgePrint" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" style="margin-left:12px;" />
|
|
|
+ </div>
|
|
|
+ <div class="editor-box" v-if="newData.pledge" style="margin-top:12px;">
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="newData.pledgeContent"
|
|
|
+ :rows="10"
|
|
|
+ placeholder="请输入考试承诺书内容"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- ==================== 防作弊 ==================== -->
|
|
|
+ <div v-show="activeTab === 'antiCheat'">
|
|
|
+ <el-form :model="newData" label-width="120px">
|
|
|
+ <div class="section-block">
|
|
|
+ <el-form-item label="图形弹窗校验">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.captcha" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <template v-if="newData.captcha">
|
|
|
+ <span class="tip-text" style="margin-left:12px;">开启后,每隔</span>
|
|
|
+ <div class="number-stepper" style="margin-left:8px;">
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('captchaInterval', -1)">-</button>
|
|
|
+ <span class="stepper-val">{{ newData.captchaInterval }}</span>
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('captchaInterval', 1)">+</button>
|
|
|
+ </div>
|
|
|
+ <span class="tip-text" style="margin-left:8px;">分钟,提醒弹窗验证</span>
|
|
|
+ </template>
|
|
|
+ <span class="tip-text" style="margin-left:12px;" v-else>开启后,每隔 N 分钟,提醒弹窗验证</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="人脸识别校验">
|
|
|
+ <div class="anti-cheat-group">
|
|
|
+ <div class="switch-row" style="margin-bottom:12px;">
|
|
|
+ <el-switch v-model="newData.faceRecognitionBefore" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <span class="tip-text" style="margin-left:12px;">开启后,考试前需要进行人脸识别(仅学习考试一体机)</span>
|
|
|
+ </div>
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.faceRecognitionAfter" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <span class="tip-text" style="margin-left:12px;">开启后,考试后需要进行人脸识别(仅学习考试一体机)</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="摄像头抓拍">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.cameraCapture" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <span class="tip-text" style="margin-left:12px;">开启后,考试过程中摄像头随机抓拍(仅学习考试一体机)</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- ==================== 获得证书 ==================== -->
|
|
|
+ <div v-show="activeTab === 'certificate'">
|
|
|
+ <el-form :model="newData" label-width="120px">
|
|
|
+ <div class="section-block">
|
|
|
+ <el-form-item label="获得证书">
|
|
|
+ <div class="switch-row">
|
|
|
+ <el-switch v-model="newData.certificate" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ <el-button type="primary" style="margin-left:12px;" @click="openCertTemplateDrawer">选择模板</el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="证书打印">
|
|
|
+ <el-switch v-model="newData.certPrint" :active-value="true" :inactive-value="false"
|
|
|
+ active-color="#0183FB" inactive-color="#AAAAAA" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="证书有效期">
|
|
|
+ <div class="stepper-row">
|
|
|
+ <div class="number-stepper">
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('certValidity', -1)">-</button>
|
|
|
+ <span class="stepper-val">{{ newData.certValidity }}</span>
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('certValidity', 1)">+</button>
|
|
|
+ </div>
|
|
|
+ <span class="unit-text">个月</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="证书复审周期">
|
|
|
+ <div class="stepper-row">
|
|
|
+ <div class="number-stepper">
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('certReviewCycle', -1)">-</button>
|
|
|
+ <span class="stepper-val">{{ newData.certReviewCycle }}</span>
|
|
|
+ <button class="stepper-btn" @click.prevent="stepChange('certReviewCycle', 1)">+</button>
|
|
|
+ </div>
|
|
|
+ <span class="unit-text">个月</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ name: 'addPage',
|
|
|
+ props: {
|
|
|
+ propsData: {}
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ activeTab: 'basic',
|
|
|
+ tabs: [
|
|
|
+ { key: 'basic', label: '基本设置' },
|
|
|
+ { key: 'preExam', label: '考前配置' },
|
|
|
+ { key: 'antiCheat', label: '防作弊' },
|
|
|
+ { key: 'certificate', label: '获得证书' },
|
|
|
+ ],
|
|
|
+ scopeOptions: [
|
|
|
+ { label: '全校', value: 'all' },
|
|
|
+ { label: '考试范围', value: 'scope' },
|
|
|
+ { label: '指定考生', value: 'specify' },
|
|
|
+ ],
|
|
|
+ optionExamType: [
|
|
|
+ { label: '分级分类', value: 1 },
|
|
|
+ ],
|
|
|
+ optionRiskLevel: [
|
|
|
+ { label: 'I级', value: 1 },
|
|
|
+ { label: 'II级', value: 2 },
|
|
|
+ { label: 'III级', value: 3 },
|
|
|
+ ],
|
|
|
+ scopeList: [],
|
|
|
+ newData: {
|
|
|
+ id: null,
|
|
|
+ examType: null,
|
|
|
+ riskLevel: null,
|
|
|
+ examName: '',
|
|
|
+ answerCount: 2,
|
|
|
+ answerUnlimited: false,
|
|
|
+ isShare: true,
|
|
|
+ enabled: true,
|
|
|
+ paperId: null,
|
|
|
+ paperName: '',
|
|
|
+ examTimeRange: null,
|
|
|
+ examDuration: 2,
|
|
|
+ examScope: 'scope',
|
|
|
+ creditRequired: false,
|
|
|
+ creditHours: 2,
|
|
|
+ preStudy: false,
|
|
|
+ preStudyCourseId: null,
|
|
|
+ preStudyCourseName: '',
|
|
|
+ mockPractice: false,
|
|
|
+ mockPaperId: null,
|
|
|
+ mockTotalCount: 0,
|
|
|
+ mockTotalScore: 0,
|
|
|
+ mockPassScore: 0,
|
|
|
+ pledge: false,
|
|
|
+ pledgePrint: false,
|
|
|
+ pledgeContent: '',
|
|
|
+ captcha: false,
|
|
|
+ captchaInterval: 2,
|
|
|
+ faceRecognitionBefore: false,
|
|
|
+ faceRecognitionAfter: false,
|
|
|
+ cameraCapture: false,
|
|
|
+ certificate: true,
|
|
|
+ certPrint: true,
|
|
|
+ certValidity: 12,
|
|
|
+ certReviewCycle: 12,
|
|
|
+ },
|
|
|
+ rules: {
|
|
|
+ examType: [{ required: true, message: '请选择考试类型', trigger: 'change' }],
|
|
|
+ examName: [{ required: true, message: '请输入考试名称', trigger: 'blur' }],
|
|
|
+ paperId: [{ required: true, message: '请选择考卷', trigger: 'change' }],
|
|
|
+ examTimeRange: [{ required: true, message: '请选择考试时间', trigger: 'change' }],
|
|
|
+ },
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.initialize()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ initialize() {
|
|
|
+ if (this.propsData && this.propsData.id) {
|
|
|
+ this.newData = { ...this.newData, ...this.propsData }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ backPage() {
|
|
|
+ this.$parent.tableButton(6)
|
|
|
+ },
|
|
|
+ resetButton() {
|
|
|
+ this.$refs.basicForm && this.$refs.basicForm.resetFields()
|
|
|
+ },
|
|
|
+ submitButton() {
|
|
|
+ this.$refs.basicForm.validate(valid => {
|
|
|
+ if (!valid) {
|
|
|
+ this.activeTab = 'basic'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // TODO: 调用保存接口
|
|
|
+ })
|
|
|
+ },
|
|
|
+ stepChange(field, delta) {
|
|
|
+ const val = (Number(this.newData[field]) || 0) + delta
|
|
|
+ this.newData[field] = Math.max(0, val)
|
|
|
+ },
|
|
|
+ openPaperDrawer() {
|
|
|
+ // TODO: 打开选择试卷弹窗
|
|
|
+ },
|
|
|
+ openCourseDrawer() {
|
|
|
+ // TODO: 打开选择课程弹窗
|
|
|
+ },
|
|
|
+ reuseExamPaper() {
|
|
|
+ // TODO: 复用考试试卷
|
|
|
+ },
|
|
|
+ openMockPaperDrawer() {
|
|
|
+ // TODO: 打开选择试题弹窗
|
|
|
+ },
|
|
|
+ openCertTemplateDrawer() {
|
|
|
+ // TODO: 打开选择证书模板弹窗
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ .examinationArrange-addPage {
|
|
|
+ .top-max-big-box {
|
|
|
+ height: 60px;
|
|
|
+ display: flex;
|
|
|
+ overflow: hidden;
|
|
|
+ padding: 0 20px;
|
|
|
+ border-bottom: 1px solid #dedede;
|
|
|
+ align-items: center;
|
|
|
+ .top-1-p { flex: 1; font-size: 16px; font-weight: 700; }
|
|
|
+ .top-2-p {
|
|
|
+ height: 35px; line-height: 33px; margin-left: 20px; padding: 0 20px;
|
|
|
+ border-radius: 4px; background-color: #fff; border: 1px solid #999; color: #999; cursor: pointer;
|
|
|
+ }
|
|
|
+ .top-3-p {
|
|
|
+ height: 35px; line-height: 33px; margin-left: 20px; padding: 0 20px;
|
|
|
+ border-radius: 4px; background-color: #dedede; border: 1px solid #dedede; color: #333; cursor: pointer;
|
|
|
+ }
|
|
|
+ .top-4-p {
|
|
|
+ height: 35px; line-height: 33px; margin-left: 20px; padding: 0 20px;
|
|
|
+ border-radius: 4px; background-color: #0183fa; border: 1px solid #0183fa; color: #fff; cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-box {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .layout-box {
|
|
|
+ display: flex;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .side-nav {
|
|
|
+ width: 140px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ border-right: 1px solid #e8e8e8;
|
|
|
+ padding: 24px 0;
|
|
|
+ background: #fff;
|
|
|
+ .nav-item {
|
|
|
+ padding: 14px 24px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #555;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.15s;
|
|
|
+ &:hover { color: #0183fa; }
|
|
|
+ &.active {
|
|
|
+ color: #0183fa;
|
|
|
+ font-weight: 600;
|
|
|
+ background: #f0f7ff;
|
|
|
+ border-right: 3px solid #0183fa;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-content {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 24px 32px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-block {
|
|
|
+ padding-bottom: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-divider {
|
|
|
+ height: 1px;
|
|
|
+ background: #e8e8e8;
|
|
|
+ margin: 16px 0 24px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .flex-row-box {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 0 60px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stepper-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .number-stepper {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ .stepper-btn {
|
|
|
+ width: 32px; height: 32px; background: #f5f7fa; border: none;
|
|
|
+ cursor: pointer; font-size: 16px; color: #333;
|
|
|
+ &:hover { background: #e6f0fe; }
|
|
|
+ }
|
|
|
+ .stepper-val {
|
|
|
+ min-width: 44px; text-align: center; font-size: 14px; padding: 0 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .unit-text {
|
|
|
+ margin-left: 8px; color: #333; white-space: nowrap; font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tip-text {
|
|
|
+ color: #999; font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .paper-select-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .selected-tag {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ background: #e6f4ff;
|
|
|
+ border: 1px solid #91caff;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 6px 12px;
|
|
|
+ color: #0183fa;
|
|
|
+ font-size: 13px;
|
|
|
+ min-width: 200px;
|
|
|
+ max-width: 500px;
|
|
|
+ i { margin-left: 8px; cursor: pointer; &:hover { color: #e74c3c; } }
|
|
|
+ }
|
|
|
+
|
|
|
+ .scope-btn-group {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ .scope-btn {
|
|
|
+ padding: 7px 20px; border: 1px solid #dcdfe6; border-radius: 4px;
|
|
|
+ background: #fff; cursor: pointer; font-size: 14px; color: #333;
|
|
|
+ display: flex; align-items: center; transition: all 0.15s;
|
|
|
+ &:hover { border-color: #0183fa; color: #0183fa; }
|
|
|
+ &.active { border-color: #0183fa; color: #0183fa; background: #f0f7ff; }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .scope-table-box {
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ .scope-table-header {
|
|
|
+ background: #f5f5f5;
|
|
|
+ padding: 10px 16px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #555;
|
|
|
+ border-bottom: 1px solid #e8e8e8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .switch-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .anti-cheat-group {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mock-stat-bar {
|
|
|
+ background: #e6f4ff;
|
|
|
+ border: 1px solid #91caff;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 10px 16px;
|
|
|
+ margin-top: 10px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #333;
|
|
|
+ display: inline-block;
|
|
|
+ b { color: #0183fa; font-weight: 600; }
|
|
|
+ }
|
|
|
+
|
|
|
+ .editor-box {
|
|
|
+ max-width: 760px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|