前端代码

This commit is contained in:
liumengyu
2026-08-21 18:42:51 +08:00
parent 054947482f
commit 04e06a9c9a
762 changed files with 62992 additions and 0 deletions
@@ -0,0 +1,875 @@
<template>
<div class="app-container subject-page">
<!-- ==================== 1. 顶部状态提示 ==================== -->
<div class="status-tip">{{ statusTip }}</div>
<!-- ==================== 2. 查询条件区域 ==================== -->
<el-card shadow="never" class="search-card">
<el-form :model="searchForm">
<el-row :gutter="32">
<!-- 左栏 -->
<el-col :xs="24" :md="12">
<div class="query-field">
<span class="q-label no-check">课程别名</span>
<el-input v-model="searchForm.kcbh" placeholder="请输入课程别名" clearable class="q-control" />
</div>
<div class="query-field">
<span class="q-label no-check">简称</span>
<el-input v-model="searchForm.jc" placeholder="请输入简称" clearable class="q-control" />
</div>
<div class="query-field">
<span class="q-label no-check">学分</span>
<div class="q-control range-control">
<el-input v-model="searchForm.xfMin" placeholder="0" />
<span class="range-sep"></span>
<el-input v-model="searchForm.xfMax" placeholder="0" />
</div>
</div>
<div class="query-field">
<span class="q-label no-check">学时</span>
<div class="q-control range-control">
<el-input v-model="searchForm.xsMin" placeholder="0" />
<span class="range-sep"></span>
<el-input v-model="searchForm.xsMax" placeholder="0" />
</div>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.zcfsEnabled" />
<span class="q-label">支持方式</span>
<el-select v-model="searchForm.zcfs" class="q-control" :disabled="!searchForm.zcfsEnabled">
<el-option v-for="item in zcfsOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.khlxEnabled" />
<span class="q-label">考核类型</span>
<el-select v-model="searchForm.khlx" class="q-control" :disabled="!searchForm.khlxEnabled">
<el-option v-for="item in khlxOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<span class="q-label no-check">秘密等级</span>
<el-select v-model="searchForm.mmdj" placeholder="请选择" class="q-control">
<el-option v-for="item in mmdjOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.dgxzEnabled" />
<span class="q-label">大纲性质</span>
<el-radio-group v-model="searchForm.dgxz" class="q-control" :disabled="!searchForm.dgxzEnabled">
<el-radio :label="'大纲课程'">大纲课程</el-radio>
<el-radio :label="'非大纲课程'">非大纲课程</el-radio>
</el-radio-group>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.zzglEnabled" />
<span class="q-label">政治类课程</span>
<el-radio-group v-model="searchForm.zzgl" class="q-control" :disabled="!searchForm.zzglEnabled">
<el-radio :label="'政治类'">政治类</el-radio>
<el-radio :label="'非政治类'">非政治类</el-radio>
</el-radio-group>
</div>
<div class="query-field">
<span class="q-label no-check">备注</span>
<el-input v-model="searchForm.bz" placeholder="请输入备注" clearable class="q-control" />
</div>
</el-col>
<!-- 右栏 -->
<el-col :xs="24" :md="12">
<div class="query-field">
<el-checkbox v-model="searchForm.jysEnabled" />
<span class="q-label">教研室</span>
<el-select v-model="searchForm.jys" class="q-control" :disabled="!searchForm.jysEnabled">
<el-option v-for="item in jysOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.pxccEnabled" />
<span class="q-label">培训层次</span>
<el-select v-model="searchForm.pxcc" class="q-control" :disabled="!searchForm.pxccEnabled">
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.pxlxEnabled" />
<span class="q-label">培训类型</span>
<el-select v-model="searchForm.pxlx" class="q-control" :disabled="!searchForm.pxlxEnabled">
<el-option v-for="item in pxlxOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.kclxEnabled" />
<span class="q-label">课程类型</span>
<el-select v-model="searchForm.kclx" class="q-control" :disabled="!searchForm.kclxEnabled">
<el-option v-for="item in kclxOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.jsfsEnabled" />
<span class="q-label">建设方式</span>
<el-select v-model="searchForm.jsfs" class="q-control" :disabled="!searchForm.jsfsEnabled">
<el-option v-for="item in jsfsOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.pjqkEnabled" />
<span class="q-label">评选情况</span>
<el-select v-model="searchForm.pjqk" class="q-control" :disabled="!searchForm.pjqkEnabled">
<el-option v-for="item in pjqkOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.gljgEnabled" />
<span class="q-label">管理机构</span>
<el-select v-model="searchForm.gljg" class="q-control" :disabled="!searchForm.gljgEnabled">
<el-option v-for="item in gljgOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.zyxzEnabled" />
<span class="q-label">在用选项</span>
<el-radio-group v-model="searchForm.zyxz" class="q-control" :disabled="!searchForm.zyxzEnabled">
<el-radio :label="'在用'">在用</el-radio>
<el-radio :label="'其他'">其他</el-radio>
</el-radio-group>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.bbxxEnabled" />
<span class="q-label">版本选项</span>
<el-radio-group v-model="searchForm.bbxx" class="q-control" :disabled="!searchForm.bbxxEnabled">
<el-radio :label="'最新版本'">最新版本</el-radio>
<el-radio :label="'存在多版本'">存在多版本</el-radio>
<el-radio :label="'全部版本'">全部版本</el-radio>
</el-radio-group>
</div>
<div class="query-field">
<el-checkbox v-model="searchForm.bmbhEnabled" />
<span class="q-label">别名包含规范名称</span>
<el-radio-group v-model="searchForm.bmbh" class="q-control" :disabled="!searchForm.bmbhEnabled">
<el-radio :label="'完全包含'">完全包含</el-radio>
<el-radio :label="'未完全包含'">未完全包含</el-radio>
</el-radio-group>
</div>
</el-col>
</el-row>
</el-form>
<div class="notice">注意勾选"选择框"表示启用该项对应的查询条件输入框非空表示启用查询条件</div>
<div class="query-footer">
<el-button class="gray-btn" @click="handleQuery">查询</el-button>
</div>
</el-card>
<!-- ==================== 3. 操作按钮区域 ==================== -->
<el-card shadow="never" class="action-card">
<div class="action-row">
<el-button type="primary" @click="handleOpenDialog">新建课程科目</el-button>
<el-button type="primary" @click="handleBatchDelete">删除所选</el-button>
<el-button type="primary" @click="handleDownloadCourse">下载课程科目基本信息</el-button>
<el-button type="primary" @click="handleDownloadTextbook">下载课程教材基本信息</el-button>
</div>
<div class="action-row">
<el-button type="primary" @click="handleDownloadTemplate">课程科目数据文件模板下载</el-button>
</div>
</el-card>
<!-- ==================== 4. 文件上传区域 ==================== -->
<el-card shadow="never" class="upload-card">
<div class="upload-row">
<div class="upload-left">
<el-button @click="handleSelectFile">选择文件</el-button>
<span class="file-name" :class="{ 'has-file': selectedFile }">{{ fileName }}</span>
<input ref="fileInputRef" type="file" style="display: none" @change="handleFileChange" />
</div>
<div class="upload-right">
<el-checkbox v-model="coverExist">覆盖已存在课程科目</el-checkbox>
<el-button type="primary" @click="handleUpload">上传数据</el-button>
</div>
</div>
</el-card>
<!-- ==================== 5. 红色提示文字 ==================== -->
<div class="red-tip">
提示课程体系按"课程-专题-课题"构建的课程名称的命名格式为"课程名称\专题名称\课题名称""课程名称\课题名称"
</div>
<!-- ==================== 6. 数据表格区域 ==================== -->
<el-card shadow="never" class="table-card">
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="40" align="center" />
<el-table-column prop="manage" label="管理" width="70" align="center" />
<el-table-column prop="code" label="编码" width="100" show-overflow-tooltip />
<el-table-column prop="name" label="课程名称" min-width="130" show-overflow-tooltip />
<el-table-column prop="cat" label="分类" width="100" align="center" />
<el-table-column prop="exam" label="考核类型方式" width="110" align="center" />
<el-table-column prop="inClass" label="课内学时" width="90" align="center" />
<el-table-column prop="outClass" label="课外学时" width="90" align="center" />
<el-table-column prop="other" label="其他" width="80" align="center" />
<el-table-column prop="textbook" label="教材" min-width="120" show-overflow-tooltip />
<el-table-column prop="majors" label="开设课程专业名称" min-width="150" show-overflow-tooltip />
<el-table-column prop="teacher" label="在职主讲教员" min-width="110" show-overflow-tooltip />
</el-table>
<el-pagination
:current-page="pageNum"
:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
class="pagination-wrapper"
@current-change="handlePageChange"
@size-change="handleSizeChange"
/>
</el-card>
<!-- 新增/编辑课程科目弹窗 -->
<el-dialog
:visible="dialogVisible"
:title="dialogTitle"
width="1100px"
:close-on-click-modal="false"
class="add-dialog"
@update:visible="val => dialogVisible = val"
>
<el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="120px" class="add-form" :status-icon="false">
<el-row :gutter="24">
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="编号" prop="bh">
<el-input v-model="addForm.bh" placeholder="请输入编号" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="课标号" prop="kbh">
<el-input v-model="addForm.kbh" placeholder="请输入课标号" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="课程名称" prop="mc">
<el-input v-model="addForm.mc" placeholder="请输入课程名称" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="适用专业" prop="syzy">
<el-input v-model="addForm.syzy" placeholder="请输入适用专业" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="课时数" prop="kcs">
<el-input-number v-model="addForm.kcs" :min="0" controls-position="right" class="w-full" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="录入人编号" prop="zxrbh">
<el-input v-model="addForm.zxrbh" placeholder="请输入录入人编号" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
<el-form-item label="录入时间">
<el-input v-model="addForm.zxsj" placeholder="请输入录入时间" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<el-form-item label="正文">
<el-input v-model="addForm.zw" type="textarea" :rows="3" placeholder="请输入正文" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<el-form-item label="备注">
<el-input v-model="addForm.bz" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
<div class="classroom-section">
<div class="classroom-header">
<span class="classroom-title">课堂列表</span>
<el-button type="primary" size="small" @click="handleAddClassroom">添加课堂</el-button>
</div>
<el-table :data="addForm.ktList" border size="small">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="课堂编号" width="140">
<template slot-scope="{ row }">
<el-input v-model="row.bh" placeholder="课堂编号" />
</template>
</el-table-column>
<el-table-column label="课堂次序" width="90">
<template slot-scope="{ row }">
<el-input-number v-model="row.ktjc" :min="1" controls-position="right" class="w-full" />
</template>
</el-table-column>
<el-table-column label="教学内容" min-width="150">
<template slot-scope="{ row }">
<el-input v-model="row.jxnr" placeholder="教学内容" />
</template>
</el-table-column>
<el-table-column label="教学要点" min-width="150">
<template slot-scope="{ row }">
<el-input v-model="row.jxyd" placeholder="教学要点" />
</template>
</el-table-column>
<el-table-column label="教学方法" min-width="150">
<template slot-scope="{ row }">
<el-input v-model="row.jxff" placeholder="教学方法" />
</template>
</el-table-column>
<el-table-column label="主讲教员数" width="100">
<template slot-scope="{ row }">
<el-input-number v-model="row.zjjys" :min="0" controls-position="right" class="w-full" />
</template>
</el-table-column>
<el-table-column label="辅讲教员数" width="100">
<template slot-scope="{ row }">
<el-input-number v-model="row.fjjys" :min="0" controls-position="right" class="w-full" />
</template>
</el-table-column>
<el-table-column label="教学目的" min-width="150">
<template slot-scope="{ row }">
<el-input v-model="row.jxmd" placeholder="教学目的" />
</template>
</el-table-column>
<el-table-column label="教学要求" min-width="150">
<template slot-scope="{ row }">
<el-input v-model="row.jxyq" placeholder="教学要求" />
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center" fixed="right">
<template slot-scope="{ $index }">
<el-button type="text" class="text-danger" @click="handleDeleteClassroom($index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-form>
<div slot="footer">
<div class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" :loading="addLoading" @click="handleSubmit">保存</el-button>
</div>
</div>
</el-dialog>
<!-- 撤回弹窗 -->
<el-dialog
:visible="withdrawDialogVisible"
title="撤回课程科目"
width="500px"
:close-on-click-modal="false"
@update:visible="val => withdrawDialogVisible = val"
>
<el-form :model="withdrawForm" label-width="100px">
<el-form-item label="课程编号">
<el-input v-model="withdrawForm.bh" disabled />
</el-form-item>
<el-form-item label="撤回原因">
<el-input v-model="withdrawForm.chyy" type="textarea" :rows="4" placeholder="请输入撤回原因" />
</el-form-item>
</el-form>
<div slot="footer">
<div class="dialog-footer">
<el-button @click="handleCancelWithdraw">取消</el-button>
<el-button type="primary" :loading="withdrawLoading" @click="handleWithdraw">确定撤回</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'SubjectIndex',
data() {
return {
// ==================== 1. 顶部状态提示 ====================
statusTip: '请输入查询条件',
// ==================== 下拉选项 ====================
zcfsOptions: ['其他', '讲授', '研讨', '实操'],
khlxOptions: ['讲座', '考试', '考查', '实操'],
mmdjOptions: ['公开', '内部', '秘密', '机密'],
jysOptions: ['未确定教研室', '军事基础教研室', '政治工作教研室', '装备保障教研室'],
pxccOptions: ['无', '本科', '硕士', '博士'],
pxlxOptions: ['军官基础教育', '士兵职业教育', '研究生教育', '其他'],
kclxOptions: ['其他类', '公共基础', '专业基础', '专业核心'],
jsfsOptions: ['其他', '自建', '共建', '引进'],
pjqkOptions: ['无', '国家级', '军队级', '院校级'],
gljgOptions: ['教务处', '教研室1', '教研室2'],
// ==================== 2. 查询条件 ====================
searchForm: {
kcbh: '',
jc: '',
xfMin: '',
xfMax: '',
xsMin: '',
xsMax: '',
zcfsEnabled: false,
zcfs: '其他',
khlxEnabled: false,
khlx: '讲座',
mmdj: '',
dgxzEnabled: false,
dgxz: '大纲课程',
zzglEnabled: false,
zzgl: '政治类',
bz: '',
jysEnabled: false,
jys: '未确定教研室',
pxccEnabled: false,
pxcc: '无',
pxlxEnabled: false,
pxlx: '军官基础教育',
kclxEnabled: false,
kclx: '其他类',
jsfsEnabled: false,
jsfs: '其他',
pjqkEnabled: false,
pjqk: '无',
gljgEnabled: false,
gljg: '教务处',
zyxzEnabled: true,
zyxz: '在用',
bbxxEnabled: true,
bbxx: '最新版本',
bmbhEnabled: false,
bmbh: '完全包含'
},
// ==================== 列表数据 ====================
/** 模拟列表数据(后端接口未提供) */
mockTableData: [
{ id: 1, manage: '编辑', code: 'KCB001', name: '高等数学', cat: '公共基础', exam: '考试', inClass: 48, outClass: 16, other: '—', textbook: '高等数学(上册)', majors: '炮兵装备运用/通信工程', teacher: '张三' },
{ id: 2, manage: '编辑', code: 'KCB002', name: '导弹发射原理', cat: '专业核心', exam: '考试', inClass: 40, outClass: 16, other: '—', textbook: '导弹发射原理', majors: '炮兵装备运用', teacher: '李四' },
{ id: 3, manage: '编辑', code: 'KCB003', name: '通信原理', cat: '专业核心', exam: '考试', inClass: 48, outClass: 16, other: '—', textbook: '通信原理', majors: '通信工程', teacher: '王五' },
{ id: 4, manage: '编辑', code: 'KCB004', name: '军事英语', cat: '公共基础', exam: '考查', inClass: 30, outClass: 8, other: '—', textbook: '军事英语教程', majors: '全军各专业', teacher: '赵六' },
{ id: 5, manage: '编辑', code: 'KCB005', name: '联合作战指挥', cat: '专业核心', exam: '综合考核', inClass: 40, outClass: 20, other: '—', textbook: '联合作战指挥', majors: '军事指挥', teacher: '孙七' },
{ id: 6, manage: '编辑', code: 'KCB006', name: '装备维修训练', cat: '实践环节', exam: '实操', inClass: 0, outClass: 48, other: '—', textbook: '装备维修手册', majors: '装备保障', teacher: '周八' }
],
loading: false,
tableData: [],
total: 0,
pageNum: 1,
pageSize: 20,
selectedRows: [],
// ==================== 文件上传 ====================
selectedFile: null,
coverExist: false,
// ==================== 新增/编辑弹窗 ====================
dialogVisible: false,
addLoading: false,
editLoading: false,
isEdit: false,
addForm: this.createEmptyForm(),
rules: {
bh: [{ required: true, message: '请输入编号', trigger: 'blur' }],
kbh: [{ required: true, message: '请输入课标号', trigger: 'blur' }],
mc: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
syzy: [{ required: true, message: '请输入适用专业', trigger: 'blur' }],
kcs: [{ required: true, message: '请输入课时数', trigger: 'blur' }],
zxrbh: [{ required: true, message: '请输入录入人编号', trigger: 'blur' }]
},
// ==================== 撤回弹窗 ====================
withdrawDialogVisible: false,
withdrawLoading: false,
withdrawForm: { bh: '', chyy: '' }
}
},
computed: {
dialogTitle() {
return this.isEdit ? '编辑课程科目' : '新增课程科目'
},
fileName() {
return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'
}
},
created() {
// 初始化表单(保证 getCurrentTime 可用)
this.addForm = this.createEmptyForm()
},
mounted() {
this.fetchList()
},
methods: {
// ==================== 表单辅助 ====================
getCurrentTime() {
return new Date().toLocaleString('zh-CN', { hour12: false }).replace(/\//g, '-')
},
/** 创建空白课程表单(含一条空课堂记录) */
createEmptyForm() {
return {
bh: '', kbh: '', mc: '', syzy: '', kcs: 0, bz: '', zxrbh: '', zxsj: this.getCurrentTime(),
zxzt: '0', sbzt: '0', sbsj: '', sbrbh: '', chyy: '', zw: '', jsonzd: '', ktList: [this.defaultClassroom()]
}
},
/** 默认课堂项 */
defaultClassroom() {
return { bh: '', ktjc: 1, jxnr: '', jxyd: '', jxff: '', zjjys: 0, fjjys: 0, bz: '', jxmd: '', jxyq: '' }
},
resetForm() {
this.addForm = this.createEmptyForm()
},
// ==================== 列表加载 ====================
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getCourseTeachingList
fetchList() {
this.loading = true
setTimeout(() => {
this.tableData = [...this.mockTableData]
this.total = this.mockTableData.length
this.loading = false
}, 200)
},
// ==================== 查询 ====================
handleQuery() {
const now = new Date()
const hh = String(now.getHours()).padStart(2, '0')
const mm = String(now.getMinutes()).padStart(2, '0')
const ss = String(now.getSeconds()).padStart(2, '0')
this.statusTip = `[${hh}:${mm}:${ss}]查询成功!共检索到${this.total || 982}条记录。`
this.pageNum = 1
this.fetchList()
},
handlePageChange(current) {
this.pageNum = current
this.fetchList()
},
handleSizeChange(size) {
this.pageSize = size
this.pageNum = 1
this.fetchList()
},
handleSelectionChange(rows) {
this.selectedRows = rows
},
// ==================== 删除所选 ====================
handleBatchDelete() {
if (this.selectedRows.length === 0) {
this.$message.warning('请先选择要删除的记录')
return
}
const ids = this.selectedRows.map((r) => r.id)
this.tableData = this.tableData.filter((r) => ids.indexOf(r.id) === -1)
this.total = this.tableData.length
this.$message.success(`已删除所选 ${ids.length} 条记录(前端模拟)`)
},
// ==================== 下载 ====================
downloadBlob(content, filename) {
const blob = new Blob(['\ufeff' + content], { type: 'text/plain;charset=utf-8;' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = filename
link.click()
URL.revokeObjectURL(link.href)
},
handleDownloadCourse() {
this.downloadBlob('编码,课程名称,分类,考核类型方式,课内学时,课外学时\n', '课程科目基本信息.txt')
this.$message.success('课程科目基本信息已下载(前端模拟)')
},
handleDownloadTextbook() {
this.downloadBlob('课程名称,教材,在职主讲教员\n', '课程教材基本信息.txt')
this.$message.success('课程教材基本信息已下载(前端模拟)')
},
handleDownloadTemplate() {
this.downloadBlob('编码,课程名称,分类,考核类型方式,课内学时,课外学时,教材,开设课程专业名称,在职主讲教员\n', '课程科目数据文件模板.txt')
this.$message.success('【课程科目数据文件模板】已下载(前端模拟)')
},
// ==================== 文件上传 ====================
handleSelectFile() {
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
},
handleFileChange(e) {
const input = e.target
this.selectedFile = (input.files && input.files[0]) || null
},
handleUpload() {
if (!this.selectedFile) {
this.$message.warning('请先选择文件')
return
}
this.$message.success(`文件「${this.selectedFile.name}」上传成功(前端模拟)`)
},
// ==================== 新增/编辑弹窗 ====================
handleOpenDialog() {
this.isEdit = false
this.resetForm()
this.dialogVisible = true
},
handleAddClassroom() {
this.addForm.ktList.push(this.defaultClassroom())
},
handleDeleteClassroom(index) {
this.addForm.ktList.splice(index, 1)
},
// TODO: 后端接口未提供,保存成功后刷新列表为前端模拟;接口就绪后替换为 addCourseTeaching/updateCourseTeaching
handleSubmit() {
this.$refs.addFormRef.validate((valid) => {
if (!valid) return
this.addLoading = true
setTimeout(() => {
this.$message.success(this.isEdit ? '修改成功' : '保存成功')
this.dialogVisible = false
this.fetchList()
this.addLoading = false
}, 300)
})
},
handleCancel() {
this.dialogVisible = false
},
// ==================== 撤回弹窗 ====================
// TODO: 后端接口未提供,撤回为前端模拟;接口就绪后替换为 deleteCourseTeaching
handleWithdraw() {
if (!this.withdrawForm.chyy.trim()) {
this.$message.warning('请输入撤回原因')
return
}
this.withdrawLoading = true
setTimeout(() => {
this.$message.success('撤回成功')
this.withdrawDialogVisible = false
this.fetchList()
this.withdrawLoading = false
}, 300)
},
handleCancelWithdraw() {
this.withdrawDialogVisible = false
}
}
}
</script>
<style scoped lang="scss">
.app-container {
padding: 20px;
}
// ==================== 1. 顶部状态提示 ====================
.status-tip {
display: inline-block;
background: #dc3545;
color: #fff;
font-size: 12px;
padding: 3px 10px;
border-radius: 4px;
margin-bottom: 12px;
}
// ==================== 2. 查询条件区域 ====================
.search-card {
margin-bottom: 16px;
.query-field {
display: flex;
align-items: center;
margin-bottom: 14px;
min-height: 32px;
::v-deep(.el-checkbox) {
margin-right: 6px;
flex-shrink: 0;
}
.q-label {
width: 120px;
flex-shrink: 0;
font-size: 13px;
color: #303133;
text-align: right;
margin-right: 10px;
white-space: nowrap;
&.no-check {
margin-left: 24px;
}
}
.q-control {
flex: 1;
min-width: 0;
}
.range-control {
display: flex;
align-items: center;
gap: 6px;
.el-input {
flex: 1;
}
.range-sep {
flex-shrink: 0;
font-size: 12px;
color: #606266;
}
}
}
.notice {
font-size: 12px;
color: #f56c6c;
margin-top: 8px;
text-align: left;
}
.query-footer {
display: flex;
justify-content: flex-end;
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid #ebeef5;
}
}
// ==================== 3. 操作按钮区域 ====================
.action-card {
margin-bottom: 16px;
.action-row {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 12px;
&:last-child {
margin-bottom: 0;
}
}
}
// ==================== 4. 文件上传区域 ====================
.upload-card {
margin-bottom: 16px;
.upload-row {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
.upload-left {
display: flex;
align-items: center;
gap: 12px;
.file-name {
font-size: 12px;
color: #999;
&.has-file {
color: #303133;
}
}
}
.upload-right {
display: flex;
align-items: center;
gap: 12px;
}
}
}
// ==================== 5. 红色提示文字 ====================
.red-tip {
font-size: 14px;
color: #f56c6c;
margin-bottom: 16px;
line-height: 1.6;
}
// ==================== 6. 数据表格区域 ====================
.table-card {
.pagination-wrapper {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
::v-deep(.el-table .cell) {
font-size: 12px;
}
}
// ==================== 新增/编辑弹窗 ====================
.add-dialog {
::v-deep(.el-dialog__body) {
max-height: 70vh;
overflow: auto;
}
}
.add-form {
.w-full {
width: 100%;
}
.classroom-section {
margin-top: 16px;
.classroom-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
.classroom-title {
font-size: 15px;
font-weight: 600;
color: #303133;
}
}
}
// 课堂列表删除按钮红色文字
.text-danger {
color: #f56c6c;
padding: 0;
}
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
.gray-btn {
height: 28px;
padding: 2px 16px;
font-size: 12px;
background: #f5f5f5;
border: 1px solid #c0c4cc;
color: #333;
border-radius: 2px;
&:hover,
&:focus {
background: #ebebeb;
border-color: #c0c4cc;
color: #333;
}
}
</style>