876 lines
33 KiB
Vue
876 lines
33 KiB
Vue
<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>
|