forked from liweijie/education
前端文件
This commit is contained in:
@@ -0,0 +1,603 @@
|
||||
<template>
|
||||
<div class="app-container management-page elective-page">
|
||||
<!-- ==================== 2. 查询条件区域 ==================== -->
|
||||
<div class="section-card query-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2 class="section-title">筛选条件</h2>
|
||||
<p class="section-description">按课程、班次、教员及状态筛选选修课</p>
|
||||
</div>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
<el-form>
|
||||
<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.js" placeholder="请输入授课教员" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">可选班次年级</span>
|
||||
<el-input v-model="searchForm.kbcnj" placeholder="请输入可选班次年级" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">选修课状态</span>
|
||||
<el-select
|
||||
v-model="searchForm.xxkzt"
|
||||
placeholder="请选择选修课状态"
|
||||
clearable
|
||||
class="q-control"
|
||||
>
|
||||
<el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">课程科目名称</span>
|
||||
<el-input v-model="searchForm.kckmmc" placeholder="请输入课程科目名称" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">选修班名称</span>
|
||||
<el-input v-model="searchForm.xxbmc" placeholder="请输入选修班名称" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">培训层次</span>
|
||||
<el-select v-model="searchForm.pxcc" placeholder="请选择培训层次" clearable class="q-control">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 导出按钮区域 ==================== -->
|
||||
<div class="section-card export-card">
|
||||
<div class="section-heading section-heading--compact">
|
||||
<div>
|
||||
<h2 class="section-title">数据导出</h2>
|
||||
<p class="section-description">下载选修班及学员名单</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="export-bar">
|
||||
<el-button icon="el-icon-download" @click="handleDownloadList">下载选修班列表</el-button>
|
||||
<el-button icon="el-icon-download" @click="handleDownloadWord">下载选修班学员名单Word</el-button>
|
||||
<el-button icon="el-icon-download" @click="handleDownloadExcel">下载选修班学员名单Excel</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 4. 操作按钮区域 ==================== -->
|
||||
<div class="section-card action-card">
|
||||
<div class="section-heading section-heading--compact">
|
||||
<div>
|
||||
<h2 class="section-title">选修课操作</h2>
|
||||
<p class="section-description">新建选修课,或对已选数据执行批量操作</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleOpenNew">新建选修课</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-circle-check" @click="handleOpenEarly">
|
||||
所选批量开放报名
|
||||
</el-button>
|
||||
<el-button type="warning" plain icon="el-icon-remove-outline" @click="handleCancelEarly">
|
||||
所选批量取消开放报名
|
||||
</el-button>
|
||||
<el-button type="danger" plain icon="el-icon-circle-close" @click="handleStopSignup">
|
||||
批量停止报名
|
||||
</el-button>
|
||||
<!-- <el-button icon="el-icon-refresh" @click="handleReverseRange">
|
||||
所选批量根据学员反向确定班次范围
|
||||
</el-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 5. 文件上传区域 ==================== -->
|
||||
<div class="section-card upload-card">
|
||||
<div class="section-heading section-heading--compact">
|
||||
<div>
|
||||
<h2 class="section-title">数据导入</h2>
|
||||
<p class="section-description">选择填写完成的模板文件并上传</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-row">
|
||||
<div class="upload-left">
|
||||
<el-button icon="el-icon-folder-opened" @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-button type="primary" icon="el-icon-upload2" @click="handleUpload">上传数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 6. 数据表格区域 ==================== -->
|
||||
<div class="section-card table-card">
|
||||
<div class="section-heading section-heading--compact table-heading">
|
||||
<div>
|
||||
<h2 class="section-title">选修课列表</h2>
|
||||
<p class="section-description">共 {{ total }} 条数据</p>
|
||||
</div>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" border stripe class="main-table" @selection-change="handleSelectionChange">
|
||||
<template slot="empty">
|
||||
<span>无数据!</span>
|
||||
</template>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" :index="tableIndex" />
|
||||
<el-table-column prop="kmc" label="课程" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="jcmc" label="教材" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="jyxm" label="实施教员" width="90" align="center" />
|
||||
<el-table-column prop="jsmc" label="教学场地" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="kxdlbc" label="显示可选队别班次" min-width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="计划学时/运行学时/学分" width="130" align="center">
|
||||
<template slot="header">
|
||||
<div class="triple-header">
|
||||
<span>计划学时</span>
|
||||
<span>运行学时</span>
|
||||
<span>学分</span>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="{ row }">
|
||||
<div class="triple-cell">
|
||||
<span>{{ row.jhyxxsxf }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开课结课日期" min-width="150" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
{{ row.kkjkrq }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报名日期" min-width="140" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
{{ row.bmrq }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jhrs" label="计划人数" width="90" align="center" />
|
||||
<el-table-column prop="yqsm" label="要求说明" min-width="120" show-overflow-tooltip />
|
||||
</el-table>
|
||||
|
||||
<div class="pagination-wrap">
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
:page-size="pageSize"
|
||||
:current-page="currentPage"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 新建选修课弹窗 -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="新建选修课"
|
||||
width="560px"
|
||||
@update:visible="val => (dialogVisible = val)"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
|
||||
<el-form-item label="选修班名称" prop="xxbmc">
|
||||
<el-input v-model="form.xxbmc" placeholder="请输入选修班名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="年级">
|
||||
<el-input v-model="form.nj" placeholder="新建选修班时填写,如 2024" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="课程名称" prop="kcmc">
|
||||
<el-input v-model="form.kcmc" placeholder="请输入课程名称,提交时按名称查找课编号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="实施教员" prop="js">
|
||||
<el-input v-model="form.js" placeholder="请输入实施教员,提交时按名称查找教员编号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="教材">
|
||||
<el-input v-model="form.jc" placeholder="请输入教材" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="教学场地">
|
||||
<el-input v-model="form.jxcd" placeholder="请输入教学场地,提交时按名称查找教室编号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="计划学时">
|
||||
<el-input-number v-model="form.jhsxs" :min="0" :precision="0" class="w-full" />
|
||||
</el-form-item>
|
||||
<el-form-item label="运行学时">
|
||||
<el-input-number v-model="form.yxsxs" :min="0" :precision="0" class="w-full" />
|
||||
</el-form-item>
|
||||
<el-form-item label="学分">
|
||||
<el-input-number v-model="form.xf" :min="0" :precision="1" class="w-full" />
|
||||
</el-form-item>
|
||||
<el-form-item label="计划人数">
|
||||
<el-input-number v-model="form.jh" :min="0" :precision="0" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleNewConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listElective,
|
||||
addElective,
|
||||
batchOpenElective,
|
||||
batchCancelOpenElective,
|
||||
batchStopElective,
|
||||
exportElectiveList,
|
||||
exportElectiveStudentsExcel,
|
||||
exportElectiveStudentsWord
|
||||
} from '@/api/teachOffice/elective'
|
||||
import { listKb } from '@/api/teachOffice/kb'
|
||||
import { listTeacher } from '@/api/teachOffice/teacher'
|
||||
import { listClassroom } from '@/api/teachBusiness/classroom'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
export default {
|
||||
name: 'Elective',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 下拉选项 ====================
|
||||
statusOptions: ['拟制', '开放报名', '停止报名', '已开课'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
|
||||
// ==================== 查询条件 ====================
|
||||
searchForm: {
|
||||
js: '',
|
||||
kbcnj: '',
|
||||
xxkzt: '',
|
||||
kckmmc: '',
|
||||
xxbmc: '',
|
||||
pxcc: ''
|
||||
},
|
||||
|
||||
// ==================== 数据表格 ====================
|
||||
tableData: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
selectedRows: [],
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
selectedFile: null,
|
||||
|
||||
// ==================== 新建选修课弹窗 ====================
|
||||
dialogVisible: false,
|
||||
form: {
|
||||
xxbmc: '',
|
||||
nj: '',
|
||||
kcmc: '',
|
||||
js: '',
|
||||
jc: '',
|
||||
jxcd: '',
|
||||
jhsxs: 0,
|
||||
yxsxs: 0,
|
||||
xf: 0,
|
||||
jh: 0
|
||||
},
|
||||
rules: {
|
||||
xxbmc: [{ required: true, message: '请输入选修班名称', trigger: 'blur' }],
|
||||
kcmc: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
|
||||
js: [{ required: true, message: '请输入实施教员', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// ==================== 分页 ====================
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fileName() {
|
||||
return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadList()
|
||||
},
|
||||
methods: {
|
||||
// 组装查询过滤条件(列表与导出共用,导出不含分页参数)
|
||||
buildFilter() {
|
||||
const q = {}
|
||||
if (this.searchForm.js) q.jyxm = this.searchForm.js
|
||||
if (this.searchForm.kbcnj) q.kxbcnj = this.searchForm.kbcnj
|
||||
if (this.searchForm.kckmmc) q.kmc = this.searchForm.kckmmc
|
||||
if (this.searchForm.xxbmc) q.xxbmc = this.searchForm.xxbmc
|
||||
if (this.searchForm.xxkzt) q.xkzt = this.searchForm.xxkzt
|
||||
if (this.searchForm.pxcc) q.pxcc = this.searchForm.pxcc
|
||||
return q
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
handleQuery() {
|
||||
this.currentPage = 1
|
||||
this.loadList()
|
||||
},
|
||||
loadList() {
|
||||
this.loading = true
|
||||
const params = Object.assign({ pageNum: this.currentPage, pageSize: this.pageSize }, this.buildFilter())
|
||||
listElective(params)
|
||||
.then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 导出 ====================
|
||||
handleDownloadList() {
|
||||
exportElectiveList(this.buildFilter())
|
||||
.then(blob => {
|
||||
saveAs(blob, '选修班列表.xlsx')
|
||||
this.$message.success('选修班列表已下载')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
handleDownloadWord() {
|
||||
const bhList = this.selectedRows.map(row => row.bh)
|
||||
if (bhList.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
exportElectiveStudentsWord(bhList)
|
||||
.then(blob => {
|
||||
saveAs(blob, '选修班学员名单.docx')
|
||||
this.$message.success('选修班学员名单Word已下载')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
handleDownloadExcel() {
|
||||
const bhList = this.selectedRows.map(row => row.bh)
|
||||
if (bhList.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
exportElectiveStudentsExcel(bhList)
|
||||
.then(blob => {
|
||||
saveAs(blob, '选修班学员名单.xlsx')
|
||||
this.$message.success('选修班学员名单Excel已下载')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 操作按钮 ====================
|
||||
handleOpenEarly() {
|
||||
const bhList = this.selectedRows.map(row => row.bh)
|
||||
if (bhList.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
batchOpenElective(bhList)
|
||||
.then(() => {
|
||||
this.$message.success('所选班已开放报名')
|
||||
this.loadList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
handleCancelEarly() {
|
||||
const bhList = this.selectedRows.map(row => row.bh)
|
||||
if (bhList.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
batchCancelOpenElective(bhList)
|
||||
.then(() => {
|
||||
this.$message.success('所选班已取消开放报名')
|
||||
this.loadList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
handleStopSignup() {
|
||||
const bhList = this.selectedRows.map(row => row.bh)
|
||||
if (bhList.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
batchStopElective(bhList)
|
||||
.then(() => {
|
||||
this.$message.success('已批量停止报名')
|
||||
this.loadList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
handleReverseRange() {
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
handleSelectFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
handleFileChange(e) {
|
||||
this.selectedFile = e.target.files[0] || null
|
||||
},
|
||||
handleUpload() {
|
||||
if (!this.selectedFile) {
|
||||
this.$message.warning('请先选择文件')
|
||||
return
|
||||
}
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
// ==================== 表格多选 ====================
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
|
||||
// ==================== 新建选修课弹窗 ====================
|
||||
handleOpenNew() {
|
||||
this.form = {
|
||||
xxbmc: '',
|
||||
nj: '',
|
||||
kcmc: '',
|
||||
js: '',
|
||||
jc: '',
|
||||
jxcd: '',
|
||||
jhsxs: 0,
|
||||
yxsxs: 0,
|
||||
xf: 0,
|
||||
jh: 0
|
||||
}
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
handleNewConfirm() {
|
||||
if (!this.$refs.formRef) return
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.submitNewElective()
|
||||
})
|
||||
},
|
||||
submitNewElective() {
|
||||
const emptyPage = { data: { records: [] } }
|
||||
Promise.all([
|
||||
listKb({ pageNum: 1, pageSize: 1, kmc: this.form.kcmc }),
|
||||
listTeacher({ pageNum: 1, pageSize: 1, jyxm: this.form.js }),
|
||||
this.form.jxcd ? listClassroom({ pageNum: 1, pageSize: 1, jsmc: this.form.jxcd }) : Promise.resolve(emptyPage)
|
||||
])
|
||||
.then(([kbRes, teacherRes, roomRes]) => {
|
||||
const kbh = kbRes?.data?.records?.[0]?.kbh
|
||||
const jybh = teacherRes?.data?.records?.[0]?.jybh
|
||||
const jsbh = roomRes?.data?.records?.[0]?.jsbh
|
||||
if (!kbh) {
|
||||
this.$message.warning(`未找到课程科目:${this.form.kcmc}`)
|
||||
return
|
||||
}
|
||||
const dto = {
|
||||
kbh: kbh,
|
||||
xxbmc: this.form.xxbmc,
|
||||
nj: this.form.nj || undefined,
|
||||
jybh: jybh || undefined,
|
||||
jsbh: jsbh || undefined,
|
||||
rs: this.form.jh || undefined,
|
||||
xs: this.form.jhsxs || undefined,
|
||||
xf: this.form.xf || undefined
|
||||
}
|
||||
return addElective(dto).then(() => {
|
||||
this.$message.success('新建选修课成功')
|
||||
this.dialogVisible = false
|
||||
this.loadList()
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 分页 ====================
|
||||
handlePageChange(page) {
|
||||
this.currentPage = page
|
||||
this.loadList()
|
||||
},
|
||||
|
||||
// 表格序号(跨页连续)
|
||||
tableIndex(index) {
|
||||
return (this.currentPage - 1) * this.pageSize + index + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// ==================== 2. 查询条件区域 ====================
|
||||
.query-card {
|
||||
.query-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
min-height: 32px;
|
||||
|
||||
.q-label {
|
||||
width: 120px;
|
||||
flex-shrink: 0;
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.q-control {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.export-bar {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// ==================== 4. 操作按钮区域 ====================
|
||||
.action-card {
|
||||
.action-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 5. 文件上传区域 ====================
|
||||
.upload-card {
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 6. 数据表格区域 ====================
|
||||
.table-card {
|
||||
.main-table {
|
||||
::v-deep .cell {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.triple-header,
|
||||
.triple-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.pagination-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,364 @@
|
||||
<template>
|
||||
<div class="app-container teach-office">
|
||||
<!-- 查询条件区域 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="88px" v-show="showSearch">
|
||||
<el-form-item label="教研室代号" prop="jysdh">
|
||||
<el-input
|
||||
v-model="queryParams.jysdh"
|
||||
placeholder="请输入教研室代号"
|
||||
clearable
|
||||
style="width: 160px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="教研室名称" prop="jysmc">
|
||||
<el-input
|
||||
v-model="queryParams.jysmc"
|
||||
placeholder="请输入教研室名称"
|
||||
clearable
|
||||
style="width: 180px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="部系" prop="bx">
|
||||
<el-input
|
||||
v-model="queryParams.bx"
|
||||
placeholder="请输入部系"
|
||||
clearable
|
||||
style="width: 160px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="停用" prop="ty">
|
||||
<el-radio-group v-model="queryParams.ty">
|
||||
<el-radio :label="1">是</el-radio>
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="openImport">导入</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleDownloadTemplate">模板下载</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据列表区域 -->
|
||||
<el-table v-loading="loading" :data="officeList" border :height="tableHeight">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="教研室代号" align="center" prop="jysdh" min-width="110" />
|
||||
<el-table-column label="教研室名称" align="center" prop="jysmc" min-width="160" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="简称" align="center" prop="jc" min-width="90" />
|
||||
<el-table-column label="部系" align="center" prop="bx" min-width="100" />
|
||||
<el-table-column label="机关性质" align="center" min-width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.jgxz ? 'primary' : 'info'" size="mini">{{ scope.row.jgxz ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="停用" align="center" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.ty ? 'danger' : 'success'" size="mini">{{ scope.row.ty ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="bz" min-width="120" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" align="center" min-width="140" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-circle-close"
|
||||
style="color: #f56c6c"
|
||||
:disabled="scope.row.ty === 1"
|
||||
@click="handleDisable(scope.row)"
|
||||
>停用</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="教研室代号" prop="jysdh">
|
||||
<el-input v-model="form.jysdh" placeholder="请输入教研室代号" :disabled="!isAdd" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="教研室名称" prop="jysmc">
|
||||
<el-input v-model="form.jysmc" placeholder="请输入教研室名称" maxlength="50" />
|
||||
</el-form-item>
|
||||
<el-form-item label="简称" prop="jc">
|
||||
<el-input v-model="form.jc" placeholder="请输入简称" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="部系" prop="bx">
|
||||
<el-input v-model="form.bx" placeholder="请输入部系" maxlength="30" />
|
||||
</el-form-item>
|
||||
<el-form-item label="序号" prop="xh">
|
||||
<el-input v-model="form.xh" placeholder="请输入序号" maxlength="10" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="bz">
|
||||
<el-input v-model="form.bz" type="textarea" placeholder="请输入备注" :rows="3" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入对话框 -->
|
||||
<el-dialog title="教研室数据导入" :visible.sync="importOpen" width="420px" append-to-body>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:action="importUrl"
|
||||
:headers="uploadHeaders"
|
||||
:on-success="handleImportSuccess"
|
||||
:on-error="handleImportError"
|
||||
:limit="1"
|
||||
:before-upload="beforeImport"
|
||||
accept=".xls, .xlsx"
|
||||
drag
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<div class="el-upload__tip text-center" slot="tip">
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitImport">确 定</el-button>
|
||||
<el-button @click="importOpen = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOffice, addOffice, updateOffice, disableOffice, downloadOfficeTemplate } from "@/api/teachOffice/office"
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
export default {
|
||||
name: "Office",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 表格高度
|
||||
tableHeight: window.innerHeight - 280,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 教研室列表数据
|
||||
officeList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示新增/编辑弹出层
|
||||
open: false,
|
||||
// 是否新增(false 为编辑)
|
||||
isAdd: true,
|
||||
// 是否显示导入弹出层
|
||||
importOpen: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
jysdh: undefined,
|
||||
jysmc: undefined,
|
||||
bx: undefined,
|
||||
ty: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
jysdh: [
|
||||
{ required: true, message: "教研室代号不能为空", trigger: "blur" }
|
||||
],
|
||||
jysmc: [
|
||||
{ required: true, message: "教研室名称不能为空", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
importUrl() {
|
||||
return process.env.VUE_APP_BASE_API + '/jys/office/import'
|
||||
},
|
||||
uploadHeaders() {
|
||||
return { Authorization: 'Bearer ' + getToken() }
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
/** 查询教研室列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listOffice(this.queryParams).then(response => {
|
||||
// 后端返回 MyBatis-Plus 分页结构:data.records / data.total
|
||||
const data = response.data || {}
|
||||
this.officeList = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.officeList = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 查询按钮 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm")
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.isAdd = true
|
||||
this.open = true
|
||||
this.title = "新增教研室"
|
||||
},
|
||||
/** 编辑按钮 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
this.isAdd = false
|
||||
// 编辑:jysdh 必传
|
||||
this.form = {
|
||||
jysdh: row.jysdh,
|
||||
jysmc: row.jysmc,
|
||||
jc: row.jc,
|
||||
bx: row.bx,
|
||||
xh: row.xh,
|
||||
bz: row.bz
|
||||
}
|
||||
this.open = true
|
||||
this.title = "编辑教研室"
|
||||
},
|
||||
/** 停用按钮 */
|
||||
handleDisable(row) {
|
||||
const jysdh = row.jysdh
|
||||
this.$modal.confirm('确认停用教研室【' + row.jysmc + '】吗?').then(() => {
|
||||
return disableOffice(jysdh)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess("停用成功")
|
||||
}).catch(() => {})
|
||||
},
|
||||
/** 提交表单 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.isAdd) {
|
||||
addOffice(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功")
|
||||
this.open = false
|
||||
this.getList()
|
||||
}).catch(() => {})
|
||||
} else {
|
||||
updateOffice(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功")
|
||||
this.open = false
|
||||
this.getList()
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 重置表单 */
|
||||
reset() {
|
||||
this.form = {
|
||||
jysdh: undefined,
|
||||
jysmc: undefined,
|
||||
jc: undefined,
|
||||
bx: undefined,
|
||||
xh: undefined,
|
||||
bz: undefined
|
||||
}
|
||||
this.resetForm("form")
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
/** 打开导入对话框 */
|
||||
openImport() {
|
||||
this.importOpen = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.uploadRef) {
|
||||
this.$refs.uploadRef.clearFiles()
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 导入前校验文件格式 */
|
||||
beforeImport(file) {
|
||||
const name = file.name.toLowerCase()
|
||||
if (!name.endsWith('.xls') && !name.endsWith('.xlsx')) {
|
||||
this.$modal.msgError('仅支持 xls、xlsx 格式文件')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
/** 提交导入 */
|
||||
submitImport() {
|
||||
const files = this.$refs.uploadRef.uploadFiles
|
||||
if (!files || files.length === 0) {
|
||||
this.$modal.msgError('请选择要导入的文件')
|
||||
return
|
||||
}
|
||||
this.$refs.uploadRef.submit()
|
||||
},
|
||||
/** 导入成功 */
|
||||
handleImportSuccess(response) {
|
||||
this.importOpen = false
|
||||
this.$alert("<div style='overflow:auto;overflow-x:hidden;max-height:70vh;padding:10px 20px 0;'>" + response.msg + '</div>', '导入结果', { dangerouslyUseHTMLString: true })
|
||||
this.getList()
|
||||
},
|
||||
/** 导入失败 */
|
||||
handleImportError() {
|
||||
this.$modal.msgError('导入失败,请稍后重试')
|
||||
},
|
||||
/** 下载导入模板 */
|
||||
handleDownloadTemplate() {
|
||||
downloadOfficeTemplate().then(blob => {
|
||||
saveAs(blob, '教研室导入模板.xlsx')
|
||||
this.$modal.msgSuccess('模板下载成功')
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.teach-office {
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,752 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="`班历管理——${semesterTitle}`"
|
||||
width="1200px"
|
||||
top="6vh"
|
||||
:close-on-click-modal="false"
|
||||
class="class-calendar-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<div v-loading="loading" class="class-calendar">
|
||||
<!-- ==================== 1. 学期与班次信息 ==================== -->
|
||||
<div class="info-panel">
|
||||
<div class="info-title-row">
|
||||
<span class="semester-name">{{ semesterTitle }}</span>
|
||||
<span class="class-name">{{ className }}</span>
|
||||
</div>
|
||||
<div class="date-range-row">
|
||||
<div class="range-item">学期日期:{{ fmtDate(safeSemester.kxrq) }} 至 {{ fmtDate(safeSemester.jsrq) }},共 {{ semesterWeeks }} 周</div>
|
||||
<div class="range-item">班历记录:{{ records.length }} 条,总学时 {{ summary.totalXs }},总学分 {{ summary.totalXf }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 2. 操作按钮区域 ==================== -->
|
||||
<div class="settings-panel">
|
||||
<div class="action-buttons-row">
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">新增记录</el-button>
|
||||
<el-button size="small" @click="handleAutoGenerate">自动生成必修课程</el-button>
|
||||
<el-button size="small" @click="handlePresetMerge">预设合班</el-button>
|
||||
<el-button size="small" @click="handlePresetSplit">预设拆班</el-button>
|
||||
<el-button size="small" @click="handleApplyRegion">选定区域应用于其它班次</el-button>
|
||||
<el-button size="small" @click="handleApplyWhole">整个班历应用于其它班次</el-button>
|
||||
<el-button size="small" icon="el-icon-refresh" @click="handleRefresh">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 班历记录表格 ==================== -->
|
||||
<div class="table-area">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="records"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
max-height="480"
|
||||
class="calendar-table"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="kcxh" label="课次序号" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jhkcxh" label="计划课次" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jc" label="简称" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="kbh" label="课编号" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="klx" label="课类型" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jybh" label="教员编号" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jsbh" label="教室编号" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zks" label="周课时" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xs" label="学时" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="llxs" label="理论学时" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="sjxs" label="实践学时" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xf" label="学分" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rs" label="人数" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="ksbh" label="考试编号" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="ksdd" label="考试地点" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="bz" label="备注" min-width="120" align="left" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="select-tip">
|
||||
提示:勾选多条记录后可进行 预设合班 / 预设拆班 / 选定区域应用于其它班次 操作;删除为物理删除,请谨慎操作。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 班历记录新增/编辑弹窗 ==================== -->
|
||||
<el-dialog
|
||||
:visible="editVisible"
|
||||
:title="editTitle"
|
||||
width="760px"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
@update:visible="val => editVisible = val"
|
||||
>
|
||||
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="120px" size="small" class="edit-form">
|
||||
<div class="form-section-title">基本信息</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="简称" prop="jc">
|
||||
<el-input v-model="editForm.jc" placeholder="课程简称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课编号">
|
||||
<el-input v-model="editForm.kbh" placeholder="课程编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课类型">
|
||||
<el-input v-model="editForm.klx" placeholder="如 必修/选修/实践" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课次序号">
|
||||
<el-input-number v-model="editForm.kcxh" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划课次序号">
|
||||
<el-input-number v-model="editForm.jhkcxh" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="序号标识">
|
||||
<el-input-number v-model="editForm.xhbs" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员编号">
|
||||
<el-input v-model="editForm.jybh" placeholder="教员编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教室编号">
|
||||
<el-input v-model="editForm.jsbh" placeholder="教室编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="人数">
|
||||
<el-input-number v-model="editForm.rs" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周课时">
|
||||
<el-input-number v-model="editForm.zks" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="form-section-title">学时学分</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学时">
|
||||
<el-input-number v-model="editForm.xs" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="理论学时">
|
||||
<el-input-number v-model="editForm.llxs" :min="0" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="实践学时">
|
||||
<el-input-number v-model="editForm.sjxs" :min="0" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学分">
|
||||
<el-input-number v-model="editForm.xf" :min="0" :precision="1" :step="0.5" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="form-section-title">考试信息</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试课时">
|
||||
<el-input-number v-model="editForm.ksks" :min="0" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试编号">
|
||||
<el-input v-model="editForm.ksbh" placeholder="考试编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试地点">
|
||||
<el-input v-model="editForm.ksdd" placeholder="考试地点" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="成绩分制">
|
||||
<el-input v-model="editForm.cjfz" placeholder="如 百分制/等级制" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="不计入平均分">
|
||||
<el-select v-model="editForm.bjrxypjf" clearable style="width: 100%">
|
||||
<el-option label="是" :value="1" />
|
||||
<el-option label="否" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试课时不显示">
|
||||
<el-select v-model="editForm.ksksbxs" clearable style="width: 100%">
|
||||
<el-option label="是" :value="1" />
|
||||
<el-option label="否" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="form-section-title">教研室计划</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教研室代号">
|
||||
<el-input v-model="editForm.jysdh" placeholder="教研室代号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划教员编号">
|
||||
<el-input v-model="editForm.jysjhjybh" placeholder="教研室计划教员编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="计划备注">
|
||||
<el-input v-model="editForm.jysjhbz" type="textarea" :rows="2" placeholder="教研室计划备注" clearable />
|
||||
</el-form-item>
|
||||
<div class="form-section-title">配档设置</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="配档序号">
|
||||
<el-input-number v-model="editForm.pdxh" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="配档起始周">
|
||||
<el-input-number v-model="editForm.pdqsz" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="配档按周">
|
||||
<el-input-number v-model="editForm.pdaz" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="占正课时间">
|
||||
<el-input-number v-model="editForm.pdzzksj" :min="0" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="配档编组">
|
||||
<el-input-number v-model="editForm.pdbz" :min="1" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="同班异课选修编组">
|
||||
<el-select v-model="editForm.pdtbykxxbz" clearable style="width: 100%">
|
||||
<el-option label="是" :value="1" />
|
||||
<el-option label="否" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="启用自定义学时">
|
||||
<el-select v-model="editForm.pdqyzdyxs" clearable style="width: 100%">
|
||||
<el-option label="是" :value="1" />
|
||||
<el-option label="否" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="编组">
|
||||
<el-input-number v-model="editForm.bz2" :min="0" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="自定义学时分布">
|
||||
<el-input v-model="editForm.pdzdyxsfbsj" type="textarea" :rows="2" placeholder="配档自定义学时分布数据" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="editForm.bz" type="textarea" :rows="2" placeholder="备注" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button size="small" @click="editVisible = false">取消</el-button>
|
||||
<el-button size="small" type="primary" :loading="saving" @click="handleEditSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 目标班次学期选取弹窗 ==================== -->
|
||||
<ClassTeamSelectDialog
|
||||
:visible="teamSelectVisible"
|
||||
:semester-list="semesterOptions"
|
||||
:exclude-bh="safeSemester.bh"
|
||||
:exclude-note="copyNote"
|
||||
@update:visible="val => teamSelectVisible = val"
|
||||
@confirm="handleTeamConfirm"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ClassTeamSelectDialog from './ClassTeamSelectDialog.vue'
|
||||
import {
|
||||
listClassCalendar,
|
||||
updateClassCalendar,
|
||||
batchCopyCalendar,
|
||||
batchCopyCalendarBySemester,
|
||||
addTeamTask,
|
||||
delTeamTask,
|
||||
batchPresetMerge,
|
||||
batchPresetSplit,
|
||||
autoGenerateRequiredCourses
|
||||
} from '@/api/studentRecords/classCalendar'
|
||||
|
||||
export default {
|
||||
name: 'ClassCalendarDialog',
|
||||
components: { ClassTeamSelectDialog },
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 选中的班次学期记录(含 bh/xydbh/xqdc/nd/xydmc/kxrq/jsrq) */
|
||||
semester: { type: Object, default: null },
|
||||
/** 可选的目标班次学期列表(已含班次名称的完整列表) */
|
||||
semesterOptions: { type: Array, default: () => [] }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
saving: false,
|
||||
records: [],
|
||||
selection: [],
|
||||
|
||||
// ==================== 新增/编辑 ====================
|
||||
editVisible: false,
|
||||
editMode: 'add',
|
||||
editForm: this.createEmptyEditForm(),
|
||||
editRules: {
|
||||
jc: [{ required: true, message: '请输入课程简称', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// ==================== 复制到其它班次 ====================
|
||||
teamSelectVisible: false,
|
||||
applyMode: 'region',
|
||||
copyNote: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
safeSemester() {
|
||||
return this.semester || {}
|
||||
},
|
||||
className() {
|
||||
const s = this.safeSemester
|
||||
return s.xydmc || s.xydbh || ''
|
||||
},
|
||||
semesterTitle() {
|
||||
const s = this.safeSemester
|
||||
const nd = s.nd !== undefined && s.nd !== null && s.nd !== '' ? `${s.nd}年` : ''
|
||||
const xq = this.xqdcLabel(s.xqdc)
|
||||
return `${nd}${xq}`
|
||||
},
|
||||
semesterWeeks() {
|
||||
const s = this.safeSemester
|
||||
if (!s.kxrq || !s.jsrq) return '-'
|
||||
const start = new Date(String(s.kxrq).slice(0, 10))
|
||||
const end = new Date(String(s.jsrq).slice(0, 10))
|
||||
const diff = Math.round((end - start) / (1000 * 60 * 60 * 24)) + 1
|
||||
return diff > 0 ? Math.ceil(diff / 7) : '-'
|
||||
},
|
||||
/** 班历统计:课程数 / 总学时 / 总学分 */
|
||||
summary() {
|
||||
const totalXs = this.records.reduce((sum, r) => sum + (Number(r.xs) || 0), 0)
|
||||
const totalXf = this.records.reduce((sum, r) => sum + (Number(r.xf) || 0), 0)
|
||||
return { totalXs, totalXf }
|
||||
},
|
||||
editTitle() {
|
||||
return this.editMode === 'edit' ? '编辑班历记录' : '新增班历记录'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.loadData()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 格式化 ---------- */
|
||||
fmtDate(val) {
|
||||
if (!val) return '-'
|
||||
return String(val).slice(0, 10)
|
||||
},
|
||||
xqdcLabel(val) {
|
||||
if (val === 1 || val === '1') return '第1学期'
|
||||
if (val === 2 || val === '2') return '第2学期'
|
||||
if (val === 3 || val === '3') return '第3学期'
|
||||
return val !== undefined && val !== null && val !== '' ? `第${val}学期` : '-'
|
||||
},
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
|
||||
/* ---------- 列表加载 ---------- */
|
||||
loadData() {
|
||||
const s = this.semester || {}
|
||||
if (!s.bh) return
|
||||
this.loading = true
|
||||
listClassCalendar(s.bh).then(res => {
|
||||
this.records = (res && res.data) || []
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.records = []
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleSelectionChange(rows) {
|
||||
this.selection = rows
|
||||
},
|
||||
|
||||
/* ---------- 新增 / 编辑 ---------- */
|
||||
createEmptyEditForm() {
|
||||
const s = this.semester || {}
|
||||
return {
|
||||
bh: '',
|
||||
nd: s.nd,
|
||||
xydbh: s.xydbh || '',
|
||||
xqdc: s.xqdc,
|
||||
xydxqbh: s.bh || '',
|
||||
jc: '',
|
||||
kbh: '',
|
||||
klx: '',
|
||||
kcxh: undefined,
|
||||
jhkcxh: undefined,
|
||||
xhbs: undefined,
|
||||
jybh: '',
|
||||
jsbh: '',
|
||||
rs: undefined,
|
||||
zks: undefined,
|
||||
xs: undefined,
|
||||
llxs: undefined,
|
||||
sjxs: undefined,
|
||||
xf: undefined,
|
||||
ksks: undefined,
|
||||
ksbh: '',
|
||||
ksdd: '',
|
||||
cjfz: '',
|
||||
bjrxypjf: undefined,
|
||||
ksksbxs: undefined,
|
||||
jysdh: '',
|
||||
jysjhjybh: '',
|
||||
jysjhbz: '',
|
||||
pdxh: undefined,
|
||||
pdqsz: undefined,
|
||||
pdaz: undefined,
|
||||
pdzzksj: undefined,
|
||||
pdbz: undefined,
|
||||
pdtbykxxbz: undefined,
|
||||
pdqyzdyxs: undefined,
|
||||
pdzdyxsfbsj: '',
|
||||
bz2: undefined,
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
|
||||
handleAdd() {
|
||||
this.editMode = 'add'
|
||||
this.editForm = this.createEmptyEditForm()
|
||||
this.editVisible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.editFormRef) this.$refs.editFormRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
this.editMode = 'edit'
|
||||
const s = this.semester || {}
|
||||
const form = this.createEmptyEditForm()
|
||||
Object.keys(form).forEach(key => {
|
||||
if (row[key] !== undefined && row[key] !== null) form[key] = row[key]
|
||||
})
|
||||
form.xydxqbh = s.bh || row.xydxqbh
|
||||
this.editForm = form
|
||||
this.editVisible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.editFormRef) this.$refs.editFormRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleEditSubmit() {
|
||||
this.$refs.editFormRef.validate(valid => {
|
||||
if (!valid) return
|
||||
const payload = this.cleanPayload({ ...this.editForm })
|
||||
const req = this.editMode === 'edit'
|
||||
? updateClassCalendar(payload)
|
||||
: addTeamTask(payload)
|
||||
this.saving = true
|
||||
req.then(() => {
|
||||
this.saving = false
|
||||
this.editVisible = false
|
||||
this.$message.success(this.editMode === 'edit' ? '班历记录已更新' : '班历记录已新增')
|
||||
this.loadData()
|
||||
}).catch(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 删除 ---------- */
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定删除该班历记录(${row.jc || row.bh})吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
delTeamTask(row.bh).then(() => {
|
||||
this.$message.success('已删除')
|
||||
this.loadData()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 自动生成必修课程 ---------- */
|
||||
handleAutoGenerate() {
|
||||
const s = this.semester || {}
|
||||
if (!s.xydbh || !s.xqdc) {
|
||||
this.$message.warning('当前班次学期缺少学员队编号或学期第次,无法自动生成')
|
||||
return
|
||||
}
|
||||
this.$confirm('将按专业教学计划自动生成该班次的必修课程(已存在的课程不会重复添加),是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
autoGenerateRequiredCourses(s.xydbh, s.xqdc).then(res => {
|
||||
const count = (res && res.data) || 0
|
||||
this.$message.success(`已自动生成 ${count} 门必修课程`)
|
||||
this.loadData()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 预设合班 / 拆班 ---------- */
|
||||
handlePresetMerge() {
|
||||
const bhs = this.selection.map(r => r.bh)
|
||||
if (!bhs.length) {
|
||||
this.$message.warning('请先勾选要合班的班历记录')
|
||||
return
|
||||
}
|
||||
this.$confirm(`将按年度为选中的 ${bhs.length} 条记录设置统一的课次序号,是否继续?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
batchPresetMerge(bhs).then(res => {
|
||||
const count = (res && res.data) || 0
|
||||
this.$message.success(`已完成 ${count} 条记录的预设合班`)
|
||||
this.loadData()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
handlePresetSplit() {
|
||||
const bhs = this.selection.map(r => r.bh)
|
||||
if (!bhs.length) {
|
||||
this.$message.warning('请先勾选要拆班的班历记录')
|
||||
return
|
||||
}
|
||||
this.$confirm(`将清空选中的 ${bhs.length} 条记录的课次序号,是否继续?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
batchPresetSplit(bhs).then(res => {
|
||||
const count = (res && res.data) || 0
|
||||
this.$message.success(`已完成 ${count} 条记录的预设拆班`)
|
||||
this.loadData()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 应用于其它班次 ---------- */
|
||||
handleApplyRegion() {
|
||||
const bhs = this.selection.map(r => r.bh)
|
||||
if (!bhs.length) {
|
||||
this.$message.warning('请先勾选要应用的班历记录(选定区域)')
|
||||
return
|
||||
}
|
||||
this.applyMode = 'region'
|
||||
this.copyNote = `将选中的 ${bhs.length} 条班历记录复制到所选班次`
|
||||
this.teamSelectVisible = true
|
||||
},
|
||||
|
||||
handleApplyWhole() {
|
||||
this.applyMode = 'whole'
|
||||
this.copyNote = '将整个班历复制到所选班次'
|
||||
this.teamSelectVisible = true
|
||||
},
|
||||
|
||||
handleTeamConfirm(targets) {
|
||||
if (!targets || !targets.length) return
|
||||
const targetBhList = targets.map(t => t.bh)
|
||||
if (this.applyMode === 'whole') {
|
||||
batchCopyCalendarBySemester({
|
||||
sourceXydxqbh: this.semester.bh,
|
||||
targetBhList: targetBhList
|
||||
}).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.$message.success(`已复制整个班历,共新增 ${data.count || 0} 条记录`)
|
||||
this.loadData()
|
||||
})
|
||||
} else {
|
||||
batchCopyCalendar({
|
||||
sourceBhList: this.selection.map(r => r.bh),
|
||||
targetBhList: targetBhList
|
||||
}).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.$message.success(`已复制选定区域,共新增 ${data.count || 0} 条记录`)
|
||||
this.loadData()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/* ---------- 刷新 ---------- */
|
||||
handleRefresh() {
|
||||
this.loadData()
|
||||
this.$message.success('已刷新班历')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.class-calendar {
|
||||
// ========== 1. 学期与班次信息 ==========
|
||||
.info-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 12px 20px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.info-title-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 20px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.semester-name,
|
||||
.class-name {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #1e6fff;
|
||||
}
|
||||
}
|
||||
|
||||
.date-range-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.range-item {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #1e6fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 2. 操作按钮区域 ==========
|
||||
.settings-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 12px 20px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.action-buttons-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 3. 表格区域 ==========
|
||||
.table-area {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
.select-tip {
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
border-top: 1px solid #ebeef5;
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 弹窗内表单分区标题 ==========
|
||||
.edit-form {
|
||||
.form-section-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin: 6px 0 10px;
|
||||
padding: 6px 10px;
|
||||
background: #f0f7ff;
|
||||
border-left: 3px solid #1e6fff;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="isEdit ? '编辑班次学期信息' : '教学班次学期信息明细'"
|
||||
width="620px"
|
||||
class="class-detail-dialog"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px" class="detail-form">
|
||||
<!-- 班次信息(只读展示) -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="班次">
|
||||
<el-input :value="form.xydmc || form.xydbh" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="班次编号">
|
||||
<el-input v-model="form.xydbh" :readonly="isEdit" :disabled="isEdit" placeholder="编辑模式不可修改" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-select v-model="form.nd" placeholder="请选择年度" filterable style="width: 100%">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="`${y}年`" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期第次" prop="xqdc">
|
||||
<el-select v-model="form.xqdc" placeholder="请选择学期" style="width: 100%">
|
||||
<el-option v-for="opt in levelOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开学日期" prop="kxrq">
|
||||
<el-date-picker v-model="form.kxrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束日期" prop="jsrq">
|
||||
<el-date-picker v-model="form.jsrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专用教室">
|
||||
<el-input v-model="form.zyjsbh" placeholder="请输入专用教室编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学任务">
|
||||
<el-select v-model="form.jxrwbh" clearable filterable placeholder="请选择教学任务" style="width: 100%">
|
||||
<el-option v-for="opt in taskOptions" :key="opt.bh" :label="opt.rwmc" :value="opt.bh" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="开放教员排课">
|
||||
<el-checkbox v-model="form.kfjypk">开放教员排课</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入备注" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ClassSemesterDetailDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 编辑模式:edit / add */
|
||||
mode: { type: String, default: 'add' },
|
||||
/** 编辑时的班次学期记录 */
|
||||
semester: { type: Object, default: null },
|
||||
/** 新增时选中的班次(学员队)信息 */
|
||||
teamInfo: { type: Object, default: null },
|
||||
/** 年度下拉 */
|
||||
yearOptions: { type: Array, default: () => [] },
|
||||
/** 教学任务下拉({ bh, rwmc }) */
|
||||
taskOptions: { type: Array, default: () => [] }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: this.createEmptyForm(),
|
||||
levelOptions: [
|
||||
{ label: '第1学期', value: 1 },
|
||||
{ label: '第2学期', value: 2 },
|
||||
{ label: '第3学期', value: 3 }
|
||||
],
|
||||
saving: false,
|
||||
rules: {
|
||||
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||
xqdc: [{ required: true, message: '请选择学期第次', trigger: 'change' }],
|
||||
kxrq: [{ required: true, message: '请选择开学日期', trigger: 'change' }],
|
||||
jsrq: [{ required: true, message: '请选择结束日期', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
isEdit() {
|
||||
return this.mode === 'edit'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (!val) return
|
||||
this.initForm()
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.formRef) this.$refs.formRef.clearValidate()
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
xydbh: '',
|
||||
xydmc: '',
|
||||
nd: undefined,
|
||||
xqdc: undefined,
|
||||
kxrq: '',
|
||||
jsrq: '',
|
||||
zyjsbh: '',
|
||||
jxrwbh: undefined,
|
||||
kfjypk: false,
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
/** 打开时按编辑/新增模式初始化表单 */
|
||||
initForm() {
|
||||
const form = this.createEmptyForm()
|
||||
if (this.isEdit && this.semester) {
|
||||
const row = this.semester
|
||||
form.bh = row.bh || ''
|
||||
form.xydbh = row.xydbh || ''
|
||||
form.xydmc = row.xydmc || ''
|
||||
form.nd = row.nd
|
||||
form.xqdc = row.xqdc
|
||||
form.kxrq = row.kxrq ? String(row.kxrq).slice(0, 10) : ''
|
||||
form.jsrq = row.jsrq ? String(row.jsrq).slice(0, 10) : ''
|
||||
form.zyjsbh = row.zyjsbh || ''
|
||||
form.jxrwbh = row.jxrwbh || undefined
|
||||
form.kfjypk = Number(row.kfjypk) === 1
|
||||
form.bz = row.bz || ''
|
||||
} else if (this.teamInfo) {
|
||||
form.xydbh = this.teamInfo.xydbh || ''
|
||||
form.xydmc = this.teamInfo.xydmc || ''
|
||||
// 默认取当前选中年度的第一学期,日期可后续修改
|
||||
form.nd = this.yearOptions[0]
|
||||
form.xqdc = 1
|
||||
}
|
||||
this.form = form
|
||||
},
|
||||
/** 移除空值(保留 0 等有效值) */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) return
|
||||
if (!this.form.xydbh) {
|
||||
this.$message.warning('缺少班次编号,无法保存')
|
||||
return
|
||||
}
|
||||
const payload = this.cleanPayload({
|
||||
bh: this.form.bh,
|
||||
xydbh: this.form.xydbh,
|
||||
nd: this.form.nd,
|
||||
xqdc: this.form.xqdc,
|
||||
kxrq: this.form.kxrq,
|
||||
jsrq: this.form.jsrq,
|
||||
zyjsbh: this.form.zyjsbh,
|
||||
jxrwbh: this.form.jxrwbh,
|
||||
kfjypk: this.form.kfjypk ? 1 : 0,
|
||||
bz: this.form.bz
|
||||
})
|
||||
this.$emit('submit', payload)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.class-detail-dialog {
|
||||
.detail-form {
|
||||
// 只读输入框灰色底
|
||||
::v-deep .el-input__inner[readonly] {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="title"
|
||||
width="900px"
|
||||
top="8vh"
|
||||
:close-on-click-modal="false"
|
||||
class="team-select-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<div class="team-select">
|
||||
<!-- ==================== 操作说明 ==================== -->
|
||||
<div v-if="excludeNote" class="note-bar">
|
||||
<i class="el-icon-info"></i>
|
||||
<span>{{ excludeNote }}</span>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 查询条件区域 ==================== -->
|
||||
<div class="query-panel">
|
||||
<el-form :inline="true" class="query-form" @submit.native.prevent>
|
||||
<el-form-item label="班次编号">
|
||||
<el-input
|
||||
v-model="queryForm.xydbh"
|
||||
placeholder="请输入班次编号(模糊)"
|
||||
clearable
|
||||
style="width: 220px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button size="small" @click="handleResetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 目标班次学期表格 ==================== -->
|
||||
<div class="table-panel">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="loading"
|
||||
:data="filteredList"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
max-height="360"
|
||||
class="team-table"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="44" align="center" reserve-selection />
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="nd" label="年度" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="学期第次" width="90" align="center">
|
||||
<template slot-scope="{ row }">{{ xqdcLabel(row.xqdc) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="xydbh" label="班次编号" min-width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="kxrq" label="开学日期" width="110" align="center" :formatter="fmtDate" />
|
||||
<el-table-column prop="jsrq" label="结束日期" width="110" align="center" :formatter="fmtDate" />
|
||||
<el-table-column prop="bz" label="备注" min-width="120" align="left" header-align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<el-empty v-if="!filteredList.length" description="暂无可选的目标班次学期" :image-size="60" />
|
||||
</div>
|
||||
|
||||
<!-- ==================== 底部按钮区域 ==================== -->
|
||||
<div class="footer-actions">
|
||||
<span class="selected-count">已选择 {{ selection.length }} 个班次学期</span>
|
||||
<el-button size="small" @click="dialogVisible = false">取消</el-button>
|
||||
<el-button size="small" type="primary" :disabled="!selection.length" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ClassTeamSelectDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 标题(可选) */
|
||||
title: { type: String, default: '目标班次学期选取' },
|
||||
/** 可选的目标班次学期列表(含 bh/nd/xqdc/xydbh/kxrq/jsrq 等) */
|
||||
semesterList: { type: Array, default: () => [] },
|
||||
/** 需要排除的班次学期编号(当前班次学期,不可复制给自己) */
|
||||
excludeBh: { type: String, default: '' },
|
||||
/** 顶部操作说明 */
|
||||
excludeNote: { type: String, default: '' }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
queryForm: { xydbh: '' },
|
||||
selection: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
/** 排除当前班次学期后的可选列表 */
|
||||
availableList() {
|
||||
const excludeBh = this.excludeBh || ''
|
||||
return (this.semesterList || []).filter(item => item.bh && String(item.bh) !== String(excludeBh))
|
||||
},
|
||||
/** 本地过滤后的列表 */
|
||||
filteredList() {
|
||||
const kw = (this.queryForm.xydbh || '').trim()
|
||||
if (!kw) return this.availableList
|
||||
return this.availableList.filter(item => item.xydbh && String(item.xydbh).includes(kw))
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.selection = []
|
||||
this.queryForm.xydbh = ''
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.tableRef) this.$refs.tableRef.clearSelection()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fmtDate(val) {
|
||||
if (!val) return '-'
|
||||
return String(val).slice(0, 10)
|
||||
},
|
||||
xqdcLabel(val) {
|
||||
if (val === 1 || val === '1') return '第1学期'
|
||||
if (val === 2 || val === '2') return '第2学期'
|
||||
if (val === 3 || val === '3') return '第3学期'
|
||||
return val !== undefined && val !== null && val !== '' ? `第${val}学期` : '-'
|
||||
},
|
||||
handleSelectionChange(rows) {
|
||||
this.selection = rows
|
||||
},
|
||||
handleQuery() {},
|
||||
handleResetQuery() {
|
||||
this.queryForm.xydbh = ''
|
||||
},
|
||||
handleConfirm() {
|
||||
if (!this.selection.length) {
|
||||
this.$message.warning('请先勾选目标班次学期')
|
||||
return
|
||||
}
|
||||
this.$emit('confirm', this.selection.slice())
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.team-select {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
|
||||
// ========== 操作说明 ==========
|
||||
.note-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
color: #1e6fff;
|
||||
background: #ecf5ff;
|
||||
border: 1px solid #d9ecff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
// ========== 查询条件区域 ==========
|
||||
.query-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 10px 12px 2px;
|
||||
|
||||
.query-form {
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 表格区域 ==========
|
||||
.table-panel {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
.team-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .el-empty {
|
||||
padding: 12px 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 底部按钮区域 ==========
|
||||
.footer-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
|
||||
.selected-count {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,656 @@
|
||||
<template>
|
||||
<div class="app-container shift-semester-page">
|
||||
<!-- ==================== 页面标题 ==================== -->
|
||||
<div class="page-title">班次学期信息管理</div>
|
||||
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :inline="true" :model="searchForm" class="search-form">
|
||||
<el-form-item label="班次编号">
|
||||
<el-input
|
||||
v-model="searchForm.xydbh"
|
||||
placeholder="请输入班次编号(模糊)"
|
||||
clearable
|
||||
style="width: 220px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="年度">
|
||||
<el-select
|
||||
v-model="filterYear"
|
||||
placeholder="全部年度"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 140px"
|
||||
@change="handleYearChange"
|
||||
>
|
||||
<el-option v-for="y in yearFilterOptions" :key="y" :label="`${y}年`" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 工具栏按钮区 ==================== -->
|
||||
<div class="list-toolbar">
|
||||
<div class="left-group">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleBatchAdd">批量创建班次学期</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-document-add" @click="handleAdd">新增</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-edit" :disabled="!currentRow" @click="handleEdit">编辑</el-button>
|
||||
<el-button type="danger" plain icon="el-icon-delete" :disabled="!selection.length" @click="handleDelete">删除所选</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-date" :disabled="!selection.length" @click="handleQuickSetDates">快速设定学期日期</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-notebook-2" :disabled="!selection.length" @click="handleSetJxrw">批量设置教学任务</el-button>
|
||||
</div>
|
||||
<div class="right-group">
|
||||
<el-button type="success" plain icon="el-icon-calendar" :disabled="!currentRow" @click="handleEditCalendar">编辑班历</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 班次学期信息列表 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="loading"
|
||||
:data="displayData"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
size="small"
|
||||
max-height="480"
|
||||
class="class-table"
|
||||
@selection-change="handleSelectionChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template slot="empty">
|
||||
<span>无数据!</span>
|
||||
</template>
|
||||
<el-table-column type="selection" width="44" align="center" />
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="xydbh" label="班次编号" min-width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nd" label="年度" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="学期第次" width="90" align="center">
|
||||
<template slot-scope="{ row }">{{ xqdcLabel(row.xqdc) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kxrq" label="开学日期" width="110" align="center" :formatter="fmtDate" />
|
||||
<el-table-column prop="jsrq" label="结束日期" width="110" align="center" :formatter="fmtDate" />
|
||||
<el-table-column prop="zyjsbh" label="专用教室" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="教学任务" min-width="160" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="{ row }">{{ taskName(row.jxrwbh) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开放教员排课" width="110" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-tag v-if="Number(row.kfjypk) === 1" type="success" size="small">开放</el-tag>
|
||||
<el-tag v-else type="info" size="small">关闭</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bz" label="备注" min-width="120" align="left" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="handleEditCalendar(row)">班历</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDeleteRow(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
class="list-pagination"
|
||||
:current-page="pageNum"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 班次学期新增/编辑弹窗 ==================== -->
|
||||
<ClassSemesterDetailDialog
|
||||
:visible="detailVisible"
|
||||
:mode="detailMode"
|
||||
:semester="detailSemester"
|
||||
:team-info="detailTeamInfo"
|
||||
:year-options="yearOptions"
|
||||
:task-options="taskOptions"
|
||||
@update:visible="val => detailVisible = val"
|
||||
@submit="handleDetailSubmit"
|
||||
/>
|
||||
|
||||
<!-- ==================== 班历管理弹窗 ==================== -->
|
||||
<ClassCalendarDialog
|
||||
:visible="calendarVisible"
|
||||
:semester="calendarSemester"
|
||||
:semester-options="semesterOptions"
|
||||
@update:visible="val => calendarVisible = val"
|
||||
/>
|
||||
|
||||
<!-- ==================== 批量创建班次学期弹窗 ==================== -->
|
||||
<el-dialog
|
||||
:visible="batchAddVisible"
|
||||
title="批量创建班次学期"
|
||||
width="520px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => batchAddVisible = val"
|
||||
>
|
||||
<el-form ref="batchAddFormRef" :model="batchAddForm" :rules="batchAddRules" label-width="100px">
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-select v-model="batchAddForm.nd" placeholder="请选择年度" filterable style="width: 100%">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="`${y}年`" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学期" prop="xqdc">
|
||||
<el-select v-model="batchAddForm.xqdc" placeholder="请选择学期" style="width: 100%">
|
||||
<el-option label="春季学期" value="春季学期" />
|
||||
<el-option label="夏季学期" value="夏季学期" />
|
||||
<el-option label="秋季学期" value="秋季学期" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期" prop="startTime">
|
||||
<el-date-picker v-model="batchAddForm.startTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择开始日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期" prop="endTime">
|
||||
<el-date-picker v-model="batchAddForm.endTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择结束日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="batchAddVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleBatchAddSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 快速设定学期日期弹窗 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dateRangeVisible"
|
||||
title="快速设定学期日期"
|
||||
width="480px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dateRangeVisible = val"
|
||||
>
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
:title="`将对选中的 ${selection.length} 条班次学期统一设定开学/结束日期`"
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
<el-form ref="dateRangeFormRef" :model="dateRangeForm" :rules="dateRangeRules" label-width="100px">
|
||||
<el-form-item label="开学日期" prop="kxrq">
|
||||
<el-date-picker v-model="dateRangeForm.kxrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择开学日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期" prop="jsrq">
|
||||
<el-date-picker v-model="dateRangeForm.jsrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择结束日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="dateRangeVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleDateRangeSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 批量设置教学任务弹窗 ==================== -->
|
||||
<el-dialog
|
||||
:visible="jxrwVisible"
|
||||
title="批量设置教学任务"
|
||||
width="480px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => jxrwVisible = val"
|
||||
>
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
:title="`将对选中的 ${selection.length} 条班次学期统一设置教学任务`"
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
<el-form ref="jxrwFormRef" :model="jxrwForm" :rules="jxrwRules" label-width="100px">
|
||||
<el-form-item label="教学任务" prop="jxrwbh">
|
||||
<el-select v-model="jxrwForm.jxrwbh" placeholder="请选择教学任务" filterable style="width: 100%">
|
||||
<el-option v-for="opt in taskOptions" :key="opt.bh" :label="opt.rwmc" :value="opt.bh" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="jxrwVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleJxrwSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ClassSemesterDetailDialog from './ClassSemesterDetailDialog.vue'
|
||||
import ClassCalendarDialog from './ClassCalendarDialog.vue'
|
||||
import { listSemester, allSemester, addSemester, updateSemester, delSemester, batchDeleteSemester, batchUpdateDateRange, batchUpdateJxrwbh, batchAddFromElective } from '@/api/studentRecords/semester'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
import { listTeachingTask } from '@/api/teachBusiness/teachingTask'
|
||||
|
||||
export default {
|
||||
name: 'ShiftSemester',
|
||||
components: {
|
||||
ClassSemesterDetailDialog,
|
||||
ClassCalendarDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
saving: false,
|
||||
|
||||
// ==================== 查询条件 ====================
|
||||
searchForm: { xydbh: '' },
|
||||
filterYear: undefined,
|
||||
yearFilterOptions: [],
|
||||
|
||||
// ==================== 列表与分页 ====================
|
||||
tableData: [],
|
||||
selection: [],
|
||||
currentRow: null,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
|
||||
// ==================== 下拉数据 ====================
|
||||
/** 年度下拉(来自 /semester/all) */
|
||||
yearOptions: [],
|
||||
/** 教学任务下拉({ bh, rwmc }) */
|
||||
taskOptions: [],
|
||||
/** 全部班次学期(用于班历复制目标选择) */
|
||||
semesterOptions: [],
|
||||
|
||||
// ==================== 班次学期新增/编辑 ====================
|
||||
detailVisible: false,
|
||||
detailMode: 'add',
|
||||
detailSemester: null,
|
||||
detailTeamInfo: null,
|
||||
|
||||
// ==================== 班历管理 ====================
|
||||
calendarVisible: false,
|
||||
calendarSemester: null,
|
||||
|
||||
// ==================== 批量创建班次学期 ====================
|
||||
batchAddVisible: false,
|
||||
batchAddForm: { nd: undefined, xqdc: '', startTime: '', endTime: '' },
|
||||
batchAddRules: {
|
||||
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||
xqdc: [{ required: true, message: '请选择学期', trigger: 'change' }],
|
||||
startTime: [{ required: true, message: '请选择开始日期', trigger: 'change' }],
|
||||
endTime: [{ required: true, message: '请选择结束日期', trigger: 'change' }]
|
||||
},
|
||||
|
||||
// ==================== 快速设定学期日期 ====================
|
||||
dateRangeVisible: false,
|
||||
dateRangeForm: { kxrq: '', jsrq: '' },
|
||||
dateRangeRules: {
|
||||
kxrq: [{ required: true, message: '请选择开学日期', trigger: 'change' }],
|
||||
jsrq: [{ required: true, message: '请选择结束日期', trigger: 'change' }]
|
||||
},
|
||||
|
||||
// ==================== 批量设置教学任务 ====================
|
||||
jxrwVisible: false,
|
||||
jxrwForm: { jxrwbh: undefined },
|
||||
jxrwRules: {
|
||||
jxrwbh: [{ required: true, message: '请选择教学任务', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 本地按年度过滤(后端 /semester/list 仅支持 xydbh 模糊筛选) */
|
||||
displayData() {
|
||||
if (!this.filterYear) return this.tableData
|
||||
return this.tableData.filter(item => String(item.nd) === String(this.filterYear))
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadYearOptions()
|
||||
this.loadTaskOptions()
|
||||
this.loadSemesterOptions()
|
||||
this.loadList()
|
||||
},
|
||||
methods: {
|
||||
/* ==================== 格式化 ==================== */
|
||||
fmtDate(val) {
|
||||
if (!val) return '-'
|
||||
return String(val).slice(0, 10)
|
||||
},
|
||||
xqdcLabel(val) {
|
||||
if (val === 1 || val === '1') return '第1学期'
|
||||
if (val === 2 || val === '2') return '第2学期'
|
||||
if (val === 3 || val === '3') return '第3学期'
|
||||
return val !== undefined && val !== null && val !== '' ? `第${val}学期` : '-'
|
||||
},
|
||||
/** 教学任务编号 → 名称 */
|
||||
taskName(bh) {
|
||||
if (!bh) return '-'
|
||||
const opt = this.taskOptions.find(o => o.bh === bh)
|
||||
return opt ? opt.rwmc : bh
|
||||
},
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
|
||||
/* ==================== 下拉数据加载 ==================== */
|
||||
loadYearOptions() {
|
||||
listAllSemester().then(res => {
|
||||
const list = (res && res.data) || []
|
||||
const years = list.map(x => x.nd).filter(v => v !== undefined && v !== null && v !== '')
|
||||
this.yearOptions = [...new Set(years)].sort((a, b) => Number(a) - Number(b))
|
||||
}).catch(() => {
|
||||
this.yearOptions = []
|
||||
})
|
||||
},
|
||||
loadTaskOptions() {
|
||||
listTeachingTask({ pageNum: 1, pageSize: 1000 }).then(res => {
|
||||
const list = (res && res.data && res.data.records) || []
|
||||
this.taskOptions = list.filter(o => o.bh)
|
||||
}).catch(() => {
|
||||
this.taskOptions = []
|
||||
})
|
||||
},
|
||||
loadSemesterOptions() {
|
||||
allSemester().then(res => {
|
||||
this.semesterOptions = (res && res.data) || []
|
||||
}).catch(() => {
|
||||
this.semesterOptions = []
|
||||
})
|
||||
},
|
||||
|
||||
/* ==================== 列表加载 ==================== */
|
||||
loadList() {
|
||||
this.loading = true
|
||||
const query = this.cleanPayload({
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize,
|
||||
xydbh: this.searchForm.xydbh
|
||||
})
|
||||
listSemester(query).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.buildYearFilterOptions()
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 本地年度过滤下拉(从当前数据动态生成,避免硬编码) */
|
||||
buildYearFilterOptions() {
|
||||
const years = this.tableData.map(r => r.nd).filter(v => v !== undefined && v !== null && v !== '')
|
||||
this.yearFilterOptions = [...new Set(years)].sort((a, b) => Number(a) - Number(b))
|
||||
},
|
||||
handleYearChange() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.tableRef) this.$refs.tableRef.setCurrentRow(null)
|
||||
this.currentRow = null
|
||||
})
|
||||
},
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.loadList()
|
||||
},
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.loadList()
|
||||
},
|
||||
handleSelectionChange(rows) {
|
||||
this.selection = rows
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
this.currentRow = row
|
||||
},
|
||||
|
||||
/* ==================== 查询 / 重置 ==================== */
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.loadList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm.xydbh = ''
|
||||
this.filterYear = undefined
|
||||
this.pageNum = 1
|
||||
this.loadList()
|
||||
},
|
||||
|
||||
/* ==================== 新增 / 编辑 ==================== */
|
||||
handleAdd() {
|
||||
this.detailMode = 'add'
|
||||
this.detailSemester = null
|
||||
this.detailTeamInfo = null
|
||||
this.detailVisible = true
|
||||
},
|
||||
handleEdit(row) {
|
||||
const target = row || this.currentRow
|
||||
if (!target) {
|
||||
this.$message.warning('请先选择一条班次学期信息')
|
||||
return
|
||||
}
|
||||
this.detailMode = 'edit'
|
||||
this.detailSemester = target
|
||||
this.detailTeamInfo = null
|
||||
this.detailVisible = true
|
||||
},
|
||||
handleDetailSubmit(payload) {
|
||||
this.saving = true
|
||||
const req = this.detailMode === 'edit'
|
||||
? updateSemester(payload)
|
||||
: addSemester(payload)
|
||||
req.then(() => {
|
||||
this.saving = false
|
||||
this.detailVisible = false
|
||||
this.$message.success(this.detailMode === 'edit' ? '班次学期已更新' : '班次学期已新增')
|
||||
this.loadList()
|
||||
this.loadSemesterOptions()
|
||||
}).catch(() => {
|
||||
this.saving = false
|
||||
})
|
||||
},
|
||||
|
||||
/* ==================== 删除 ==================== */
|
||||
handleDelete() {
|
||||
if (!this.selection.length) {
|
||||
this.$message.warning('请先勾选要删除的班次学期')
|
||||
return
|
||||
}
|
||||
this.$confirm(`确定删除选中的 ${this.selection.length} 条班次学期吗?删除后其下班历记录将一并删除。`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const bhList = this.selection.map(r => r.bh)
|
||||
batchDeleteSemester(bhList).then(() => {
|
||||
this.$message.success('已删除')
|
||||
this.loadList()
|
||||
this.loadSemesterOptions()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
handleDeleteRow(row) {
|
||||
this.$confirm(`确定删除班次学期「${row.xydbh || row.bh}」吗?删除后其下班历记录将一并删除。`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
delSemester(row.bh).then(() => {
|
||||
this.$message.success('已删除')
|
||||
this.loadList()
|
||||
this.loadSemesterOptions()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ==================== 编辑班历 ==================== */
|
||||
handleEditCalendar(row) {
|
||||
const target = row || this.currentRow
|
||||
if (!target) {
|
||||
this.$message.warning('请先在列表中选择一条班次学期信息')
|
||||
return
|
||||
}
|
||||
this.calendarSemester = target
|
||||
this.calendarVisible = true
|
||||
},
|
||||
|
||||
/* ==================== 批量创建班次学期 ==================== */
|
||||
handleBatchAdd() {
|
||||
this.batchAddForm = { nd: this.yearOptions[0] || undefined, xqdc: '', startTime: '', endTime: '' }
|
||||
this.batchAddVisible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.batchAddFormRef) this.$refs.batchAddFormRef.clearValidate()
|
||||
})
|
||||
},
|
||||
handleBatchAddSubmit() {
|
||||
this.$refs.batchAddFormRef.validate(valid => {
|
||||
if (!valid) return
|
||||
const f = this.batchAddForm
|
||||
this.saving = true
|
||||
batchAddFromElective({
|
||||
nd: f.nd,
|
||||
xqdc: f.xqdc,
|
||||
startTime: f.startTime,
|
||||
endTime: f.endTime
|
||||
}).then(res => {
|
||||
this.saving = false
|
||||
this.batchAddVisible = false
|
||||
const count = (res && res.data) || 0
|
||||
this.$message.success(`已创建 ${count} 个班次学期`)
|
||||
this.loadList()
|
||||
this.loadSemesterOptions()
|
||||
}).catch(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/* ==================== 快速设定学期日期 ==================== */
|
||||
handleQuickSetDates() {
|
||||
if (!this.selection.length) {
|
||||
this.$message.warning('请先勾选要设定日期的班次学期')
|
||||
return
|
||||
}
|
||||
this.dateRangeForm = { kxrq: '', jsrq: '' }
|
||||
this.dateRangeVisible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.dateRangeFormRef) this.$refs.dateRangeFormRef.clearValidate()
|
||||
})
|
||||
},
|
||||
handleDateRangeSubmit() {
|
||||
this.$refs.dateRangeFormRef.validate(valid => {
|
||||
if (!valid) return
|
||||
const f = this.dateRangeForm
|
||||
this.saving = true
|
||||
batchUpdateDateRange({
|
||||
bhList: this.selection.map(r => r.bh),
|
||||
xqkssj: f.kxrq,
|
||||
xqjssj: f.jsrq
|
||||
}).then(res => {
|
||||
this.saving = false
|
||||
this.dateRangeVisible = false
|
||||
const count = (res && res.data) || 0
|
||||
this.$message.success(`已更新 ${count} 条班次学期的日期`)
|
||||
this.loadList()
|
||||
}).catch(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/* ==================== 批量设置教学任务 ==================== */
|
||||
handleSetJxrw() {
|
||||
if (!this.selection.length) {
|
||||
this.$message.warning('请先勾选要设置教学任务的班次学期')
|
||||
return
|
||||
}
|
||||
this.jxrwForm = { jxrwbh: undefined }
|
||||
this.jxrwVisible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.jxrwFormRef) this.$refs.jxrwFormRef.clearValidate()
|
||||
})
|
||||
},
|
||||
handleJxrwSubmit() {
|
||||
this.$refs.jxrwFormRef.validate(valid => {
|
||||
if (!valid) return
|
||||
this.saving = true
|
||||
batchUpdateJxrwbh({
|
||||
bhList: this.selection.map(r => r.bh),
|
||||
jxrwbh: this.jxrwForm.jxrwbh
|
||||
}).then(res => {
|
||||
this.saving = false
|
||||
this.jxrwVisible = false
|
||||
const count = (res && res.data) || 0
|
||||
this.$message.success(`已更新 ${count} 条班次学期的教学任务`)
|
||||
this.loadList()
|
||||
}).catch(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.shift-semester-page {
|
||||
// ========== 页面标题 ==========
|
||||
.page-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
padding-left: 10px;
|
||||
border-left: 4px solid var(--edu-green-primary);
|
||||
}
|
||||
|
||||
// ========== 1. 查询条件区域 ==========
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
// ========== 2. 工具栏按钮区 ==========
|
||||
.list-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.left-group,
|
||||
.right-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 3. 数据表格区 ==========
|
||||
.table-card {
|
||||
.class-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.list-pagination {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,740 @@
|
||||
<template>
|
||||
<div class="app-container management-page subject-page">
|
||||
|
||||
<!-- ==================== 2. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2 class="section-title">筛选条件</h2>
|
||||
<p class="section-description">按课程名称、代码和培训属性筛选课程科目</p>
|
||||
</div>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
<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.kmc" placeholder="请输入课名称" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">科目代码</span>
|
||||
<el-input v-model="searchForm.kmdm" placeholder="请输入科目代码" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">培训层次</span>
|
||||
<el-input v-model="searchForm.pxcc" placeholder="请输入培训层次" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">课程类型</span>
|
||||
<el-input v-model="searchForm.kclx" placeholder="请输入课程类型" clearable class="q-control" />
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<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>
|
||||
<el-input v-model="searchForm.jysdh" placeholder="请输入教研室代号" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">培训类型</span>
|
||||
<el-input v-model="searchForm.pxlx" placeholder="请输入培训类型" clearable class="q-control" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 操作按钮区域 ==================== -->
|
||||
<el-card shadow="never" class="action-card">
|
||||
<div class="section-heading section-heading--compact">
|
||||
<div>
|
||||
<h2 class="section-title">课程科目操作</h2>
|
||||
<p class="section-description">维护课程科目,或下载业务数据与导入模板</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleOpenDialog">新建课程科目</el-button>
|
||||
<el-button type="danger" plain icon="el-icon-delete" @click="handleBatchDelete">删除所选</el-button>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button icon="el-icon-download" @click="handleDownloadTemplate">【课程科目数据文件模板】下载</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 4. 文件上传区域 ==================== -->
|
||||
<el-card shadow="never" class="upload-card">
|
||||
<div class="section-heading section-heading--compact">
|
||||
<div>
|
||||
<h2 class="section-title">数据导入</h2>
|
||||
<p class="section-description">选择填写完成的课程科目模板并上传</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-row">
|
||||
<div class="upload-left">
|
||||
<el-button icon="el-icon-folder-opened" @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" icon="el-icon-upload2" @click="handleUpload">上传数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 6. 数据表格区域 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<div class="section-heading section-heading--compact table-heading">
|
||||
<div>
|
||||
<h2 class="section-title">课程科目列表</h2>
|
||||
<p class="section-description">共 {{ total }} 条数据</p>
|
||||
</div>
|
||||
</div>
|
||||
<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="kbh" label="课编号" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="kmc" label="课名称" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="jc" label="简称" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="jysdh" label="教研室代号" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="kclx" label="课程类型" width="150" align="center" />
|
||||
<el-table-column prop="pxlx" label="培训类型" width="150" align="center" />
|
||||
<el-table-column prop="pxcc" label="培训层次" width="200" align="center" />
|
||||
<el-table-column prop="xf" label="学分" align="center" />
|
||||
<el-table-column prop="xs" label="学时" width="160" align="center" />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</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="1000px"
|
||||
: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">
|
||||
<el-form-item label="课编号" prop="kbh">
|
||||
<el-input v-model="addForm.kbh" :disabled="isEdit" placeholder="新增时留空自动生成" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课名称" prop="kmc">
|
||||
<el-input v-model="addForm.kmc" placeholder="请输入课名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="简称" prop="jc">
|
||||
<el-input v-model="addForm.jc" placeholder="请输入简称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="教研室代号" prop="jysdh">
|
||||
<el-input v-model="addForm.jysdh" placeholder="请输入教研室代号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="学分" prop="xf">
|
||||
<el-input-number v-model="addForm.xf" :min="0" :precision="1" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="学时" prop="xs">
|
||||
<el-input-number v-model="addForm.xs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="培训层次" prop="pxcc">
|
||||
<el-input v-model="addForm.pxcc" placeholder="请输入培训层次" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="培训类型" prop="pxlx">
|
||||
<el-input v-model="addForm.pxlx" placeholder="请输入培训类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程类型" prop="kclx">
|
||||
<el-input v-model="addForm.kclx" placeholder="请输入课程类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="考试课时" prop="ksks">
|
||||
<el-input-number v-model="addForm.ksks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="成绩分制" prop="cjfz">
|
||||
<el-input v-model="addForm.cjfz" placeholder="请输入成绩分制" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="不计入学员平均分" prop="bjrxypjf">
|
||||
<el-select v-model="addForm.bjrxypjf" class="w-full">
|
||||
<el-option label="否" :value="0" />
|
||||
<el-option label="是" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="理论学时" prop="llxs">
|
||||
<el-input-number v-model="addForm.llxs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="实践学时" prop="sjxs">
|
||||
<el-input-number v-model="addForm.sjxs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="周课时" prop="zks">
|
||||
<el-input-number v-model="addForm.zks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课类型" prop="klx">
|
||||
<el-input v-model="addForm.klx" placeholder="请输入课类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="考试课时不显示" prop="ksksbxs">
|
||||
<el-select v-model="addForm.ksksbxs" class="w-full">
|
||||
<el-option label="否" :value="0" />
|
||||
<el-option label="是" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程统一编号" prop="kctybh">
|
||||
<el-input v-model="addForm.kctybh" placeholder="请输入课程统一编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="辅导答疑课时" prop="fddyks">
|
||||
<el-input-number v-model="addForm.fddyks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="自修课时" prop="zxks">
|
||||
<el-input-number v-model="addForm.zxks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="修订日期" prop="xdrq">
|
||||
<el-input v-model="addForm.xdrq" placeholder="如 2026-08-24" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="节次优选级" prop="jcyxj">
|
||||
<el-input v-model="addForm.jcyxj" placeholder="请输入节次优选级" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程支持方式" prop="kczcfs">
|
||||
<el-input v-model="addForm.kczcfs" placeholder="请输入课程支持方式" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程建设方式" prop="kcjsfs">
|
||||
<el-input v-model="addForm.kcjsfs" placeholder="请输入课程建设方式" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="政治类课程" prop="zzlkc">
|
||||
<el-select v-model="addForm.zzlkc" class="w-full">
|
||||
<el-option label="否" :value="0" />
|
||||
<el-option label="是" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="考核方式" prop="khfs">
|
||||
<el-input v-model="addForm.khfs" placeholder="请输入考核方式" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="形成性成绩分值" prop="xcxcjfz">
|
||||
<el-input-number v-model="addForm.xcxcjfz" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="终结性成绩分值" prop="zjxcjfz">
|
||||
<el-input-number v-model="addForm.zjxcjfz" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="密级" prop="mj">
|
||||
<el-input v-model="addForm.mj" placeholder="请输入密级" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="评选情况" prop="pxqk">
|
||||
<el-input v-model="addForm.pxqk" placeholder="请输入评选情况" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24">
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="addForm.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { saveAs } from 'file-saver'
|
||||
import { listKb as listSubject, addKb as addSubject, updateKb as updateSubject, deleteKb as deleteSubject, getKb, downloadCourseSubjectTemplate } from '@/api/teachOffice/kb'
|
||||
|
||||
export default {
|
||||
name: 'SubjectIndex',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 1. 顶部状态提示 ====================
|
||||
statusTip: '请输入查询条件',
|
||||
|
||||
// ==================== 2. 查询条件 ====================
|
||||
searchForm: {
|
||||
kmc: '',
|
||||
jc: '',
|
||||
kmdm: '',
|
||||
jysdh: '',
|
||||
kclx: '',
|
||||
pxlx: '',
|
||||
pxcc: ''
|
||||
},
|
||||
|
||||
// ==================== 列表数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
selectedRows: [],
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
selectedFile: null,
|
||||
coverExist: false,
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
dialogVisible: false,
|
||||
addLoading: false,
|
||||
isEdit: false,
|
||||
addForm: this.createEmptyForm(),
|
||||
rules: {
|
||||
kmc: [{ required: true, message: '请输入课名称', trigger: 'blur' }],
|
||||
jysdh: [{ required: true, message: '请输入教研室代号', trigger: 'blur' }],
|
||||
xf: [{ required: true, message: '请输入学分', trigger: 'blur' }],
|
||||
pxcc: [{ required: true, message: '请输入培训层次', trigger: 'blur' }],
|
||||
pxlx: [{ required: true, message: '请输入培训类型', trigger: 'blur' }],
|
||||
kclx: [{ required: true, message: '请输入课程类型', trigger: 'blur' }],
|
||||
ksks: [{ required: true, message: '请输入考试课时', trigger: 'blur' }],
|
||||
cjfz: [{ required: true, message: '请输入成绩分制', trigger: 'blur' }],
|
||||
llxs: [{ required: true, message: '请输入理论学时', trigger: 'blur' }],
|
||||
sjxs: [{ required: true, message: '请输入实践学时', trigger: 'blur' }],
|
||||
zks: [{ required: true, message: '请输入周课时', trigger: 'blur' }],
|
||||
klx: [{ required: true, message: '请输入课类型', trigger: 'blur' }],
|
||||
kctybh: [{ required: true, message: '请输入课程统一编号', trigger: 'blur' }],
|
||||
fddyks: [{ required: true, message: '请输入辅导答疑课时', trigger: 'blur' }],
|
||||
zxks: [{ required: true, message: '请输入自修课时', trigger: 'blur' }],
|
||||
xdrq: [{ required: true, message: '请输入修订日期', trigger: 'blur' }],
|
||||
jcyxj: [{ required: true, message: '请输入节次优选级', trigger: 'blur' }],
|
||||
kczcfs: [{ required: true, message: '请输入课程支持方式', trigger: 'blur' }],
|
||||
kcjsfs: [{ required: true, message: '请输入课程建设方式', trigger: 'blur' }],
|
||||
khfs: [{ required: true, message: '请输入考核方式', trigger: 'blur' }],
|
||||
xcxcjfz: [{ required: true, message: '请输入形成性成绩分值', trigger: 'blur' }],
|
||||
zjxcjfz: [{ required: true, message: '请输入终结性成绩分值', trigger: 'blur' }],
|
||||
mj: [{ required: true, message: '请输入密级', trigger: 'blur' }],
|
||||
pxqk: [{ required: true, message: '请输入评选情况', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogTitle() {
|
||||
return this.isEdit ? '编辑课程科目' : '新增课程科目'
|
||||
},
|
||||
fileName() {
|
||||
return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
/** 移除空值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
|
||||
/** 创建空白课程科目表单 */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
kbh: '', kmc: '', jysdh: '', bz: '', xh: '', xf: 0, jc: '', xs: 0,
|
||||
pxcc: '', pxlx: '', kclx: '', ksks: 0, py: '', gfmc: '', cjfz: '',
|
||||
bjrxypjf: 0, jxglbmbh: '', llxs: 0, sjxs: 0, kmdm: '', zks: 0, klx: '',
|
||||
ksksbxs: 0, kctybh: '', sydx: '', fddyks: 0, zxks: 0, bb: '', xdrq: '',
|
||||
jcyxj: '', kczcfs: '', kcjsfs: '', jsonzd: '', zzlkc: 0, khfs: '',
|
||||
xcxcjfz: 0, zjxcjfz: 0, mj: '', pxqk: ''
|
||||
}
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.addForm = this.createEmptyForm()
|
||||
},
|
||||
|
||||
// ==================== 列表加载 ====================
|
||||
buildQuery() {
|
||||
return this.cleanPayload({
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize,
|
||||
kmc: this.searchForm.kmc,
|
||||
jc: this.searchForm.jc,
|
||||
kmdm: this.searchForm.kmdm,
|
||||
jysdh: this.searchForm.jysdh,
|
||||
kclx: this.searchForm.kclx,
|
||||
pxlx: this.searchForm.pxlx,
|
||||
pxcc: this.searchForm.pxcc
|
||||
})
|
||||
},
|
||||
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
listSubject(this.buildQuery())
|
||||
.then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.statusTip = `共检索到 ${this.total} 条记录`
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
handleQuery() {
|
||||
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 kbhList = this.selectedRows.map(r => r.kbh)
|
||||
this.$confirm(`确定删除所选 ${kbhList.length} 条课程科目吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const tasks = kbhList.map(kbh => deleteSubject(kbh))
|
||||
Promise.all(tasks)
|
||||
.then(() => {
|
||||
this.$message.success(`已删除 ${kbhList.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('删除失败')
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/** 单条删除 */
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定删除课程科目「${row.kmc || row.kbh}」吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return deleteSubject(row.kbh)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch((err) => {
|
||||
if (err && err !== 'cancel') {
|
||||
this.$message.error('删除失败')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 下载 ====================
|
||||
handleDownloadTemplate() {
|
||||
downloadCourseSubjectTemplate().then(blob => {
|
||||
saveAs(blob, '课程课目数据文件模板.xls')
|
||||
this.$message.success('模板下载成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 文件上传(后端暂未提供) ====================
|
||||
handleSelectFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
|
||||
handleFileChange(e) {
|
||||
const input = e.target
|
||||
this.selectedFile = (input.files && input.files[0]) || null
|
||||
},
|
||||
|
||||
handleUpload() {
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
handleOpenDialog() {
|
||||
this.isEdit = false
|
||||
this.resetForm()
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
this.addLoading = true
|
||||
getKb(row.kbh)
|
||||
.then(res => {
|
||||
const data = (res && res.data) || row
|
||||
this.isEdit = true
|
||||
this.addForm = Object.assign(this.createEmptyForm(), data)
|
||||
this.dialogVisible = true
|
||||
})
|
||||
.finally(() => {
|
||||
this.addLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleSubmit() {
|
||||
this.$refs.addFormRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.addLoading = true
|
||||
const payload = this.cleanPayload({ ...this.addForm })
|
||||
const requestFn = this.isEdit ? updateSubject : addSubject
|
||||
requestFn(payload)
|
||||
.then(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '保存成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
})
|
||||
.finally(() => {
|
||||
this.addLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
handleCancel() {
|
||||
this.dialogVisible = 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;
|
||||
}
|
||||
}
|
||||
|
||||
.notice {
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
margin-top: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ==================== 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;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
.add-dialog {
|
||||
::v-deep(.el-dialog__body) {
|
||||
max-height: 70vh;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.add-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,513 @@
|
||||
<template>
|
||||
<div class="app-container task-plan-page">
|
||||
<!-- ==================== 页面标题 ==================== -->
|
||||
<div class="page-title">教学任务计划管理</div>
|
||||
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :inline="true" :model="searchForm" class="search-form">
|
||||
<el-form-item label="任务名称">
|
||||
<el-input
|
||||
v-model="searchForm.rwmc"
|
||||
placeholder="请输入任务名称"
|
||||
clearable
|
||||
style="width: 180px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="年度">
|
||||
<el-select v-model="searchForm.nd" placeholder="请选择年度" clearable filterable style="width: 140px">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="searchForm.zt" placeholder="请选择状态" clearable style="width: 140px">
|
||||
<el-option
|
||||
v-for="opt in statusOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 操作区域 ==================== -->
|
||||
<div class="list-toolbar">
|
||||
<div class="left-group">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新建教学任务</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 数据表格 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="loading" :data="tableData" border stripe class="task-table">
|
||||
<template slot="empty">
|
||||
<span>无数据!</span>
|
||||
</template>
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column prop="rwmc" label="任务名称" width="250" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nd" label="年度" width="150" align="center" />
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-tag :type="row.zt === '发布' ? 'success' : 'info'" size="small">
|
||||
{{ row.zt || '-' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fbsj" label="发布时间" width="180" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="jssj" label="结束时间" width="180" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="cjsj" label="创建时间" width="180" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="jcxqscsj" label="教材需求生成时间" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column label="操作" width="300" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
:disabled="row.zt === '发布'"
|
||||
@click="handlePublish(row)"
|
||||
>发布</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</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"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 4. 新增/修改对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="560px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="140px" class="add-form">
|
||||
<el-form-item v-if="isEdit" label="编号" prop="bh">
|
||||
<el-input v-model="form.bh" disabled placeholder="编号不可修改" />
|
||||
</el-form-item>
|
||||
<el-form-item v-else label="编号">
|
||||
<el-input disabled placeholder="新增后由系统自动生成" />
|
||||
</el-form-item>
|
||||
<el-form-item label="任务名称" prop="rwmc">
|
||||
<el-input v-model="form.rwmc" placeholder="请输入任务名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-select v-model="form.nd" placeholder="请选择年度" filterable style="width: 100%">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="zt">
|
||||
<el-select v-model="form.zt" placeholder="请选择状态" style="width: 100%">
|
||||
<el-option
|
||||
v-for="opt in statusOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="发布时间">
|
||||
<el-date-picker
|
||||
v-model="form.fbsj"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="请选择发布时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间">
|
||||
<el-date-picker
|
||||
v-model="form.jssj"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="请选择结束时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="教材需求生成时间">
|
||||
<el-date-picker
|
||||
v-model="form.jcxqscsj"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="请选择教材需求生成时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 5. 详情对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="detailVisible"
|
||||
title="教学任务详情"
|
||||
width="620px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => detailVisible = val"
|
||||
>
|
||||
<el-descriptions v-if="detailData.bh" :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailData.bh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务名称">{{ detailData.rwmc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年度">{{ fmtVal(detailData.nd) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{ detailData.zt || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="发布时间">{{ fmtVal(detailData.fbsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">{{ fmtVal(detailData.jssj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ fmtVal(detailData.cjsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教材需求生成时间">{{ fmtVal(detailData.jcxqscsj) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-else v-loading="detailLoading" class="detail-empty">加载中...</div>
|
||||
<div slot="footer">
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 教学任务计划管理(完整管理页)
|
||||
* 对应菜单:teachOffice/taskPlan
|
||||
* 提供 teachingTask 全套真实接口操作:分页查询 list、详情 get?bh=、新增 add、编辑 update、
|
||||
* 发布 batchPublish?bh=(需先填写教研室任务书)、删除 delete?bh=(级联删除教研室任务书)
|
||||
* 只读查询视图在 src/views/teachBusiness/teachingTask/index.vue(教学任务列表)提供,避免重复操作同一实体
|
||||
*/
|
||||
import {
|
||||
listTeachingTask,
|
||||
getTeachingTask,
|
||||
addTeachingTask,
|
||||
updateTeachingTask,
|
||||
deleteTeachingTask,
|
||||
publishTeachingTask
|
||||
} from '@/api/teachBusiness/teachingTask'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
|
||||
export default {
|
||||
name: 'TaskPlan',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 1. 查询条件 ====================
|
||||
searchForm: {
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: ''
|
||||
},
|
||||
yearOptions: [],
|
||||
statusOptions: [
|
||||
{ label: '未发布', value: '未发布' },
|
||||
{ label: '发布', value: '发布' }
|
||||
],
|
||||
|
||||
// ==================== 2. 表格数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
|
||||
// ==================== 3. 新增/修改表单 ====================
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新建教学任务',
|
||||
isEdit: false,
|
||||
saving: false,
|
||||
form: this.createEmptyForm(),
|
||||
rules: {
|
||||
rwmc: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
||||
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||
zt: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
||||
},
|
||||
|
||||
// ==================== 4. 详情 ====================
|
||||
detailVisible: false,
|
||||
detailLoading: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadYearOptions().then(() => this.fetchList())
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 年度下拉(数据来自 /semester/all,禁止硬编码) ---------- */
|
||||
loadYearOptions() {
|
||||
return listAllSemester().then(response => {
|
||||
const list = response.data || []
|
||||
const map = {}
|
||||
list.forEach(item => {
|
||||
if (item.nd !== null && item.nd !== undefined && item.nd !== '') map[item.nd] = item
|
||||
})
|
||||
const arr = Object.keys(map).sort((a, b) => String(b).localeCompare(String(a)))
|
||||
this.yearOptions = arr
|
||||
// 默认年度:优先当前学期(dqxq=true),否则取最新年度
|
||||
const current = list.find(item => item.dqxq === true)
|
||||
const defaultNd = (current && current.nd) || arr[0]
|
||||
if (!this.searchForm.nd) this.searchForm.nd = defaultNd
|
||||
return arr
|
||||
}).catch(() => {
|
||||
this.yearOptions = []
|
||||
return []
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 通用格式化 ---------- */
|
||||
fmtDateTime(row, column, cellValue) {
|
||||
if (cellValue === null || cellValue === undefined || cellValue === '') return '-'
|
||||
return String(cellValue).replace('T', ' ').slice(0, 16)
|
||||
},
|
||||
fmtVal(val) {
|
||||
if (val === null || val === undefined || val === '') return '-'
|
||||
return String(val).replace('T', ' ').slice(0, 16)
|
||||
},
|
||||
/** 移除空值(''/null/undefined),保留 0 等有效值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
|
||||
/* ---------- 列表加载 ---------- */
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
if (this.searchForm.rwmc && this.searchForm.rwmc.trim()) params.rwmc = this.searchForm.rwmc.trim()
|
||||
if (this.searchForm.nd !== undefined && this.searchForm.nd !== null && this.searchForm.nd !== '') {
|
||||
params.nd = this.searchForm.nd
|
||||
}
|
||||
if (this.searchForm.zt && this.searchForm.zt.trim()) params.zt = this.searchForm.zt.trim()
|
||||
listTeachingTask(params).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/* ---------- 新增 / 修改 ---------- */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: '未发布',
|
||||
fbsj: '',
|
||||
jssj: '',
|
||||
jcxqscsj: ''
|
||||
}
|
||||
},
|
||||
|
||||
handleAdd() {
|
||||
this.form = this.createEmptyForm()
|
||||
if (!this.form.nd && this.searchForm.nd) this.form.nd = this.searchForm.nd
|
||||
this.isEdit = false
|
||||
this.dialogTitle = '新建教学任务'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
this.form = {
|
||||
bh: row.bh || '',
|
||||
rwmc: row.rwmc || '',
|
||||
nd: row.nd,
|
||||
zt: row.zt || '未发布',
|
||||
fbsj: row.fbsj || '',
|
||||
jssj: row.jssj || '',
|
||||
jcxqscsj: row.jcxqscsj || ''
|
||||
}
|
||||
this.isEdit = true
|
||||
this.dialogTitle = '修改教学任务'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
const payload = this.cleanPayload(this.buildPayload())
|
||||
this.saving = true
|
||||
const req = this.isEdit ? updateTeachingTask(payload) : addTeachingTask(payload)
|
||||
req.then(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '新建成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/** 构建请求体:年度转数字以匹配后端 Integer,时间字段有值才传 */
|
||||
buildPayload() {
|
||||
const f = this.form
|
||||
const payload = {}
|
||||
if (this.isEdit && f.bh && String(f.bh).trim()) payload.bh = String(f.bh).trim()
|
||||
if (f.rwmc && String(f.rwmc).trim()) payload.rwmc = String(f.rwmc).trim()
|
||||
if (f.nd !== undefined && f.nd !== null && f.nd !== '') payload.nd = Number(f.nd)
|
||||
if (f.zt && String(f.zt).trim()) payload.zt = String(f.zt).trim()
|
||||
if (f.fbsj) payload.fbsj = f.fbsj
|
||||
if (f.jssj) payload.jssj = f.jssj
|
||||
if (f.jcxqscsj) payload.jcxqscsj = f.jcxqscsj
|
||||
return payload
|
||||
},
|
||||
|
||||
/* ---------- 详情 ---------- */
|
||||
handleDetail(row) {
|
||||
this.detailVisible = true
|
||||
this.detailLoading = true
|
||||
this.detailData = {}
|
||||
getTeachingTask(row.bh).then(res => {
|
||||
this.detailData = (res && res.data) || {}
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 删除 ---------- */
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除「${row.rwmc || row.bh || '该记录'}」吗?删除将级联删除关联的教研室任务书。`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => deleteTeachingTask(row.bh)).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 发布 ---------- */
|
||||
handlePublish(row) {
|
||||
this.$confirm(`确定要发布教学任务「${row.rwmc || row.bh || '该记录'}」吗?发布前请先填写关联的教研室任务书。`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => publishTeachingTask(row.bh)).then(() => {
|
||||
this.$message.success('发布成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.task-plan-page {
|
||||
.page-title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
// ========== 1. 查询条件区域 ==========
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 2. 工具栏 ==========
|
||||
.list-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.left-group,
|
||||
.right-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 3. 数据表格区域 ==========
|
||||
.table-card {
|
||||
.task-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 4. 详情 ==========
|
||||
.detail-empty {
|
||||
min-height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user