forked from liweijie/education
前端代码
This commit is contained in:
@@ -0,0 +1,533 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- ==================== 2. 查询条件区域 ==================== -->
|
||||
<div class="section-card query-card">
|
||||
<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">
|
||||
<el-checkbox v-model="searchForm.xxkztEnabled" />
|
||||
<span class="q-label">选修课状态</span>
|
||||
<el-select v-model="searchForm.xxkzt" class="q-control" :disabled="!searchForm.xxkztEnabled">
|
||||
<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">
|
||||
<el-checkbox v-model="searchForm.pxccEnabled" />
|
||||
<span class="q-label">培训层次</span>
|
||||
<el-select v-model="searchForm.pxcc" class="q-control" :disabled="!searchForm.pxccEnabled">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="notice">注意:勾选"选择框"表示启用该项对应的查询条件;文本输入框非空白表示启用对应的查询条件。</div>
|
||||
<div class="query-footer">
|
||||
<el-button class="gray-btn" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 导出按钮区域 ==================== -->
|
||||
<div class="section-card export-card">
|
||||
<div class="export-bar">
|
||||
<el-button type="primary" @click="handleDownloadList">下载选修班列表</el-button>
|
||||
<el-button type="primary" @click="handleDownloadWord">下载选修班学员名单Word</el-button>
|
||||
<el-button type="primary" @click="handleDownloadExcel">下载选修班学员名单Excel</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 4. 操作按钮区域 ==================== -->
|
||||
<div class="section-card action-card">
|
||||
<div class="action-row">
|
||||
<el-button type="primary" @click="handleOpenNew">新建选修课</el-button>
|
||||
<el-button type="primary" @click="handleOpenEarly">所选批量开放报名</el-button>
|
||||
<el-button type="primary" @click="handleCancelEarly">所选批量取消开放报名</el-button>
|
||||
<el-button type="primary" @click="handleStopSignup">批量停止报名</el-button>
|
||||
<el-button type="primary" @click="handleReverseRange">所选批量根据学员反向确定班次范围</el-button>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button type="primary" @click="handleDownloadTemplate">【选修课数据文件模板】下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 5. 文件上传区域 ==================== -->
|
||||
<div class="section-card upload-card">
|
||||
<div class="upload-row">
|
||||
<div class="upload-left">
|
||||
<el-button @click="handleSelectFile">选择文件</el-button>
|
||||
<span class="file-name" :class="{ 'has-file': selectedFile }">{{ fileName }}</span>
|
||||
<input ref="fileInputRef" type="file" style="display: none" @change="handleFileChange" />
|
||||
</div>
|
||||
<div class="upload-right">
|
||||
<el-button type="primary" @click="handleUpload">上传数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 6. 数据表格区域 ==================== -->
|
||||
<div class="section-card table-card">
|
||||
<el-table :data="pagedData" 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="course" label="课程" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="textbook" label="教材" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="teacher" label="实施教员" width="90" align="center" />
|
||||
<el-table-column prop="place" label="教学场地" width="100" show-overflow-tooltip />
|
||||
<el-table-column label="显示可选队别班次" min-width="150" show-overflow-tooltip>
|
||||
<template slot="header">
|
||||
<div class="checkable-header">
|
||||
<el-checkbox />
|
||||
<span>显示可选队别班次</span>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="{ row }">{{ row.teamClass }}</template>
|
||||
</el-table-column>
|
||||
<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.planHours }}</span>
|
||||
<span>{{ row.runHours }}</span>
|
||||
<span>{{ row.credit }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开课结课日期" min-width="150" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
{{ row.startDate }} ~ {{ row.endDate }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报名日期" min-width="140" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
{{ row.signupStart }} ~ {{ row.signupEnd }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="planCount" label="计划人数" width="90" align="center" />
|
||||
<el-table-column prop="requirement" label="要求说明" min-width="120" show-overflow-tooltip />
|
||||
</el-table>
|
||||
|
||||
<div class="pagination-wrap">
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="tableData.length"
|
||||
: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="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>
|
||||
export default {
|
||||
name: 'Elective',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 下拉选项 ====================
|
||||
statusOptions: ['拟制', '开放报名', '停止报名', '已开课'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
|
||||
// ==================== 查询条件 ====================
|
||||
searchForm: {
|
||||
js: '',
|
||||
kbcnj: '',
|
||||
xxkztEnabled: false,
|
||||
xxkzt: '拟制',
|
||||
kckmmc: '',
|
||||
xxbmc: '',
|
||||
pxccEnabled: false,
|
||||
pxcc: '无'
|
||||
},
|
||||
|
||||
// ==================== 数据表格 mock ====================
|
||||
tableData: [
|
||||
{ id: 1, course: '军事英语', textbook: '军事英语教程', teacher: '张三', place: '教室101', teamClass: '2025级学员1-5队', planHours: 32, runHours: 30, credit: 2, startDate: '2026-09-01', endDate: '2027-01-15', signupStart: '2026-08-20', signupEnd: '2026-09-01', planCount: 60, requirement: '限选50人' },
|
||||
{ id: 2, course: '摄影技术', textbook: '摄影基础', teacher: '李四', place: '教室102', teamClass: '2024级学员1-4队', planHours: 24, runHours: 24, credit: 1.5, startDate: '2026-09-01', endDate: '2027-01-15', signupStart: '2026-08-20', signupEnd: '2026-09-01', planCount: 40, requirement: '自备相机' },
|
||||
{ id: 3, course: '网球', textbook: '网球教程', teacher: '王五', place: '操场', teamClass: '2025级学员2-6队', planHours: 24, runHours: 22, credit: 1.5, startDate: '2026-09-01', endDate: '2027-01-15', signupStart: '2026-08-21', signupEnd: '2026-09-02', planCount: 30, requirement: '需自备球拍' },
|
||||
{ id: 4, course: '书法鉴赏', textbook: '中国书法', teacher: '赵六', place: '教室103', teamClass: '2026级学员1-3队', planHours: 16, runHours: 16, credit: 1, startDate: '2026-09-08', endDate: '2026-12-30', signupStart: '2026-08-25', signupEnd: '2026-09-05', planCount: 35, requirement: '' },
|
||||
{ id: 5, course: '无人机操作', textbook: '无人机原理', teacher: '孙七', place: '室外训练场', teamClass: '2025级学员1-6队', planHours: 32, runHours: 28, credit: 2, startDate: '2026-09-08', endDate: '2027-01-10', signupStart: '2026-08-26', signupEnd: '2026-09-06', planCount: 25, requirement: '需通过体检' }
|
||||
],
|
||||
selectedRows: [],
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
selectedFile: null,
|
||||
|
||||
// ==================== 新建选修课弹窗 ====================
|
||||
dialogVisible: false,
|
||||
form: {
|
||||
kcmc: '',
|
||||
js: '',
|
||||
jc: '',
|
||||
jxcd: '',
|
||||
jhsxs: 0,
|
||||
yxsxs: 0,
|
||||
xf: 0,
|
||||
jh: 0
|
||||
},
|
||||
rules: {
|
||||
kcmc: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
|
||||
js: [{ required: true, message: '请输入实施教员', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// ==================== 分页 ====================
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fileName() {
|
||||
return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'
|
||||
},
|
||||
pagedData() {
|
||||
const start = (this.currentPage - 1) * this.pageSize
|
||||
return this.tableData.slice(start, start + this.pageSize)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// ==================== 查询 ====================
|
||||
handleQuery() {
|
||||
console.log('查询条件:', JSON.parse(JSON.stringify(this.searchForm)))
|
||||
this.$message.success('查询完成(前端模拟)')
|
||||
},
|
||||
|
||||
// ==================== 导出 ====================
|
||||
downloadBlob(content, filename) {
|
||||
const blob = new Blob(['\ufeff' + content], { type: 'text/plain;charset=utf-8;' })
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = filename
|
||||
link.click()
|
||||
URL.revokeObjectURL(link.href)
|
||||
},
|
||||
handleDownloadList() {
|
||||
this.downloadBlob('课程,教材,实施教员,教学场地,计划人数\n', '选修班列表.txt')
|
||||
this.$message.success('选修班列表已下载(前端模拟)')
|
||||
},
|
||||
handleDownloadWord() {
|
||||
this.downloadBlob('选修班学员名单\n', '选修班学员名单Word.txt')
|
||||
this.$message.success('选修班学员名单Word已下载(前端模拟)')
|
||||
},
|
||||
handleDownloadExcel() {
|
||||
this.downloadBlob('选修班学员名单\n', '选修班学员名单Excel.txt')
|
||||
this.$message.success('选修班学员名单Excel已下载(前端模拟)')
|
||||
},
|
||||
handleDownloadTemplate() {
|
||||
this.downloadBlob('课程,教材,实施教员,教学场地,计划学时,学分,开课结课日期,报名日期,计划人数,要求说明\n', '选修课数据文件模板.txt')
|
||||
this.$message.success('【选修课数据文件模板】已下载(前端模拟)')
|
||||
},
|
||||
|
||||
// ==================== 操作按钮 ====================
|
||||
handleOpenEarly() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
this.$message.success('所选班已早开放报名(前端模拟)')
|
||||
},
|
||||
handleCancelEarly() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
this.$message.success('所选班已早取消开放报名(前端模拟)')
|
||||
},
|
||||
handleStopSignup() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
this.$message.success('已批量停止报名(前端模拟)')
|
||||
},
|
||||
handleReverseRange() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择选修班')
|
||||
return
|
||||
}
|
||||
this.$message.success('已根据学员反向确定班次范围(前端模拟)')
|
||||
},
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
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
|
||||
}
|
||||
console.log('上传文件:', this.selectedFile.name)
|
||||
this.$message.success(`文件「${this.selectedFile.name}」上传成功(前端模拟)`)
|
||||
},
|
||||
|
||||
// ==================== 表格多选 ====================
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
|
||||
// ==================== 新建选修课弹窗 ====================
|
||||
handleOpenNew() {
|
||||
Object.assign(this.form, { kcmc: '', js: '', jc: '', jxcd: '', jhsxs: 0, yxsxs: 0, xf: 0, jh: 0 })
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleNewConfirm() {
|
||||
if (!this.$refs.formRef) return
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
console.log('新建选修课:', JSON.parse(JSON.stringify(this.form)))
|
||||
this.$message.success('新建选修课成功(前端模拟)')
|
||||
this.dialogVisible = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 分页 ====================
|
||||
handlePageChange(page) {
|
||||
this.currentPage = page
|
||||
},
|
||||
|
||||
// 表格序号(跨页连续)
|
||||
tableIndex(index) {
|
||||
return (this.currentPage - 1) * this.pageSize + index + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// ==================== 公共区域容器 ====================
|
||||
.section-card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||
padding: 16px 20px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 查询条件区域 ====================
|
||||
.query-card {
|
||||
.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;
|
||||
}
|
||||
|
||||
.query-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 3. 导出按钮区域 ====================
|
||||
.export-card {
|
||||
.export-bar {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 6. 数据表格区域 ====================
|
||||
.table-card {
|
||||
.main-table {
|
||||
::v-deep .cell {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.checkable-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.triple-header,
|
||||
.triple-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.pagination-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// ==================== 按钮样式 ====================
|
||||
.gray-btn {
|
||||
height: 28px;
|
||||
padding: 2px 16px;
|
||||
font-size: 12px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #c0c4cc;
|
||||
color: #333;
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: #ebebeb;
|
||||
border-color: #c0c4cc;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,341 @@
|
||||
<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>
|
||||
<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>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据列表区域 -->
|
||||
<el-table v-loading="loading" :data="officeList" border :height="tableHeight">
|
||||
<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" prop="xh" min-width="80" />
|
||||
<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" 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"
|
||||
@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 } from "@/api/teachOffice/office"
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
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
|
||||
},
|
||||
// 表单参数
|
||||
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('导入失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.teach-office {
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,906 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="班历设置"
|
||||
width="94%"
|
||||
top="4vh"
|
||||
:close-on-click-modal="false"
|
||||
class="class-calendar-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<div class="class-calendar">
|
||||
<!-- ==================== 1. 学期与班次信息 ==================== -->
|
||||
<div class="info-panel">
|
||||
<div class="info-title-row">
|
||||
<span class="semester-name">{{ semesterName }}</span>
|
||||
<span class="class-name">班次{{ bc }}</span>
|
||||
</div>
|
||||
<div class="date-range-row">
|
||||
<div class="range-item">从{{ calStart }}到{{ calEnd }},共{{ calWeeks }}周</div>
|
||||
<div class="range-item">从{{ classStart }}到{{ classEnd }},共{{ classWeeks }}周</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 2. 设置面板(事件设置 + 操作按钮) ==================== -->
|
||||
<div class="settings-panel">
|
||||
<div class="event-settings-row">
|
||||
<div class="setting-item">
|
||||
<span class="setting-label">事件名称</span>
|
||||
<el-input v-model="eventName" size="small" style="width: 140px" placeholder="" />
|
||||
</div>
|
||||
<el-checkbox v-model="isBold" size="small">加粗显示</el-checkbox>
|
||||
<el-checkbox v-model="isSchedulable" size="small">可排课</el-checkbox>
|
||||
<el-checkbox v-model="isRegularClass" size="small">正课</el-checkbox>
|
||||
<el-checkbox v-model="showRemark" size="small">课表备注中显示</el-checkbox>
|
||||
<div class="setting-item">
|
||||
<span class="setting-label">备注</span>
|
||||
<el-input v-model="remark" size="small" style="width: 150px" placeholder="" />
|
||||
</div>
|
||||
<el-checkbox v-model="show78" size="small">显示7/8节</el-checkbox>
|
||||
<el-checkbox v-model="showEvening" size="small">显示晚上</el-checkbox>
|
||||
<el-checkbox v-model="showNight" size="small">显示夜间</el-checkbox>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 操作按钮区域 ==================== -->
|
||||
<div class="action-buttons-row">
|
||||
<button type="button" class="gray-btn" @click="handleAbsorb">吸取</button>
|
||||
<button type="button" class="gray-btn" @click="handleSet">设定</button>
|
||||
<button type="button" class="gray-btn" @click="handleDelete">删除</button>
|
||||
<button type="button" class="blue-btn" @click="handleApplyOther">选定区域设置应用于其它班次</button>
|
||||
<button type="button" class="gray-btn" @click="handleApplyWhole">整个班历应用于其它班次</button>
|
||||
<button type="button" class="gray-btn" @click="handleRefresh">刷新</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 4. 时间编排区域 ==================== -->
|
||||
<div class="table-area">
|
||||
<div class="calendar-table-wrapper">
|
||||
<table class="calendar-table">
|
||||
<thead>
|
||||
<tr class="head-row-1">
|
||||
<th rowspan="2" class="cell-week-head">周次</th>
|
||||
<th rowspan="2" class="cell-range-head">日期段</th>
|
||||
<th v-for="name in dayNames" :key="name" :colspan="visiblePeriods.length">{{ name }}</th>
|
||||
</tr>
|
||||
<tr class="head-row-2">
|
||||
<template v-for="(name, di) in dayNames">
|
||||
<th v-for="p in visiblePeriods" :key="name + '-' + p.key">{{ p.label }}</th>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(w, wi) in weekDefs" :key="w.num">
|
||||
<td class="week-num">{{ w.num }}</td>
|
||||
<td class="date-range">{{ w.start }}至{{ w.end }}</td>
|
||||
<template v-for="d in 5">
|
||||
<td
|
||||
v-for="p in visiblePeriods"
|
||||
:key="wi + '-' + (d - 1) + '-' + p.key"
|
||||
class="cell"
|
||||
:class="cellClass(getCell(wi, d - 1, p.key))"
|
||||
:style="cellStyle(getCell(wi, d - 1, p.key))"
|
||||
:title="getCell(wi, d - 1, p.key).isDate ? '该时间格无事件,可选中后设定事件' : '双击可吸取该事件设置'"
|
||||
@mousedown.prevent="onCellMouseDown(getCell(wi, d - 1, p.key), $event)"
|
||||
@mousemove="onCellMouseMove(getCell(wi, d - 1, p.key))"
|
||||
@dblclick="handleCellDblClick(getCell(wi, d - 1, p.key))"
|
||||
>{{ getCell(wi, d - 1, p.key).text }}</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="select-tip">
|
||||
提示:在时间编排区域按住鼠标拖动可连片多选,按住 Ctrl 键可用鼠标选择多个区域;双击事件格可吸取其设置。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 学员队选取弹窗 ==================== -->
|
||||
<ClassTeamSelectDialog
|
||||
:visible="teamSelectVisible"
|
||||
@update:visible="val => teamSelectVisible = val"
|
||||
@confirm="handleTeamConfirm"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ClassTeamSelectDialog from './ClassTeamSelectDialog.vue'
|
||||
|
||||
// ==================== 模块级常量 ====================
|
||||
|
||||
/** 时段定义:1-2、3-4、5-6 恒显示;7-8 / 9-10(晚上) / 夜间 由复选框控制 */
|
||||
const ALL_PERIODS = [
|
||||
{ key: '1-2', label: '1-2' },
|
||||
{ key: '3-4', label: '3-4' },
|
||||
{ key: '5-6', label: '5-6' },
|
||||
{ key: '7-8', label: '7-8' },
|
||||
{ key: '9-10', label: '9-10' },
|
||||
{ key: 'night', label: '夜间' }
|
||||
]
|
||||
|
||||
/** 事件模式下标 → ALL_PERIODS 下标(1-2、3-4、5-6、9-10) */
|
||||
const PATTERN_PERIOD_IDX = [0, 1, 2, 4]
|
||||
|
||||
/** 事件类型 → 颜色 */
|
||||
const TYPE_STYLE = {
|
||||
red: { bg: '#d94343', fg: '#ffffff' }, // 正常课程/活动(马基、保密、布雷、维修、布修、战术、国庆节、政工)
|
||||
dark: { bg: '#2a8a7f', fg: '#ffffff' }, // 深青/墨绿:游泳、道德、日期标记
|
||||
green: { bg: '#4f9d57', fg: '#ffffff' }, // 特殊课程/活动(核心、组训)
|
||||
cyan: { bg: '#8fd4e0', fg: '#14505a' } // 青/浅蓝:学前、元旦
|
||||
}
|
||||
|
||||
const E = (text, type) => ({ text, type })
|
||||
const D = null // 日期格:显示当天日期
|
||||
|
||||
/** 班历事件(第8周~第29周,严格按截图还原;null 为日期格) */
|
||||
const weekDefs = [
|
||||
// 学前适应(青)
|
||||
{
|
||||
num: 8, start: '08-21', end: '08-27',
|
||||
monday: [E('学前', 'cyan'), E('学前', 'cyan'), E('学前', 'cyan'), E('学前', 'cyan')],
|
||||
others: [E('学前', 'cyan'), E('学前', 'cyan'), E('学前', 'cyan'), E('学前', 'cyan')]
|
||||
},
|
||||
// 马基(红)+ 游泳(墨绿)
|
||||
{
|
||||
num: 9, start: '08-28', end: '09-03',
|
||||
monday: [E('马基', 'red'), E('游泳', 'dark'), D, D],
|
||||
others: [E('马基', 'red'), E('游泳', 'dark'), D, D]
|
||||
},
|
||||
{
|
||||
num: 10, start: '09-04', end: '09-10',
|
||||
monday: [E('马基', 'red'), E('游泳', 'dark'), D, D],
|
||||
others: [E('马基', 'red'), E('游泳', 'dark'), D, D]
|
||||
},
|
||||
// 马基(红)+ 保密(红)
|
||||
{
|
||||
num: 11, start: '09-11', end: '09-17',
|
||||
monday: [E('马基', 'red'), E('保密', 'red'), D, D],
|
||||
others: [E('马基', 'red'), E('保密', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 12, start: '09-18', end: '09-24',
|
||||
monday: [E('马基', 'red'), E('保密', 'red'), D, D],
|
||||
others: [E('马基', 'red'), E('保密', 'red'), D, D]
|
||||
},
|
||||
// 布雷(红)
|
||||
{
|
||||
num: 13, start: '09-25', end: '10-01',
|
||||
monday: [E('布雷', 'red'), E('布雷', 'red'), D, D],
|
||||
others: [E('布雷', 'red'), E('布雷', 'red'), D, D]
|
||||
},
|
||||
// 国庆节(红)
|
||||
{
|
||||
num: 14, start: '10-02', end: '10-08',
|
||||
monday: [E('国庆节', 'red'), E('国庆节', 'red'), E('国庆节', 'red'), E('国庆节', 'red')],
|
||||
others: [E('国庆节', 'red'), E('国庆节', 'red'), E('国庆节', 'red'), E('国庆节', 'red')]
|
||||
},
|
||||
{
|
||||
num: 15, start: '10-09', end: '10-15',
|
||||
monday: [E('布雷', 'red'), E('布雷', 'red'), D, D],
|
||||
others: [E('布雷', 'red'), E('布雷', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 16, start: '10-16', end: '10-22',
|
||||
monday: [E('布雷', 'red'), E('布雷', 'red'), D, D],
|
||||
others: [E('布雷', 'red'), E('布雷', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 17, start: '10-23', end: '10-29',
|
||||
monday: [E('布雷', 'red'), E('布雷', 'red'), D, D],
|
||||
others: [E('布雷', 'red'), E('布雷', 'red'), D, D]
|
||||
},
|
||||
// 维修(红)
|
||||
{
|
||||
num: 18, start: '10-30', end: '11-05',
|
||||
monday: [E('维修', 'red'), E('维修', 'red'), D, D],
|
||||
others: [E('维修', 'red'), E('维修', 'red'), D, D]
|
||||
},
|
||||
// 维修(红)+ 核心(绿)
|
||||
{
|
||||
num: 19, start: '11-06', end: '11-12',
|
||||
monday: [E('维修', 'red'), E('维修', 'red'), E('核心', 'green'), D],
|
||||
others: [E('维修', 'red'), E('维修', 'red'), E('核心', 'green'), D]
|
||||
},
|
||||
// 布修(红)
|
||||
{
|
||||
num: 20, start: '11-13', end: '11-19',
|
||||
monday: [E('布修', 'red'), E('布修', 'red'), D, D],
|
||||
others: [E('布修', 'red'), E('布修', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 21, start: '11-20', end: '11-26',
|
||||
monday: [E('布修', 'red'), E('布修', 'red'), D, D],
|
||||
others: [E('布修', 'red'), E('布修', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 22, start: '11-27', end: '12-03',
|
||||
monday: [E('布修', 'red'), E('布修', 'red'), D, D],
|
||||
others: [E('布修', 'red'), E('布修', 'red'), D, D]
|
||||
},
|
||||
// 维修(红)
|
||||
{
|
||||
num: 23, start: '12-04', end: '12-10',
|
||||
monday: [E('维修', 'red'), E('维修', 'red'), D, D],
|
||||
others: [E('维修', 'red'), E('维修', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 24, start: '12-11', end: '12-17',
|
||||
monday: [E('维修', 'red'), E('维修', 'red'), D, D],
|
||||
others: [E('维修', 'red'), E('维修', 'red'), D, D]
|
||||
},
|
||||
{
|
||||
num: 25, start: '12-18', end: '12-24',
|
||||
monday: [E('维修', 'red'), E('维修', 'red'), D, D],
|
||||
others: [E('维修', 'red'), E('维修', 'red'), D, D]
|
||||
},
|
||||
// 战术(红)
|
||||
{
|
||||
num: 26, start: '12-25', end: '12-31',
|
||||
monday: [E('战术', 'red'), E('战术', 'red'), E('战术', 'red'), E('战术', 'red')],
|
||||
others: [E('战术', 'red'), E('战术', 'red'), E('战术', 'red'), E('战术', 'red')]
|
||||
},
|
||||
// 元旦(青,周一)+ 组训(绿,周二~周五)
|
||||
{
|
||||
num: 27, start: '01-01', end: '01-07',
|
||||
monday: [E('元旦', 'cyan'), E('元旦', 'cyan'), E('元旦', 'cyan'), E('元旦', 'cyan')],
|
||||
others: [E('组训', 'green'), E('组训', 'green'), E('组训', 'green'), E('组训', 'green')]
|
||||
},
|
||||
// 政工(红)+ 道德(墨绿)
|
||||
{
|
||||
num: 28, start: '01-08', end: '01-14',
|
||||
monday: [E('政工', 'red'), E('道德', 'dark'), E('道德', 'dark'), E('0106', 'dark')],
|
||||
others: [E('政工', 'red'), E('道德', 'dark'), E('道德', 'dark'), D]
|
||||
},
|
||||
{
|
||||
num: 29, start: '01-15', end: '01-21',
|
||||
monday: [E('政工', 'red'), E('道德', 'dark'), E('道德', 'dark'), E('0115', 'dark')],
|
||||
others: [E('政工', 'red'), E('道德', 'dark'), E('道德', 'dark'), D]
|
||||
}
|
||||
]
|
||||
|
||||
/** 第8周周一(起始日期) */
|
||||
const START_DATE = '2017-08-21'
|
||||
|
||||
export default {
|
||||
name: 'ClassCalendarDialog',
|
||||
components: { ClassTeamSelectDialog },
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 班次号(如 0203) */
|
||||
bc: { type: String, default: '0399' },
|
||||
/** 学期名称 */
|
||||
semesterName: { type: String, default: '2017年秋季学期' }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// ==================== 学期与班次信息 ====================
|
||||
/** 校历范围 */
|
||||
calStart: '2017-07-08',
|
||||
calEnd: '2018-02-11',
|
||||
calWeeks: 32,
|
||||
/** 班历范围(校历基础上为班次安排) */
|
||||
classStart: '2017-08-24',
|
||||
classEnd: '2018-02-05',
|
||||
classWeeks: 25,
|
||||
|
||||
// ==================== 事件设置区域 ====================
|
||||
eventName: '',
|
||||
isBold: false, // 加粗显示
|
||||
isSchedulable: false, // 可排课
|
||||
isRegularClass: false, // 正课
|
||||
showRemark: false, // 课表备注中显示
|
||||
remark: '',
|
||||
show78: false, // 显示7/8节
|
||||
showEvening: true, // 显示晚上(已勾选)
|
||||
showNight: false, // 显示夜间
|
||||
|
||||
// ==================== 班历表格数据 ====================
|
||||
dayNames: ['一', '二', '三', '四', '五'],
|
||||
weekDefs,
|
||||
allCells: this.buildCells(),
|
||||
cellMap: new Map(),
|
||||
selectedIds: new Set(),
|
||||
|
||||
// ==================== 学员队选取弹窗 ====================
|
||||
teamSelectVisible: false,
|
||||
/** 当前应用模式:region=选定区域 / whole=整个班历 */
|
||||
applyMode: 'region'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
/** 时间编排区域实际显示的时段(由三个复选框控制) */
|
||||
visiblePeriods() {
|
||||
return ALL_PERIODS.filter((p) => {
|
||||
if (p.key === '7-8') return this.show78
|
||||
if (p.key === '9-10') return this.showEvening
|
||||
if (p.key === 'night') return this.showNight
|
||||
return true
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 每次打开对话框时重置选择状态
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.selectedIds = new Set()
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 初始化非响应式拖拽状态
|
||||
this.dragActive = false
|
||||
this.dragMoved = false
|
||||
this.dragCtrl = false
|
||||
this.anchorCell = null
|
||||
this.anchorPos = { r: 0, c: 0 }
|
||||
this.lastPos = { r: 0, c: 0 }
|
||||
this.dragSnapshot = new Set()
|
||||
// 构建 cellMap 索引
|
||||
this.allCells.forEach((c) => this.cellMap.set(c.id, c))
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('mouseup', this.endSelect)
|
||||
document.addEventListener('click', this.onDocClick)
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.removeEventListener('mouseup', this.endSelect)
|
||||
document.removeEventListener('click', this.onDocClick)
|
||||
},
|
||||
methods: {
|
||||
/** 计算从起始日期偏移 n 周 + m 天后的 MMDD(替代 dayjs) */
|
||||
formatDateOffset(weeks, days) {
|
||||
const date = new Date(START_DATE + 'T00:00:00')
|
||||
date.setDate(date.getDate() + weeks * 7 + days)
|
||||
const mm = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(date.getDate()).padStart(2, '0')
|
||||
return mm + dd
|
||||
},
|
||||
|
||||
/** 根据周定义生成时间格数据(周一~周五 × 全部时段) */
|
||||
buildCells() {
|
||||
const cells = []
|
||||
weekDefs.forEach((w, wi) => {
|
||||
for (let d = 0; d < 5; d++) {
|
||||
const dateText = this.formatDateOffset(wi, d)
|
||||
const pattern = d === 0 ? w.monday : w.others
|
||||
for (let pi = 0; pi < ALL_PERIODS.length; pi++) {
|
||||
const period = ALL_PERIODS[pi]
|
||||
const isSpecialPeriod = period.key === '7-8' || period.key === 'night'
|
||||
const dj = PATTERN_PERIOD_IDX.indexOf(pi)
|
||||
const def = isSpecialPeriod ? null : (pattern[dj] !== undefined ? pattern[dj] : null)
|
||||
const isEvent = !!(def && def.text)
|
||||
cells.push({
|
||||
id: `${wi}-${d}-${period.key}`,
|
||||
weekIdx: wi,
|
||||
day: d,
|
||||
periodKey: period.key,
|
||||
dateText,
|
||||
text: isEvent ? def.text : dateText,
|
||||
isDate: !isEvent,
|
||||
type: isEvent ? def.type : 'dark',
|
||||
bold: false,
|
||||
schedulable: true,
|
||||
regular: false,
|
||||
remark: false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
return cells
|
||||
},
|
||||
|
||||
getCell(weekIdx, day, periodKey) {
|
||||
return this.cellMap.get(`${weekIdx}-${day}-${periodKey}`)
|
||||
},
|
||||
|
||||
/** 单元格样式:事件格用事件色;日期格按星期交替背景色(一、三、五深绿 / 二、四浅绿) */
|
||||
cellStyle(cell) {
|
||||
if (cell.isDate) {
|
||||
return cell.day % 2 === 0
|
||||
? { backgroundColor: '#2a8a7f', color: '#ffffff' }
|
||||
: { backgroundColor: '#d6e9e2', color: '#20604f' }
|
||||
}
|
||||
const st = TYPE_STYLE[cell.type]
|
||||
return { backgroundColor: st.bg, color: st.fg }
|
||||
},
|
||||
|
||||
/** 单元格类:选中态 / 选项语义 */
|
||||
cellClass(cell) {
|
||||
return {
|
||||
'is-event': !cell.isDate,
|
||||
'is-date': cell.isDate,
|
||||
'is-bold': !cell.isDate && cell.bold,
|
||||
selected: this.selectedIds.has(cell.id),
|
||||
'not-schedulable': !cell.isDate && !cell.schedulable,
|
||||
'is-regular': !cell.isDate && cell.regular
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 多选交互(拖动连片 + Ctrl 多区域) ====================
|
||||
/** 计算格子在当前显示列布局下的行列坐标 */
|
||||
getPos(cell) {
|
||||
const periodIdx = this.visiblePeriods.findIndex((p) => p.key === cell.periodKey)
|
||||
return { r: cell.weekIdx, c: cell.day * this.visiblePeriods.length + periodIdx }
|
||||
},
|
||||
|
||||
/** 计算 anchor 与 last 之间矩形内的所有格子 id */
|
||||
rectIds(a, b) {
|
||||
const r1 = Math.min(a.r, b.r), r2 = Math.max(a.r, b.r)
|
||||
const c1 = Math.min(a.c, b.c), c2 = Math.max(a.c, b.c)
|
||||
const ids = []
|
||||
this.allCells.forEach((cell) => {
|
||||
const p = this.getPos(cell)
|
||||
if (p.r >= r1 && p.r <= r2 && p.c >= c1 && p.c <= c2) ids.push(cell.id)
|
||||
})
|
||||
return ids
|
||||
},
|
||||
|
||||
updateSelection() {
|
||||
const ids = this.rectIds(this.anchorPos, this.lastPos)
|
||||
this.selectedIds = this.dragCtrl
|
||||
? new Set([...this.dragSnapshot, ...ids])
|
||||
: new Set(ids)
|
||||
},
|
||||
|
||||
onCellMouseDown(cell, e) {
|
||||
if (e.button !== 0) return
|
||||
this.dragActive = true
|
||||
this.dragMoved = false
|
||||
this.dragCtrl = e.ctrlKey || e.metaKey
|
||||
this.dragSnapshot = new Set(this.selectedIds)
|
||||
this.anchorCell = cell
|
||||
this.anchorPos = this.getPos(cell)
|
||||
this.lastPos = { ...this.anchorPos }
|
||||
// 非 Ctrl 按下时立即清空旧选择(Ctrl 拖动则保留并追加)
|
||||
if (!this.dragCtrl) this.selectedIds = new Set()
|
||||
},
|
||||
|
||||
onCellMouseMove(cell) {
|
||||
if (!this.dragActive) return
|
||||
const pos = this.getPos(cell)
|
||||
if (pos.r === this.lastPos.r && pos.c === this.lastPos.c) return
|
||||
this.lastPos = pos
|
||||
this.dragMoved = true
|
||||
this.updateSelection()
|
||||
},
|
||||
|
||||
endSelect() {
|
||||
if (!this.dragActive) return
|
||||
this.dragActive = false
|
||||
if (!this.dragMoved && this.anchorCell) {
|
||||
if (this.dragCtrl) {
|
||||
// Ctrl + 单击:切换单个格子
|
||||
const set = new Set(this.selectedIds)
|
||||
if (set.has(this.anchorCell.id)) set.delete(this.anchorCell.id)
|
||||
else set.add(this.anchorCell.id)
|
||||
this.selectedIds = set
|
||||
} else {
|
||||
// 普通单击:单选该格
|
||||
this.selectedIds = new Set([this.anchorCell.id])
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** 点击时间编排区域以外的空白区域时取消选择(按钮/输入框等交互元素不触发) */
|
||||
onDocClick(e) {
|
||||
const t = e.target
|
||||
if (!t || !t.closest) return
|
||||
if (t.closest('.calendar-table')) return
|
||||
if (t.closest('button, input, .el-button, .el-checkbox, .el-select, .el-input, .el-date-editor')) return
|
||||
this.selectedIds = new Set()
|
||||
},
|
||||
|
||||
// ==================== 事件操作 ====================
|
||||
/** 将事件格设置复制到工具栏(吸取) */
|
||||
applyToToolbar(cell) {
|
||||
this.eventName = cell.text
|
||||
this.isBold = cell.bold
|
||||
this.isSchedulable = cell.schedulable
|
||||
this.isRegularClass = cell.regular
|
||||
this.showRemark = cell.remark
|
||||
},
|
||||
|
||||
/** 吸取:将选中事件格的名称和选项设置复制到工具栏 */
|
||||
handleAbsorb() {
|
||||
const cell = [...this.selectedIds].map((id) => this.cellMap.get(id)).find((c) => c && !c.isDate)
|
||||
if (!cell) {
|
||||
this.$message.warning('请先选择要吸取的事件格')
|
||||
return
|
||||
}
|
||||
this.applyToToolbar(cell)
|
||||
this.$message.success('已吸取事件设置到工具栏,可像刷子一样快速设定')
|
||||
},
|
||||
|
||||
/** 双击事件格:直接吸取 */
|
||||
handleCellDblClick(cell) {
|
||||
if (cell.isDate) {
|
||||
this.$message.info('该时间格没有事件,无法吸取')
|
||||
return
|
||||
}
|
||||
this.applyToToolbar(cell)
|
||||
this.$message.success(`已吸取「${cell.text}」的设置到工具栏`)
|
||||
},
|
||||
|
||||
/** 设定:将事件名称和选项应用到所选时间格 */
|
||||
handleSet() {
|
||||
const ids = [...this.selectedIds]
|
||||
if (!ids.length) {
|
||||
this.$message.warning('请先在时间编排区域选择时间格')
|
||||
return
|
||||
}
|
||||
const name = this.eventName.trim()
|
||||
if (!name) {
|
||||
this.$message.warning('请先输入事件名称')
|
||||
return
|
||||
}
|
||||
ids.forEach((id) => {
|
||||
const c = this.cellMap.get(id)
|
||||
c.text = name
|
||||
c.isDate = false
|
||||
c.type = 'red'
|
||||
c.bold = this.isBold
|
||||
c.schedulable = this.isSchedulable
|
||||
c.regular = this.isRegularClass
|
||||
c.remark = this.showRemark
|
||||
})
|
||||
this.$message.success(`已为 ${ids.length} 个时间格设定事件「${name}」`)
|
||||
},
|
||||
|
||||
/** 删除:清除所选时间格的事件,恢复日期显示、低暗背景 */
|
||||
handleDelete() {
|
||||
const ids = [...this.selectedIds]
|
||||
if (!ids.length) {
|
||||
this.$message.warning('请先选择要删除事件的时间格')
|
||||
return
|
||||
}
|
||||
ids.forEach((id) => {
|
||||
const c = this.cellMap.get(id)
|
||||
c.isDate = true
|
||||
c.text = c.dateText
|
||||
c.bold = false
|
||||
c.schedulable = true
|
||||
c.regular = false
|
||||
c.remark = false
|
||||
})
|
||||
this.$message.success(`已删除 ${ids.length} 个时间格的事件`)
|
||||
},
|
||||
|
||||
/** 选定区域设置应用于其它班次:先选择时间格,再弹出学员队选取窗口 */
|
||||
handleApplyOther() {
|
||||
if (!this.selectedIds.size) {
|
||||
this.$message.warning('请先在时间编排区域选择时间格')
|
||||
return
|
||||
}
|
||||
this.applyMode = 'region'
|
||||
this.teamSelectVisible = true
|
||||
},
|
||||
|
||||
/** 整个班历应用于其它班次:弹出学员队选取窗口 */
|
||||
handleApplyWhole() {
|
||||
this.applyMode = 'whole'
|
||||
this.teamSelectVisible = true
|
||||
},
|
||||
|
||||
/** 学员队选取确认后应用 */
|
||||
handleTeamConfirm() {
|
||||
if (this.applyMode === 'whole') {
|
||||
// 后端接口未提供,仅前端演示:将当前班历完整复制到所选班次
|
||||
this.$message.success('整个班历已完整复制到所选班次(后端接口未提供,前端演示)')
|
||||
} else {
|
||||
this.$message.success('已应用选定区域设置到所选班次(前端演示)')
|
||||
}
|
||||
},
|
||||
|
||||
/** 刷新:恢复初始班历数据 */
|
||||
handleRefresh() {
|
||||
this.allCells.splice(0, this.allCells.length, ...this.buildCells())
|
||||
this.cellMap.clear()
|
||||
this.allCells.forEach((c) => this.cellMap.set(c.id, c))
|
||||
this.selectedIds = new Set()
|
||||
this.eventName = ''
|
||||
this.$message.success('已刷新班历')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// `class` 会直接加在 .el-dialog 元素自身,因此高度直接写在这里(不用 :deep)
|
||||
.class-calendar-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 92vh;
|
||||
margin: 4vh auto;
|
||||
overflow: hidden;
|
||||
|
||||
::v-deep .el-dialog__header {
|
||||
flex-shrink: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
::v-deep .el-dialog__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 14px 18px 18px;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.class-calendar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
|
||||
// ========== 1. 学期与班次信息 ==========
|
||||
.info-panel {
|
||||
flex-shrink: 0;
|
||||
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: 22px;
|
||||
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 {
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 12px 20px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.event-settings-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 14px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
.setting-label {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 3. 银灰色 / 蓝色边框按钮 ==========
|
||||
.gray-btn {
|
||||
min-width: 80px;
|
||||
height: 28px;
|
||||
padding: 0 14px;
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
background: linear-gradient(180deg, #fdfdfd 0%, #ececec 50%, #dcdcdc 100%);
|
||||
border: 1px solid #7a7a7a;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f4f4f4 50%, #e6e6e6 100%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #c8c8c8;
|
||||
}
|
||||
}
|
||||
|
||||
.blue-btn {
|
||||
min-width: 190px;
|
||||
height: 28px;
|
||||
padding: 0 14px;
|
||||
font-size: 12px;
|
||||
color: #1e6fff;
|
||||
background: #ecf5ff;
|
||||
border: 1px solid #1e6fff;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #d9ecff;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #c6e2ff;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 4. 时间编排区域 ==========
|
||||
.table-area {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
.calendar-table-wrapper {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #dcdfe6;
|
||||
border-radius: 4px;
|
||||
&:hover { background: #c0c4cc; }
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
}
|
||||
|
||||
.select-tip {
|
||||
flex-shrink: 0;
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
border-top: 1px solid #ebeef5;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.calendar-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
font-size: 12px;
|
||||
user-select: none;
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
|
||||
th {
|
||||
background: #f5f7fa;
|
||||
border: 1px solid #ebeef5;
|
||||
color: #303133;
|
||||
font-weight: 600;
|
||||
height: 28px;
|
||||
padding: 0 4px;
|
||||
text-align: center;
|
||||
min-width: 52px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
td {
|
||||
&.week-num,
|
||||
&.date-range {
|
||||
background: #fafafa;
|
||||
color: #303133;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.week-num {
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
&.date-range {
|
||||
width: 130px;
|
||||
}
|
||||
}
|
||||
|
||||
.cell {
|
||||
position: relative;
|
||||
height: 30px;
|
||||
padding: 0 2px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border: 1px solid #ebeef5;
|
||||
cursor: default;
|
||||
transition: filter 0.1s;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(0.92);
|
||||
}
|
||||
|
||||
&.is-event {
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// 选中高亮:蓝色描边
|
||||
&.selected {
|
||||
outline: 2px solid #1e6fff;
|
||||
outline-offset: -2px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// 加粗显示
|
||||
&.is-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
// 可排课未勾选 → 左上角灰色小方块(该时段全校不允许排课)
|
||||
&.not-schedulable::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
background: #c8c8c8;
|
||||
border: 1px solid #909399;
|
||||
}
|
||||
|
||||
// 正课 → 右上角蓝色小方块
|
||||
&.is-regular::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
background: #1e6fff;
|
||||
border: 1px solid #0b4bc0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="教学班次学期信息明细"
|
||||
width="720px"
|
||||
class="class-detail-dialog"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<el-form label-width="100px" class="detail-form">
|
||||
<el-row :gutter="24">
|
||||
<!-- 左列 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="班次">
|
||||
<el-input v-model="form.bc" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="专业">
|
||||
<el-input v-model="form.xkzy" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="年级">
|
||||
<el-input v-model="form.nj" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="学期">
|
||||
<div class="semester-field">
|
||||
<el-input v-model="form.xq" readonly />
|
||||
<el-input v-model="form.ghn" class="plan-input" placeholder="" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="开学日期">
|
||||
<el-date-picker v-model="form.kxrq" type="date" format="yyyy年M月d日" value-format="yyyy-MM-dd" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="form.jsrq" type="date" format="yyyy年M月d日" value-format="yyyy-MM-dd" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="学期周数">
|
||||
<el-input v-model="form.zs" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 右列 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学任务">
|
||||
<el-select v-model="form.jxrw" clearable placeholder="请选择" style="width: 100%">
|
||||
<el-option v-for="opt in taskOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学期层次">
|
||||
<el-select v-model="form.xqcc" style="width: 100%">
|
||||
<el-option v-for="opt in levelOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开放教员排课">
|
||||
<el-checkbox v-model="form.kfpy" />
|
||||
</el-form-item>
|
||||
<el-form-item label="查找教室">
|
||||
<el-select v-model="form.zxjs" style="width: 100%">
|
||||
<el-option v-for="opt in roomOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="教学楼">
|
||||
<el-select v-model="form.jxl" style="width: 100%">
|
||||
<el-option v-for="opt in buildingOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专用教室">
|
||||
<el-select v-model="form.zyjs" style="width: 100%">
|
||||
<el-option v-for="opt in zyjsOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 备注 -->
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ClassSemesterDetailDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 选中的班次信息 */
|
||||
classInfo: { type: Object, default: null },
|
||||
/** 学期名称 */
|
||||
semesterName: { type: String, default: '2017年秋季学期' }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
bc: '班次0633', // 班次
|
||||
xkzy: '专业209', // 专业
|
||||
nj: '2017级', // 年级
|
||||
xq: this.semesterName, // 学期
|
||||
ghn: '规划内', // 规划内
|
||||
kxrq: '2017-09-03', // 开学日期
|
||||
jsrq: '2018-02-11', // 结束日期
|
||||
zs: 24, // 学期周数
|
||||
jxrw: '', // 教学任务
|
||||
xqcc: '第1学期', // 学期层次
|
||||
kfpy: true, // 开放教员排课
|
||||
zxjs: '10-03&10-03(50)', // 查找教室
|
||||
jxl: '5号楼', // 教学楼
|
||||
zyjs: '作战实验中心学术报告厅', // 专用教室
|
||||
bz: '' // 备注
|
||||
},
|
||||
taskOptions: ['2017年下半年教学任务', '研究生2017下半年教学任务'],
|
||||
levelOptions: ['第1学期', '第2学期', '第3学期'],
|
||||
roomOptions: ['10-03&10-03(50)', '10-04&10-04(40)', '9-01'],
|
||||
buildingOptions: ['5号楼', '6号楼', '综合楼'],
|
||||
zyjsOptions: ['作战实验中心学术报告厅', '综合教学楼101', '学术报告厅']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 每次打开时按传入的班次信息初始化表单
|
||||
visible(val) {
|
||||
if (!val) return
|
||||
this.form.bc = (this.classInfo && this.classInfo.bc) || '班次0633'
|
||||
this.form.xkzy = (this.classInfo && this.classInfo.xkzy) || '专业209'
|
||||
this.form.nj = (this.classInfo && this.classInfo.nj) || '2017级'
|
||||
this.form.xq = this.semesterName
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleConfirm() {
|
||||
this.$emit('confirm')
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.class-detail-dialog {
|
||||
.detail-form {
|
||||
// 只读输入框灰色底
|
||||
::v-deep .el-input__inner[readonly] {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.semester-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
|
||||
.el-input:first-child {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.plan-input {
|
||||
flex-shrink: 0;
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,439 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="学员队选取"
|
||||
width="90%"
|
||||
top="5vh"
|
||||
:close-on-click-modal="false"
|
||||
class="team-select-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<div class="team-select">
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<div class="query-panel">
|
||||
<el-form label-width="88px" class="query-form">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业">
|
||||
<div class="check-field">
|
||||
<el-checkbox v-model="queryForm.zyEnabled" />
|
||||
<el-select v-model="queryForm.zy" :disabled="!queryForm.zyEnabled" style="flex: 1">
|
||||
<el-option v-for="opt in zyOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="年级">
|
||||
<div class="check-field">
|
||||
<el-checkbox v-model="queryForm.njEnabled" />
|
||||
<el-input v-model="queryForm.nj" :disabled="!queryForm.njEnabled" placeholder="" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="在校状态">
|
||||
<div class="check-field">
|
||||
<el-checkbox v-model="queryForm.zxztEnabled" />
|
||||
<el-select v-model="queryForm.zxzt" :disabled="!queryForm.zxztEnabled" style="flex: 1">
|
||||
<el-option v-for="opt in zxztOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学员队名称">
|
||||
<div class="check-field">
|
||||
<el-checkbox v-model="queryForm.xydmcEnabled" />
|
||||
<el-input v-model="queryForm.xydmc" :disabled="!queryForm.xydmcEnabled" placeholder="" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="任务类别">
|
||||
<div class="check-field">
|
||||
<el-checkbox v-model="queryForm.rwlbEnabled" />
|
||||
<el-select v-model="queryForm.rwlb" :disabled="!queryForm.rwlbEnabled" style="flex: 1">
|
||||
<el-option v-for="opt in rwlbOptions" :key="opt" :label="opt" :value="opt" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<!-- 分页控制区域 -->
|
||||
<div class="pager-row">
|
||||
<button type="button" class="gray-btn" @click="handleQuery">查询</button>
|
||||
<button type="button" class="gray-btn" @click="handleFirst">首页</button>
|
||||
<button type="button" class="gray-btn" @click="handlePrev">上页</button>
|
||||
<button type="button" class="gray-btn" @click="handleNext">下页</button>
|
||||
<button type="button" class="gray-btn" @click="handleLast">末页</button>
|
||||
<el-input-number v-model="currentPage" :min="1" size="small" controls-position="right" style="width: 90px" />
|
||||
<span class="pager-label">每页条数</span>
|
||||
<el-select v-model="pageSize" size="small" style="width: 70px">
|
||||
<el-option v-for="n in pageSizeOptions" :key="n" :label="String(n)" :value="n" />
|
||||
</el-select>
|
||||
<button type="button" class="gray-btn" @click="handleLocate">定位</button>
|
||||
<el-select v-model="displaySize" size="small" style="width: 80px">
|
||||
<el-option v-for="n in displaySizeOptions" :key="n" :label="String(n)" :value="n" />
|
||||
</el-select>
|
||||
<button type="button" class="blue-btn" @click="handleSetPageSize">设置页项数</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 2. 上方数据表格 ==================== -->
|
||||
<div class="table-panel">
|
||||
<el-table
|
||||
:data="teamList"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
size="small"
|
||||
class="team-table"
|
||||
@selection-change="handleTopSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column prop="xzdbm" label="行政队别名称" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xydmc" label="学员队名称" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nj" label="年级" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zy" label="专业" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="人数" width="60" align="center">
|
||||
<template slot-scope="{ row }">{{ row.rs }}人</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zxzt" label="在校状态" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rwlb" label="任务类别" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zyjs" label="专用教室" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rxrq" label="入学日期" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="byrq" label="毕业日期" width="120" align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 中间操作按钮区域 ==================== -->
|
||||
<div class="mid-actions">
|
||||
<span class="mid-label">已选择列表项</span>
|
||||
<button type="button" class="gray-btn" @click="handleAdd">加入</button>
|
||||
<button type="button" class="gray-btn" @click="handleRemove">移除</button>
|
||||
<button type="button" class="gray-btn" @click="handleClear">清除</button>
|
||||
<button type="button" class="gray-btn" @click="handleReset">重置</button>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 4. 下方数据表格(已选学员队列表) ==================== -->
|
||||
<div class="table-panel">
|
||||
<el-table
|
||||
:data="selectedList"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
class="team-table"
|
||||
@selection-change="handleBottomSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column prop="zy" label="专业" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xydmc" label="学员队名称" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nj" label="年级" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="人数" width="60" align="center">
|
||||
<template slot-scope="{ row }">{{ row.rs }}人</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="rwlb" label="任务类别" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zxzt" label="在校状态" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zyjs" label="专用教室" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rxrq" label="入学日期" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="byrq" label="毕业日期" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="bz" label="备注" width="80" align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<el-empty v-if="!selectedList.length" description="暂无已选学员队,请从上方表格加入" :image-size="60" />
|
||||
</div>
|
||||
|
||||
<!-- ==================== 5. 底部按钮区域 ==================== -->
|
||||
<div class="footer-actions">
|
||||
<button type="button" class="gray-btn" @click="handleConfirm">确定</button>
|
||||
<button type="button" class="gray-btn" @click="handleCancel">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ClassTeamSelectDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// ==================== 查询条件区域 ====================
|
||||
queryForm: {
|
||||
zyEnabled: false, // 专业启用复选框(未勾选)
|
||||
zy: '专业219', // 专业(默认值)
|
||||
njEnabled: true, // 年级启用复选框(已勾选)
|
||||
nj: '', // 年级(空值)
|
||||
zxztEnabled: false, // 在校状态启用复选框(未勾选)
|
||||
zxzt: '毕业', // 在校状态(默认值)
|
||||
xydmcEnabled: true, // 学员队名称启用复选框(已勾选)
|
||||
xydmc: '', // 学员队名称(空值)
|
||||
rwlbEnabled: false, // 任务类别启用复选框(未勾选)
|
||||
rwlb: '规划内' // 任务类别(默认值)
|
||||
},
|
||||
zyOptions: ['专业219', '专业220', '专业221'],
|
||||
zxztOptions: ['毕业', '在校'],
|
||||
rwlbOptions: ['规划内', '规划外'],
|
||||
|
||||
// ==================== 分页控制区域 ====================
|
||||
currentPage: 1,
|
||||
pageSize: 1,
|
||||
displaySize: 100,
|
||||
pageSizeOptions: [1, 5, 10, 20],
|
||||
displaySizeOptions: [50, 100, 200],
|
||||
|
||||
// ==================== 上方数据表格(可选学员队列表) ====================
|
||||
teamList: [
|
||||
{ xzdbm: '教学五系', xydmc: '班次0417', nj: '2016级', zy: '专业113', rs: 36, zxzt: '毕业', rwlb: '规划内', zyjs: '8-011', rxrq: '2016年8月26日', byrq: '2018年1月21日' },
|
||||
{ xzdbm: '教学七系', xydmc: '班次0423', nj: '2016级', zy: '专业114', rs: 9, zxzt: '毕业', rwlb: '规划内', zyjs: '8-212(南楼)', rxrq: '2016年8月26日', byrq: '2018年1月21日' },
|
||||
{ xzdbm: '教学七系', xydmc: '班次0411', nj: '2016级', zy: '专业112', rs: 38, zxzt: '毕业', rwlb: '规划内', zyjs: '6-203', rxrq: '2016年8月26日', byrq: '2018年1月21日' },
|
||||
{ xzdbm: '教学七系', xydmc: '班次0405', nj: '2016级', zy: '专业111', rs: 34, zxzt: '毕业', rwlb: '规划内', zyjs: '8-007', rxrq: '2016年8月26日', byrq: '2018年1月21日' },
|
||||
{ xzdbm: '教学五系', xydmc: '班次0429', nj: '2017级', zy: '专业117', rs: 43, zxzt: '毕业', rwlb: '规划内', zyjs: '6-202', rxrq: '2017年8月24日', byrq: '2019年1月21日' },
|
||||
{ xzdbm: '教学五系', xydmc: '班次0431', nj: '2017级', zy: '专业118', rs: 22, zxzt: '毕业', rwlb: '规划内', zyjs: '2-403', rxrq: '2017年8月24日', byrq: '2019年1月21日' },
|
||||
{ xzdbm: '教学七系', xydmc: '班次0425', nj: '2017级', zy: '专业115', rs: 19, zxzt: '毕业', rwlb: '规划内', zyjs: '2-406', rxrq: '2017年8月24日', byrq: '2019年1月21日' },
|
||||
{ xzdbm: '教学七系', xydmc: '班次0432', nj: '2017级', zy: '专业119', rs: 15, zxzt: '毕业', rwlb: '规划内', zyjs: '8-009(南楼)', rxrq: '2017年8月24日', byrq: '2019年1月21日' },
|
||||
{ xzdbm: '教学七系', xydmc: '班次0434', nj: '2017级', zy: '专业120', rs: 45, zxzt: '毕业', rwlb: '规划内', zyjs: '6-303', rxrq: '2017年8月24日', byrq: '2019年1月21日' },
|
||||
{ xzdbm: '教学六系', xydmc: '班次0427', nj: '2017级', zy: '专业116', rs: 64, zxzt: '毕业', rwlb: '规划内', zyjs: '2-501', rxrq: '2017年8月24日', byrq: '2019年1月21日' }
|
||||
],
|
||||
/** 上方表格多选 */
|
||||
topSelection: [],
|
||||
/** 下方数据表格(已选学员队列表) */
|
||||
selectedList: [],
|
||||
bottomSelection: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTopSelectionChange(rows) {
|
||||
this.topSelection = rows
|
||||
},
|
||||
handleBottomSelectionChange(rows) {
|
||||
this.bottomSelection = rows
|
||||
},
|
||||
|
||||
// ==================== 分页控制 ====================
|
||||
handleQuery() {
|
||||
this.$message.success('查询(前端演示)')
|
||||
},
|
||||
handleFirst() {
|
||||
this.currentPage = 1
|
||||
this.$message.success('已跳转首页')
|
||||
},
|
||||
handlePrev() {
|
||||
if (this.currentPage > 1) this.currentPage--
|
||||
},
|
||||
handleNext() {
|
||||
this.currentPage++
|
||||
},
|
||||
handleLast() {
|
||||
this.currentPage = this.teamList.length || 1
|
||||
},
|
||||
handleLocate() {
|
||||
this.$message.success(`已定位到第 ${this.currentPage} 页`)
|
||||
},
|
||||
handleSetPageSize() {
|
||||
this.$message.success(`每页显示条数已设置为 ${this.displaySize}`)
|
||||
},
|
||||
|
||||
// ==================== 中间操作按钮 ====================
|
||||
/** 加入:将上方表格选中行加入已选列表(去重) */
|
||||
handleAdd() {
|
||||
if (!this.topSelection.length) {
|
||||
this.$message.warning('请先在上方表格选择学员队')
|
||||
return
|
||||
}
|
||||
const existing = new Set(this.selectedList.map((r) => r.xydmc))
|
||||
let added = 0
|
||||
this.topSelection.forEach((r) => {
|
||||
if (!existing.has(r.xydmc)) {
|
||||
this.selectedList.push({ ...r, bz: '' })
|
||||
added++
|
||||
}
|
||||
})
|
||||
if (added) this.$message.success(`已加入 ${added} 个学员队`)
|
||||
else this.$message.info('所选学员队已在列表中')
|
||||
},
|
||||
|
||||
/** 移除:将下方表格选中行移除 */
|
||||
handleRemove() {
|
||||
if (!this.bottomSelection.length) {
|
||||
this.$message.warning('请先在下方表格选择要移除的学员队')
|
||||
return
|
||||
}
|
||||
const removeKeys = new Set(this.bottomSelection.map((r) => r.xydmc))
|
||||
this.selectedList = this.selectedList.filter((r) => !removeKeys.has(r.xydmc))
|
||||
this.$message.success(`已移除 ${this.bottomSelection.length} 个学员队`)
|
||||
},
|
||||
|
||||
/** 清除:清空已选列表 */
|
||||
handleClear() {
|
||||
if (!this.selectedList.length) {
|
||||
this.$message.info('已选列表为空')
|
||||
return
|
||||
}
|
||||
this.selectedList = []
|
||||
this.$message.success('已清空已选列表')
|
||||
},
|
||||
|
||||
/** 重置:清空已选列表并重置查询条件 */
|
||||
handleReset() {
|
||||
this.selectedList = []
|
||||
Object.assign(this.queryForm, {
|
||||
zyEnabled: false, zy: '专业219',
|
||||
njEnabled: true, nj: '',
|
||||
zxztEnabled: false, zxzt: '毕业',
|
||||
xydmcEnabled: true, xydmc: '',
|
||||
rwlbEnabled: false, rwlb: '规划内'
|
||||
})
|
||||
this.currentPage = 1
|
||||
this.$message.success('已重置')
|
||||
},
|
||||
|
||||
// ==================== 底部按钮 ====================
|
||||
handleConfirm() {
|
||||
if (!this.selectedList.length) {
|
||||
this.$message.warning('请先选择要应用的学员队')
|
||||
return
|
||||
}
|
||||
this.$emit('confirm', this.selectedList.slice())
|
||||
this.dialogVisible = false
|
||||
this.$message.success(`选定区域设置已应用于 ${this.selectedList.length} 个班次`)
|
||||
},
|
||||
handleCancel() {
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.team-select {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
|
||||
// ========== 1. 查询条件区域 ==========
|
||||
.query-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 12px 16px 8px;
|
||||
|
||||
.query-form {
|
||||
.check-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.pager-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
margin-top: 4px;
|
||||
|
||||
.pager-label {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 2/4. 表格区域 ==========
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 3. 中间操作按钮区域 ==========
|
||||
.mid-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
.mid-label {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
white-space: nowrap;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 5. 底部按钮区域 ==========
|
||||
.footer-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
// ========== 银灰色 / 蓝色边框按钮 ==========
|
||||
.gray-btn {
|
||||
min-width: 70px;
|
||||
height: 28px;
|
||||
padding: 0 14px;
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
background: linear-gradient(180deg, #fdfdfd 0%, #ececec 50%, #dcdcdc 100%);
|
||||
border: 1px solid #7a7a7a;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f4f4f4 50%, #e6e6e6 100%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #c8c8c8;
|
||||
}
|
||||
}
|
||||
|
||||
.blue-btn {
|
||||
min-width: 110px;
|
||||
height: 28px;
|
||||
padding: 0 14px;
|
||||
font-size: 12px;
|
||||
color: #1e6fff;
|
||||
background: #ecf5ff;
|
||||
border: 1px solid #1e6fff;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #d9ecff;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #c6e2ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,706 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:show-close="false"
|
||||
width="96%"
|
||||
top="3vh"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
class="peidang-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<!-- ==================== 自定义标题栏 ==================== -->
|
||||
<div slot="header">
|
||||
<div class="peidang-titlebar">
|
||||
<i class="el-icon-reading title-icon"></i>
|
||||
<span class="title-text">
|
||||
班次学期配档——{{ semesterName }}——{{ classLabel }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="peidang-body">
|
||||
<!-- ==================== 上半部分:左右分栏 ==================== -->
|
||||
<div class="upper">
|
||||
<!-- 左侧 75%:配档课程编组管理表格 -->
|
||||
<div class="table-area">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="displayCourses"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
size="small"
|
||||
max-height="240"
|
||||
class="peidang-table"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column prop="name" label="科目名称" width="100" align="left" show-overflow-tooltip />
|
||||
<el-table-column prop="short" label="简称" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="planStart" label="计划起始周" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="actualStart" label="实际起始周" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="endWeek" label="结束周" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="连排课" width="50" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-checkbox :value="row.continuous" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="priority" label="优先序数" width="50" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="weeklyHours" label="周学时" width="50" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="hours" label="学时" width="50" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="正课时间" width="60" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-checkbox :value="row.scheduleTime" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已排学时" width="50" align="center">
|
||||
<template slot-scope="{ row }">{{ courseStats(row).scheduled }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="未排学时" width="50" align="center">
|
||||
<template slot-scope="{ row }">{{ courseStats(row).remaining }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总班次任务数" width="70" align="center">
|
||||
<template slot-scope="{ row }">{{ row.continuous ? 1 : 1 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="配档编组任务数" width="80" align="center">
|
||||
<template slot-scope="{ row }">{{ row.continuous ? 2 : 1 }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 右侧 25%:配档课程属性设置区 + 优先序数上下移动 -->
|
||||
<div class="prop-area">
|
||||
<div class="prop-title">配档课程属性</div>
|
||||
<el-form label-width="72px" size="small" class="prop-form">
|
||||
<el-form-item label="周学时">
|
||||
<el-input-number v-model="propForm.weeklyHours" :min="1" :max="40" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="起始周次">
|
||||
<el-input-number v-model="propForm.startWeek" :min="startWeek" :max="endWeek" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束周次">
|
||||
<el-input-number v-model="propForm.endWeek" :min="startWeek" :max="endWeek" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="连排课">
|
||||
<el-checkbox v-model="propForm.continuous">单科独进</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="优先序数">
|
||||
<div class="priority-field">
|
||||
<el-input-number v-model="propForm.priority" :min="1" controls-position="right" style="width: 100%" />
|
||||
<el-button type="primary" plain icon="el-icon-arrow-up" @click="handlePriorityUp" />
|
||||
<el-button type="primary" plain icon="el-icon-arrow-down" @click="handlePriorityDown" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="配档编组">
|
||||
<el-input v-model="propForm.group" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" class="apply-btn" @click="handleApplyProp">应用属性</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 下半部分:配档显示区域(甘特图) ==================== -->
|
||||
<div class="gantt-area">
|
||||
<div class="gantt-head">
|
||||
<div class="gantt-label-col">
|
||||
<div class="gantt-label">课程 / 周次</div>
|
||||
</div>
|
||||
<div class="gantt-body">
|
||||
<!-- 行1:周次刻度(红色竖线为周刻度) -->
|
||||
<div class="gantt-row">
|
||||
<div
|
||||
v-for="w in weeks"
|
||||
:key="w"
|
||||
class="gantt-cell week-cell"
|
||||
:class="{ 'month-boundary': isMonthBoundary(w) }"
|
||||
>{{ w }}</div>
|
||||
</div>
|
||||
<!-- 行2:本周可安排正课学时 -->
|
||||
<div class="gantt-row info-row">
|
||||
<div
|
||||
v-for="w in weeks"
|
||||
:key="w"
|
||||
class="gantt-cell"
|
||||
:class="{ 'month-boundary': isMonthBoundary(w) }"
|
||||
>可排{{ weeklyCapacity }}</div>
|
||||
</div>
|
||||
<!-- 行3:已安排学时 / 剩余学时 -->
|
||||
<div class="gantt-row info-row">
|
||||
<div
|
||||
v-for="w in weeks"
|
||||
:key="w"
|
||||
class="gantt-cell"
|
||||
:class="{ 'month-boundary': isMonthBoundary(w) }"
|
||||
>
|
||||
<span class="sch">已{{ monthlyScheduled(w) }}</span>
|
||||
<span class="rem">余{{ Math.max(0, weeklyCapacity - monthlyScheduled(w)) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 课程甘特条 -->
|
||||
<div class="gantt-courses">
|
||||
<div v-for="course in displayCourses" :key="course.id" class="gantt-course">
|
||||
<div class="gantt-label-col">
|
||||
<div class="course-tag" :class="course.continuous ? 'tag-continuous' : 'tag-normal'">
|
||||
<span class="course-name">{{ course.name }}({{ course.short }})</span>
|
||||
<span class="course-hours">
|
||||
已排{{ courseStats(course).scheduled }}
|
||||
<template v-if="courseStats(course).remaining > 0">+{{ courseStats(course).remaining }}</template>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gantt-body">
|
||||
<div class="gantt-row bar-row">
|
||||
<div
|
||||
v-for="w in weeks"
|
||||
:key="w"
|
||||
class="gantt-cell bar-cell"
|
||||
:class="{
|
||||
'month-boundary': isMonthBoundary(w),
|
||||
'bar-active': w >= course.actualStart && w <= course.endWeek,
|
||||
'bar-continuous': course.continuous,
|
||||
'bar-normal': !course.continuous
|
||||
}"
|
||||
>
|
||||
<span v-if="w >= course.actualStart && w <= course.endWeek" class="bar-hours">
|
||||
{{ courseWeekHours(course)[w] || '' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部:本月可安排正课总学时(月刻度) -->
|
||||
<div class="gantt-foot">
|
||||
<div class="gantt-label-col">
|
||||
<div class="gantt-label">本月正课总学时</div>
|
||||
</div>
|
||||
<div class="gantt-body">
|
||||
<div class="gantt-row">
|
||||
<div
|
||||
v-for="w in weeks"
|
||||
:key="w"
|
||||
class="gantt-cell month-cell"
|
||||
:class="{ 'month-boundary': isMonthBoundary(w) }"
|
||||
>
|
||||
<span v-if="bottomCells[w] && isMonthEndWeek(w)" class="month-total">
|
||||
第{{ bottomCells[w].no }}月:可排{{ bottomCells[w].total }}(已排{{ bottomCells[w].scheduled }} + 余{{ bottomCells[w].remaining }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 底部操作 ==================== -->
|
||||
<div slot="footer">
|
||||
<div class="peidang-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PeidangEditDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 学年学期名称 */
|
||||
semesterName: { type: String, default: '2017-2018学年第一学期' },
|
||||
/** 班次标签(如 教学五系2016级专业0113班次0417) */
|
||||
classLabel: { type: String, default: '教学五系2016级专业0113班次0417' }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// ==================== 时间轴参数 ====================
|
||||
/** 该班次开学起始周次 */
|
||||
startWeek: 8,
|
||||
/** 该班次学期结束周次 */
|
||||
endWeek: 32,
|
||||
/** 该班次每周可安排的正课学时时数(去除不能排课学时) */
|
||||
weeklyCapacity: 40,
|
||||
/** 月刻度:每 4 周为一月(8-11 第1月,12-15 第2月...),虚线分隔 */
|
||||
monthBreaks: [12, 16, 20, 24, 28, 32],
|
||||
|
||||
// ==================== 配档课程数据 ====================
|
||||
courses: [
|
||||
// ---- 非连排课(按周学时安排,蓝色,每门独立一组) ----
|
||||
{ id: 'p1', name: '课程科目001', short: '政治', planStart: 8, actualStart: 8, endWeek: 23, continuous: false, priority: 1, weeklyHours: 4, hours: 60, scheduleTime: true, group: '组1' },
|
||||
{ id: 'p2', name: '课程科目002', short: '军事', planStart: 8, actualStart: 8, endWeek: 20, continuous: false, priority: 2, weeklyHours: 4, hours: 48, scheduleTime: true, group: '组2' },
|
||||
{ id: 'p3', name: '课程科目003', short: '战术', planStart: 8, actualStart: 10, endWeek: 21, continuous: false, priority: 3, weeklyHours: 4, hours: 44, scheduleTime: true, group: '组3' },
|
||||
{ id: 'p4', name: '课程科目004', short: '指挥', planStart: 8, actualStart: 12, endWeek: 22, continuous: false, priority: 4, weeklyHours: 4, hours: 40, scheduleTime: true, group: '组4' },
|
||||
// ---- 连排课(单科独进,红色,共为一组) ----
|
||||
{ id: 'p5', name: '课程科目005', short: '综合演练', planStart: 8, actualStart: 8, endWeek: 13, continuous: true, priority: 5, weeklyHours: 20, hours: 100, scheduleTime: true, group: '连排组' },
|
||||
{ id: 'p6', name: '课程科目006', short: '野营拉练', planStart: 14, actualStart: 14, endWeek: 16, continuous: true, priority: 6, weeklyHours: 24, hours: 48, scheduleTime: true, group: '连排组' }
|
||||
],
|
||||
|
||||
// ==================== 表格选中与属性设置 ====================
|
||||
currentCourse: null,
|
||||
propForm: {
|
||||
weeklyHours: 4,
|
||||
startWeek: 8,
|
||||
endWeek: 16,
|
||||
continuous: false,
|
||||
priority: 1,
|
||||
group: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
/** 周序列:8 ~ 32 */
|
||||
weeks() {
|
||||
const arr = []
|
||||
for (let w = this.startWeek; w <= this.endWeek; w++) arr.push(w)
|
||||
return arr
|
||||
},
|
||||
/** 月份信息:每月包含的周次与可安排正课学时 */
|
||||
months() {
|
||||
const list = []
|
||||
let mNo = 1
|
||||
let cur = this.startWeek
|
||||
while (cur <= this.endWeek) {
|
||||
const next = this.monthBreaks.find((b) => b > cur)
|
||||
const mEnd = Math.min((next === undefined ? this.endWeek + 1 : next) - 1, this.endWeek)
|
||||
list.push({ no: mNo, start: cur, end: mEnd, total: (mEnd - cur + 1) * this.weeklyCapacity })
|
||||
cur = mEnd + 1
|
||||
mNo++
|
||||
}
|
||||
return list
|
||||
},
|
||||
/** 底部每月汇总行数据:week -> 该月信息(仅月首格展示文字) */
|
||||
bottomCells() {
|
||||
const map = {}
|
||||
this.weeks.forEach((w) => {
|
||||
const m = this.months.find((item) => w >= item.start && w <= item.end)
|
||||
if (!m) return
|
||||
map[w] = {
|
||||
no: m.no,
|
||||
total: m.total,
|
||||
scheduled: this.monthlyScheduled(w),
|
||||
remaining: m.total - this.monthlyScheduled(w)
|
||||
}
|
||||
})
|
||||
return map
|
||||
},
|
||||
/** 表格展示顺序:非连排课在前,连排课在后;组内按实际起始周、优先序数排序 */
|
||||
displayCourses() {
|
||||
return [...this.courses].sort((a, b) => {
|
||||
if (a.continuous !== b.continuous) return a.continuous ? 1 : -1
|
||||
if (a.actualStart !== b.actualStart) return a.actualStart - b.actualStart
|
||||
return a.priority - b.priority
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (!val) return
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.tableRef) {
|
||||
this.$refs.tableRef.setCurrentRow(this.displayCourses[0])
|
||||
}
|
||||
this.currentCourse = this.displayCourses[0] || null
|
||||
this.syncPropForm()
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 是否为月边界列(左侧画虚线) */
|
||||
isMonthBoundary(week) {
|
||||
return this.monthBreaks.includes(week)
|
||||
},
|
||||
/** 是否为某月的结束周(仅月结束列展示文字) */
|
||||
isMonthEndWeek(week) {
|
||||
return this.months.some((m) => m.end === week)
|
||||
},
|
||||
|
||||
/** 某周所有课程已安排学时之和 */
|
||||
monthlyScheduled(week) {
|
||||
return this.courses.reduce((sum, c) => {
|
||||
const map = this.courseWeekHours(c)
|
||||
return sum + (map[week] !== undefined ? map[week] : 0)
|
||||
}, 0)
|
||||
},
|
||||
|
||||
/** 每门课程按周分布的安排学时 */
|
||||
courseWeekHours(course) {
|
||||
const map = {}
|
||||
let remaining = course.hours
|
||||
let w = course.actualStart
|
||||
while (remaining > 0 && w <= course.endWeek) {
|
||||
const h = Math.min(course.weeklyHours, remaining)
|
||||
map[w] = h
|
||||
remaining -= h
|
||||
w++
|
||||
}
|
||||
return map
|
||||
},
|
||||
|
||||
/** 课程计算属性:已排学时 / 未排学时 */
|
||||
courseStats(course) {
|
||||
const map = this.courseWeekHours(course)
|
||||
const scheduled = Object.keys(map).reduce((sum, k) => sum + map[k], 0)
|
||||
return { scheduled, remaining: Math.max(0, course.hours - scheduled) }
|
||||
},
|
||||
|
||||
handleCurrentChange(row) {
|
||||
this.currentCourse = row
|
||||
this.syncPropForm()
|
||||
},
|
||||
|
||||
/** 属性设置表单同步(右侧) */
|
||||
syncPropForm() {
|
||||
if (!this.currentCourse) return
|
||||
this.propForm.weeklyHours = this.currentCourse.weeklyHours
|
||||
this.propForm.startWeek = this.currentCourse.actualStart
|
||||
this.propForm.endWeek = this.currentCourse.endWeek
|
||||
this.propForm.continuous = this.currentCourse.continuous
|
||||
this.propForm.priority = this.currentCourse.priority
|
||||
this.propForm.group = this.currentCourse.group
|
||||
},
|
||||
|
||||
/** 属性设置保存:应用所选课程的配档属性 */
|
||||
handleApplyProp() {
|
||||
if (!this.currentCourse) {
|
||||
this.$message.warning('请先在表格中选择一门课程')
|
||||
return
|
||||
}
|
||||
const row = this.currentCourse
|
||||
row.weeklyHours = this.propForm.weeklyHours
|
||||
row.actualStart = this.propForm.startWeek
|
||||
row.endWeek = this.propForm.endWeek
|
||||
row.continuous = this.propForm.continuous
|
||||
row.priority = this.propForm.priority
|
||||
row.group = this.propForm.group
|
||||
this.$message.success('配档属性已应用(前端演示)')
|
||||
},
|
||||
|
||||
/** 优先序数上移:优先序数减 1 */
|
||||
handlePriorityUp() {
|
||||
if (!this.currentCourse) {
|
||||
this.$message.warning('请先在表格中选择一门课程')
|
||||
return
|
||||
}
|
||||
if (this.currentCourse.priority <= 1) {
|
||||
this.$message.info('已是最高优先序数')
|
||||
return
|
||||
}
|
||||
this.currentCourse.priority -= 1
|
||||
this.syncPropForm()
|
||||
},
|
||||
|
||||
/** 优先序数下移:优先序数加 1 */
|
||||
handlePriorityDown() {
|
||||
if (!this.currentCourse) {
|
||||
this.$message.warning('请先在表格中选择一门课程')
|
||||
return
|
||||
}
|
||||
this.currentCourse.priority += 1
|
||||
this.syncPropForm()
|
||||
},
|
||||
|
||||
// ==================== 底部操作 ====================
|
||||
handleConfirm() {
|
||||
this.$emit('confirm')
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.peidang-dialog {
|
||||
// ========== 自定义标题栏 ==========
|
||||
::v-deep .el-dialog__header {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.peidang-titlebar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
height: 40px;
|
||||
padding: 0 14px;
|
||||
background: linear-gradient(90deg, #0a246a 0%, #a6caf0 100%);
|
||||
color: #fff;
|
||||
|
||||
.title-icon {
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-dialog__body {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
::v-deep .el-dialog__footer {
|
||||
padding: 8px 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.peidang-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.peidang-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
// ========== 上半部分:左右分栏 ==========
|
||||
.upper {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
|
||||
// 左侧 75%:表格
|
||||
.table-area {
|
||||
flex: 3;
|
||||
min-width: 0;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
overflow: hidden;
|
||||
|
||||
.peidang-table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// 右侧 25%:属性设置
|
||||
.prop-area {
|
||||
flex: 1;
|
||||
min-width: 240px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 10px 12px;
|
||||
|
||||
.prop-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.prop-form {
|
||||
.priority-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
|
||||
.el-button {
|
||||
flex-shrink: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 下半部分:配档显示区域 ==========
|
||||
.gantt-area {
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
max-height: 320px;
|
||||
|
||||
.gantt-head,
|
||||
.gantt-course,
|
||||
.gantt-foot {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
min-width: 860px;
|
||||
}
|
||||
|
||||
.gantt-label-col {
|
||||
flex-shrink: 0;
|
||||
width: 210px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.gantt-label {
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.gantt-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.gantt-row {
|
||||
display: flex;
|
||||
|
||||
.gantt-cell {
|
||||
flex: 1;
|
||||
min-width: 34px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: #303133;
|
||||
border-right: 1px solid #ebeef5;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// 周刻度:顶部红色竖线
|
||||
.week-cell {
|
||||
font-weight: 600;
|
||||
color: #f56c6c;
|
||||
border-top: 2px solid #f56c6c;
|
||||
background: #fff5f5;
|
||||
}
|
||||
|
||||
.info-row .gantt-cell {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
|
||||
.sch {
|
||||
color: #1e6fff;
|
||||
}
|
||||
|
||||
.rem {
|
||||
color: #e6a23c;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
// 月刻度虚线
|
||||
.month-boundary {
|
||||
border-left: 1px dashed #909399;
|
||||
}
|
||||
|
||||
// 课程条
|
||||
.bar-cell {
|
||||
height: 26px;
|
||||
position: relative;
|
||||
|
||||
.bar-hours {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.bar-active {
|
||||
&.bar-normal {
|
||||
background: #409eff;
|
||||
color: #fff;
|
||||
|
||||
.bar-hours {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.bar-continuous {
|
||||
background: #f56c6c;
|
||||
color: #fff;
|
||||
|
||||
.bar-hours {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.month-cell {
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
|
||||
.month-total {
|
||||
font-size: 11px;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
background: #f4f4f5;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 2px;
|
||||
padding: 0 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gantt-course {
|
||||
.gantt-label-col {
|
||||
align-items: center;
|
||||
|
||||
.course-tag {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 1px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
|
||||
&.tag-normal {
|
||||
background: #ecf5ff;
|
||||
border: 1px solid #a0cfff;
|
||||
color: #337ecc;
|
||||
}
|
||||
|
||||
&.tag-continuous {
|
||||
background: #fef0f0;
|
||||
border: 1px solid #fbc4c4;
|
||||
color: #d63031;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.course-hours {
|
||||
font-size: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gantt-foot {
|
||||
.gantt-label-col {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,486 @@
|
||||
<template>
|
||||
<div class="app-container shift-semester-page">
|
||||
<!-- ==================== 1. 学年学期标题 ==================== -->
|
||||
<div class="list-title">{{ semesterName }}</div>
|
||||
|
||||
<!-- ==================== 2. 校历 / 预设日期信息区 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form class="search-form">
|
||||
<div class="date-group">
|
||||
<span class="date-group-label">校历</span>
|
||||
<el-form-item label="开学日期">
|
||||
<el-date-picker v-model="semester.kxrq" type="date" format="yyyy年M月d日" value-format="yyyy-MM-dd" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="semester.jsrq" type="date" format="yyyy年M月d日" value-format="yyyy-MM-dd" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="学期周数">
|
||||
<el-input-number v-model="semester.weeks" :min="1" controls-position="right" style="width: 90px" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="date-group">
|
||||
<span class="date-group-label">预设</span>
|
||||
<el-form-item label="开学日期">
|
||||
<el-date-picker v-model="preset.kxrq" type="date" format="yyyy年M月d日" value-format="yyyy-MM-dd" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="preset.jsrq" type="date" format="yyyy年M月d日" value-format="yyyy-MM-dd" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="学期周数">
|
||||
<el-input-number v-model="preset.weeks" :min="1" controls-position="right" style="width: 90px" />
|
||||
</el-form-item>
|
||||
<el-button class="absorb-btn" type="primary" plain @click="handleAbsorbDate">吸取日期</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 工具栏按钮区 ==================== -->
|
||||
<div class="list-toolbar">
|
||||
<div class="left-group">
|
||||
<!-- 新添:下拉列出可新建学期信息的班次 -->
|
||||
<el-dropdown trigger="click" @command="handleNewCommand">
|
||||
<el-button type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
<span>新添</span>
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" class="new-class-menu">
|
||||
<el-dropdown-item v-for="item in newableClasses" :key="item.bc" :command="item">
|
||||
{{ item.bc }}({{ item.xkzy }}、{{ item.nj }})
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<el-button type="primary" plain @click="handleAction('编辑')">编辑</el-button>
|
||||
<el-button type="primary" plain @click="handleQuickSetDates">快速设定学期日期</el-button>
|
||||
<el-button type="danger" @click="handleAction('删除')">删除</el-button>
|
||||
<el-button type="primary" plain @click="handleEditCalendar">编辑班历</el-button>
|
||||
<el-button type="primary" plain @click="handleAction('自动生成教学计划')">自动生成教学计划</el-button>
|
||||
<el-button type="primary" plain @click="handleAction('教学计划管理')">教学计划管理</el-button>
|
||||
|
||||
<!-- 序号排序:带下拉箭头,点击弹出排序方式 -->
|
||||
<el-dropdown trigger="click" @command="handleSortCommand">
|
||||
<el-button type="primary" plain>
|
||||
<span>{{ sortLabel }}</span>
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="xh">序号排序</el-dropdown-item>
|
||||
<el-dropdown-item command="bw">波次排序</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<el-button type="primary" plain @click="handleMerge">预设合班</el-button>
|
||||
<el-button type="primary" plain @click="handleAction('预设拆班')">预设拆班</el-button>
|
||||
<el-button type="primary" plain @click="handlePeidangEdit">配档编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 4. 班次学期信息列表 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="displayData"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
:span-method="spanMethod"
|
||||
:row-class-name="rowClassName"
|
||||
:header-cell-class-name="headerCellClassName"
|
||||
max-height="480"
|
||||
class="class-table"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column prop="xzdw" label="行政队别" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xh" label="班次序号" width="70" align="center" />
|
||||
<el-table-column prop="bc" label="班级" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rs" label="人数" width="55" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nj" label="年级" width="85" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xkzy" label="学科专业" width="85" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="kxrq" label="开学日期" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jsrq" label="结束日期" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xqcc" label="学期第次" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zyjs" label="专用教室" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jxrw" label="教学任务" min-width="160" align="left" show-overflow-tooltip />
|
||||
<el-table-column prop="zs" label="周数" width="55" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="kcrws" label="总课程数" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="kczs" label="总课时数" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="周学时" width="80" align="center">
|
||||
<template slot-scope="{ row }">{{ row.zxs.toFixed(2) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zxf" label="总学分" width="70" align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 教学班次学期信息明细弹窗(新添) ==================== -->
|
||||
<ClassSemesterDetailDialog
|
||||
:visible="detailVisible"
|
||||
:class-info="selectedNewClass"
|
||||
:semester-name="semesterName"
|
||||
@update:visible="val => detailVisible = val"
|
||||
@confirm="handleDetailConfirm"
|
||||
/>
|
||||
|
||||
<!-- ==================== 班历设置弹窗(编辑班历) ==================== -->
|
||||
<ClassCalendarDialog
|
||||
:visible="calendarVisible"
|
||||
:bc="currentRow ? currentRow.bc : ''"
|
||||
:semester-name="semesterName"
|
||||
@update:visible="val => calendarVisible = val"
|
||||
/>
|
||||
|
||||
<!-- ==================== 预设合班弹窗 ==================== -->
|
||||
<ClassTeamSelectDialog
|
||||
:visible="teamVisible"
|
||||
@update:visible="val => teamVisible = val"
|
||||
@confirm="handleTeamConfirm"
|
||||
/>
|
||||
|
||||
<!-- ==================== 班次学期配档编辑弹窗 ==================== -->
|
||||
<PeidangEditDialog
|
||||
:visible="peidangVisible"
|
||||
:semester-name="semesterName"
|
||||
:class-label="peidangClassLabel"
|
||||
@update:visible="val => peidangVisible = val"
|
||||
@confirm="handleAction('配档编辑')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ClassSemesterDetailDialog from './ClassSemesterDetailDialog.vue'
|
||||
import ClassCalendarDialog from './ClassCalendarDialog.vue'
|
||||
import ClassTeamSelectDialog from './ClassTeamSelectDialog.vue'
|
||||
import PeidangEditDialog from './PeidangEditDialog.vue'
|
||||
|
||||
export default {
|
||||
name: 'ShiftSemester',
|
||||
components: {
|
||||
ClassSemesterDetailDialog,
|
||||
ClassCalendarDialog,
|
||||
ClassTeamSelectDialog,
|
||||
PeidangEditDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// ==================== 1. 学年学期标题区 ====================
|
||||
semesterName: '2017-2018学年第一学期',
|
||||
|
||||
// ==================== 2. 校历 / 预设日期信息区 ====================
|
||||
/** 校历日期 */
|
||||
semester: {
|
||||
kxrq: '2017-07-08', // 校历开学日期
|
||||
jsrq: '2018-02-11', // 校历结束日期
|
||||
weeks: 32 // 学期周数
|
||||
},
|
||||
/** 预设(班次)日期 */
|
||||
preset: {
|
||||
kxrq: '2017-07-08', // 预设开学日期
|
||||
jsrq: '2018-02-11', // 预设结束日期
|
||||
weeks: 32 // 预设学期周数
|
||||
},
|
||||
|
||||
// ==================== 3. 工具栏按钮区 ====================
|
||||
/** 可新建学期信息的班次 */
|
||||
newableClasses: [
|
||||
{ bc: '班次0633', xkzy: '专业209', nj: '2017级' },
|
||||
{ bc: '班次0634', xkzy: '专业209', nj: '2017级' },
|
||||
{ bc: '班次0709', xkzy: '专业205', nj: '2017级' },
|
||||
{ bc: '班次0710', xkzy: '专业205', nj: '2017级' },
|
||||
{ bc: '班次0901', xkzy: '专业301', nj: '2017级' }
|
||||
],
|
||||
|
||||
/** 教学班次学期信息明细弹窗(新添) */
|
||||
detailVisible: false,
|
||||
selectedNewClass: null,
|
||||
|
||||
/** 班历设置弹窗(编辑班历) */
|
||||
calendarVisible: false,
|
||||
currentRow: null,
|
||||
|
||||
/** 预设合班弹窗 */
|
||||
teamVisible: false,
|
||||
|
||||
/** 配档编辑弹窗(班次学期配档)显示状态 */
|
||||
peidangVisible: false,
|
||||
/** 配档编辑弹窗标题(班次学期配档——...——班次) */
|
||||
peidangClassLabel: '',
|
||||
|
||||
/** 排序方式:xh=序号排序 / bw=波次排序 */
|
||||
sortType: 'xh',
|
||||
|
||||
/** 波次背景色(同一波次使用同一颜色连在一起显示) */
|
||||
bwColors: [
|
||||
'#e3f2fd', // 浅蓝
|
||||
'#e8f5e9', // 浅绿
|
||||
'#fff8e1', // 浅黄
|
||||
'#f3e5f5', // 浅紫
|
||||
'#e0f2f1' // 浅青
|
||||
],
|
||||
|
||||
// ==================== 4. 班次学期信息列表 ====================
|
||||
tableData: [
|
||||
// ---- 学员1队(跨 10 行) ----
|
||||
{ xzdw: '学员1队', xh: 1, bw: 1, bc: '0150', rs: 40, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-307', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 512, zxs: 21.33, zxf: 40 },
|
||||
{ xzdw: '学员1队', xh: 2, bw: 1, bc: '0151', rs: 40, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-307', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 512, zxs: 21.33, zxf: 40 },
|
||||
{ xzdw: '学员1队', xh: 3, bw: 1, bc: '0152', rs: 40, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-308', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 512, zxs: 21.33, zxf: 40 },
|
||||
{ xzdw: '学员1队', xh: 4, bw: 1, bc: '0153', rs: 40, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-308', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 512, zxs: 21.33, zxf: 40 },
|
||||
{ xzdw: '学员1队', xh: 5, bw: 1, bc: '0154', rs: 42, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-309', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 528, zxs: 22.0, zxf: 42 },
|
||||
{ xzdw: '学员1队', xh: 6, bw: 1, bc: '0155', rs: 42, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-309', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 528, zxs: 22.0, zxf: 42 },
|
||||
{ xzdw: '学员1队', xh: 7, bw: 1, bc: '0156', rs: 42, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-310', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 15, kczs: 540, zxs: 22.5, zxf: 43 },
|
||||
{ xzdw: '学员1队', xh: 8, bw: 1, bc: '0157', rs: 38, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-310', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 15, kczs: 540, zxs: 22.5, zxf: 43 },
|
||||
{ xzdw: '学员1队', xh: 9, bw: 1, bc: '0158', rs: 38, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-311', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 512, zxs: 21.33, zxf: 40 },
|
||||
{ xzdw: '学员1队', xh: 10, bw: 1, bc: '0159', rs: 38, nj: '2017级秋', xkzy: '专业5', kxrq: '2017-09-03', jsrq: '2018-02-05', xqcc: '第1学期', zyjs: '1-311', jxrw: '2017年下半年教学任务', zs: 24, kcrws: 14, kczs: 512, zxs: 21.33, zxf: 40 },
|
||||
// ---- 教学五系(跨 2 行) ----
|
||||
{ xzdw: '教学五系', xh: 11, bw: 2, bc: '0201', rs: 30, nj: '2016级', xkzy: '专业113', kxrq: '2017-08-24', jsrq: '2018-02-05', xqcc: '第3学期', zyjs: '6-202', jxrw: '2017年下半年教学任务', zs: 25, kcrws: 12, kczs: 480, zxs: 19.2, zxf: 36 },
|
||||
{ xzdw: '教学五系', xh: 12, bw: 2, bc: '0202', rs: 30, nj: '2016级', xkzy: '专业113', kxrq: '2017-08-24', jsrq: '2018-02-05', xqcc: '第3学期', zyjs: '6-202', jxrw: '2017年下半年教学任务', zs: 25, kcrws: 12, kczs: 480, zxs: 19.2, zxf: 36 },
|
||||
// ---- 教学七系(跨 3 行) ----
|
||||
{ xzdw: '教学七系', xh: 13, bw: 3, bc: '0203', rs: 36, nj: '2016级', xkzy: '专业115', kxrq: '2017-08-24', jsrq: '2018-02-05', xqcc: '第3学期', zyjs: '8-007', jxrw: '2017年下半年教学任务', zs: 25, kcrws: 13, kczs: 520, zxs: 20.8, zxf: 38 },
|
||||
{ xzdw: '教学七系', xh: 14, bw: 3, bc: '0204', rs: 36, nj: '2016级', xkzy: '专业115', kxrq: '2017-08-24', jsrq: '2018-02-05', xqcc: '第3学期', zyjs: '8-007', jxrw: '2017年下半年教学任务', zs: 25, kcrws: 13, kczs: 520, zxs: 20.8, zxf: 38 },
|
||||
{ xzdw: '教学七系', xh: 15, bw: 3, bc: '0205', rs: 36, nj: '2016级', xkzy: '专业115', kxrq: '2017-08-24', jsrq: '2018-02-05', xqcc: '第3学期', zyjs: '8-008', jxrw: '2017年下半年教学任务', zs: 25, kcrws: 13, kczs: 520, zxs: 20.8, zxf: 38 }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 排序方式标签 */
|
||||
sortLabel() {
|
||||
return this.sortType === 'bw' ? '波次排序' : '序号排序'
|
||||
},
|
||||
/** 根据排序方式展示列表:波次排序时按波次分组连排 */
|
||||
displayData() {
|
||||
if (this.sortType === 'bw') {
|
||||
return [...this.tableData].sort((a, b) => a.bw - b.bw || a.xh - b.xh)
|
||||
}
|
||||
return this.tableData
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 默认选中第一行 班次0150(高亮)
|
||||
this.$nextTick(() => {
|
||||
if (this.tableData.length && this.$refs.tableRef) {
|
||||
this.$refs.tableRef.setCurrentRow(this.tableData[0])
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// ==================== 2. 校历 / 预设日期 ====================
|
||||
/** 吸取日期:将校历日期复制到预设日期 */
|
||||
handleAbsorbDate() {
|
||||
this.preset.kxrq = this.semester.kxrq
|
||||
this.preset.jsrq = this.semester.jsrq
|
||||
this.preset.weeks = this.semester.weeks
|
||||
this.$message.success('已吸取校历日期到预设日期')
|
||||
},
|
||||
|
||||
/** 快速设定学期日期 */
|
||||
handleQuickSetDates() {
|
||||
this.$message.success('快速设定学期日期(前端演示)')
|
||||
},
|
||||
|
||||
// ==================== 3. 工具栏按钮区 ====================
|
||||
/** 通用操作(前端演示) */
|
||||
handleAction(name) {
|
||||
this.$message.success(`${name}(前端演示)`)
|
||||
},
|
||||
|
||||
/** 新添:从下拉选择班次后打开明细弹窗 */
|
||||
handleNewCommand(item) {
|
||||
if (typeof item === 'string') return
|
||||
this.selectedNewClass = item
|
||||
this.detailVisible = true
|
||||
},
|
||||
|
||||
handleDetailConfirm() {
|
||||
this.$message.success('已创建班次学期信息(前端演示)')
|
||||
},
|
||||
|
||||
/** 编辑班历 */
|
||||
handleEditCalendar() {
|
||||
if (!this.currentRow) {
|
||||
this.$message.warning('请先在列表中选择一条班次学期信息')
|
||||
return
|
||||
}
|
||||
this.calendarVisible = true
|
||||
},
|
||||
|
||||
/** 预设合班 */
|
||||
handleMerge() {
|
||||
this.teamVisible = true
|
||||
},
|
||||
handleTeamConfirm(teams) {
|
||||
this.$message.success(`预设合班已应用于 ${teams.length} 个班次(前端演示)`)
|
||||
},
|
||||
|
||||
/** 配档编辑:选择班次后打开班次学期配档窗口 */
|
||||
handlePeidangEdit() {
|
||||
if (!this.currentRow) {
|
||||
this.$message.warning('请先在列表中选择一个班次')
|
||||
return
|
||||
}
|
||||
const row = this.currentRow
|
||||
this.peidangClassLabel = `${row.xzdw}${row.nj}${row.xkzy}班次${row.bc}`
|
||||
this.peidangVisible = true
|
||||
},
|
||||
|
||||
handleSortCommand(command) {
|
||||
this.sortType = command
|
||||
},
|
||||
|
||||
/** 行样式:波次排序时同一波次使用同一背景色 */
|
||||
rowClassName({ row }) {
|
||||
if (this.sortType !== 'bw') return ''
|
||||
const colorIndex = (row.bw - 1) % this.bwColors.length
|
||||
return `bw-row bw-row-${colorIndex}`
|
||||
},
|
||||
|
||||
// ==================== 4. 班次学期信息列表 ====================
|
||||
handleCurrentChange(row) {
|
||||
this.currentRow = row
|
||||
},
|
||||
|
||||
/** 合并单元格:行政队别列(第一列)纵向合并相同值 */
|
||||
spanMethod({ rowIndex, columnIndex }) {
|
||||
if (columnIndex === 0) {
|
||||
const list = this.displayData
|
||||
const current = list[rowIndex]
|
||||
// 非分组首行,隐藏
|
||||
if (rowIndex > 0 && list[rowIndex - 1].xzdw === current.xzdw) {
|
||||
return { rowspan: 0, colspan: 0 }
|
||||
}
|
||||
// 统计连续相同行政队别的行数
|
||||
let rowspan = 1
|
||||
for (let i = rowIndex + 1; i < list.length; i++) {
|
||||
if (list[i].xzdw === current.xzdw) rowspan++
|
||||
else break
|
||||
}
|
||||
return { rowspan, colspan: 1 }
|
||||
}
|
||||
return { rowspan: 1, colspan: 1 }
|
||||
},
|
||||
|
||||
/** 表头特殊样式:总课程数 / 总课时数列红色框标注 */
|
||||
headerCellClassName({ column }) {
|
||||
if (column.property === 'kcrws' || column.property === 'kczs') {
|
||||
return 'red-header-cell'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.shift-semester-page {
|
||||
// ========== 1. 学年学期标题 ==========
|
||||
.list-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
padding-left: 10px;
|
||||
border-left: 4px solid var(--edu-green-primary);
|
||||
}
|
||||
|
||||
// ========== 2. 校历 / 预设日期信息区 ==========
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.date-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.date-group-label {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.absorb-btn {
|
||||
margin-left: auto;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 3. 工具栏按钮区 ==========
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 新建下拉菜单 ==========
|
||||
.new-class-menu {
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
// ========== 4. 数据表格区 ==========
|
||||
$bwColors: (#e3f2fd, #e8f5e9, #fff8e1, #f3e5f5, #e0f2f1);
|
||||
|
||||
.table-card {
|
||||
flex: 1;
|
||||
|
||||
.class-table {
|
||||
width: 100%;
|
||||
|
||||
// 波次背景色(同一合班波次使用同一背景颜色连在一起显示)
|
||||
@for $i from 0 through length($bwColors) - 1 {
|
||||
::v-deep(.el-table__body tr.bw-row-#{$i} > td.el-table__cell) {
|
||||
background-color: nth($bwColors, $i + 1);
|
||||
}
|
||||
|
||||
::v-deep(.el-table__body tr.bw-row-#{$i}:hover > td.el-table__cell) {
|
||||
background-color: nth($bwColors, $i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 当前行高亮(优先于波次背景色)
|
||||
::v-deep(.el-table__body tr.current-row > td.el-table__cell) {
|
||||
background-color: #e1f5ec;
|
||||
}
|
||||
|
||||
::v-deep(.el-table__body tr.current-row:hover > td.el-table__cell) {
|
||||
background-color: #e1f5ec;
|
||||
}
|
||||
|
||||
// 表头红色框标注列(总课程数 / 总课时数)
|
||||
::v-deep(th.red-header-cell) {
|
||||
border: 2px solid #f56c6c !important;
|
||||
background: #fdeaea !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,875 @@
|
||||
<template>
|
||||
<div class="app-container subject-page">
|
||||
<!-- ==================== 1. 顶部状态提示 ==================== -->
|
||||
<div class="status-tip">{{ statusTip }}</div>
|
||||
|
||||
<!-- ==================== 2. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm">
|
||||
<el-row :gutter="32">
|
||||
<!-- 左栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">课程别名</span>
|
||||
<el-input v-model="searchForm.kcbh" placeholder="请输入课程别名" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">简称</span>
|
||||
<el-input v-model="searchForm.jc" placeholder="请输入简称" clearable class="q-control" />
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">学分</span>
|
||||
<div class="q-control range-control">
|
||||
<el-input v-model="searchForm.xfMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="searchForm.xfMax" placeholder="0" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">学时</span>
|
||||
<div class="q-control range-control">
|
||||
<el-input v-model="searchForm.xsMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="searchForm.xsMax" placeholder="0" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.zcfsEnabled" />
|
||||
<span class="q-label">支持方式</span>
|
||||
<el-select v-model="searchForm.zcfs" class="q-control" :disabled="!searchForm.zcfsEnabled">
|
||||
<el-option v-for="item in zcfsOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.khlxEnabled" />
|
||||
<span class="q-label">考核类型</span>
|
||||
<el-select v-model="searchForm.khlx" class="q-control" :disabled="!searchForm.khlxEnabled">
|
||||
<el-option v-for="item in khlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">秘密等级</span>
|
||||
<el-select v-model="searchForm.mmdj" placeholder="请选择" class="q-control">
|
||||
<el-option v-for="item in mmdjOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.dgxzEnabled" />
|
||||
<span class="q-label">大纲性质</span>
|
||||
<el-radio-group v-model="searchForm.dgxz" class="q-control" :disabled="!searchForm.dgxzEnabled">
|
||||
<el-radio :label="'大纲课程'">大纲课程</el-radio>
|
||||
<el-radio :label="'非大纲课程'">非大纲课程</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.zzglEnabled" />
|
||||
<span class="q-label">政治类课程</span>
|
||||
<el-radio-group v-model="searchForm.zzgl" class="q-control" :disabled="!searchForm.zzglEnabled">
|
||||
<el-radio :label="'政治类'">政治类</el-radio>
|
||||
<el-radio :label="'非政治类'">非政治类</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<span class="q-label no-check">备注</span>
|
||||
<el-input v-model="searchForm.bz" placeholder="请输入备注" clearable class="q-control" />
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.jysEnabled" />
|
||||
<span class="q-label">教研室</span>
|
||||
<el-select v-model="searchForm.jys" class="q-control" :disabled="!searchForm.jysEnabled">
|
||||
<el-option v-for="item in jysOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.pxccEnabled" />
|
||||
<span class="q-label">培训层次</span>
|
||||
<el-select v-model="searchForm.pxcc" class="q-control" :disabled="!searchForm.pxccEnabled">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.pxlxEnabled" />
|
||||
<span class="q-label">培训类型</span>
|
||||
<el-select v-model="searchForm.pxlx" class="q-control" :disabled="!searchForm.pxlxEnabled">
|
||||
<el-option v-for="item in pxlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.kclxEnabled" />
|
||||
<span class="q-label">课程类型</span>
|
||||
<el-select v-model="searchForm.kclx" class="q-control" :disabled="!searchForm.kclxEnabled">
|
||||
<el-option v-for="item in kclxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.jsfsEnabled" />
|
||||
<span class="q-label">建设方式</span>
|
||||
<el-select v-model="searchForm.jsfs" class="q-control" :disabled="!searchForm.jsfsEnabled">
|
||||
<el-option v-for="item in jsfsOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.pjqkEnabled" />
|
||||
<span class="q-label">评选情况</span>
|
||||
<el-select v-model="searchForm.pjqk" class="q-control" :disabled="!searchForm.pjqkEnabled">
|
||||
<el-option v-for="item in pjqkOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.gljgEnabled" />
|
||||
<span class="q-label">管理机构</span>
|
||||
<el-select v-model="searchForm.gljg" class="q-control" :disabled="!searchForm.gljgEnabled">
|
||||
<el-option v-for="item in gljgOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.zyxzEnabled" />
|
||||
<span class="q-label">在用选项</span>
|
||||
<el-radio-group v-model="searchForm.zyxz" class="q-control" :disabled="!searchForm.zyxzEnabled">
|
||||
<el-radio :label="'在用'">在用</el-radio>
|
||||
<el-radio :label="'其他'">其他</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.bbxxEnabled" />
|
||||
<span class="q-label">版本选项</span>
|
||||
<el-radio-group v-model="searchForm.bbxx" class="q-control" :disabled="!searchForm.bbxxEnabled">
|
||||
<el-radio :label="'最新版本'">最新版本</el-radio>
|
||||
<el-radio :label="'存在多版本'">存在多版本</el-radio>
|
||||
<el-radio :label="'全部版本'">全部版本</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="query-field">
|
||||
<el-checkbox v-model="searchForm.bmbhEnabled" />
|
||||
<span class="q-label">别名包含规范名称</span>
|
||||
<el-radio-group v-model="searchForm.bmbh" class="q-control" :disabled="!searchForm.bmbhEnabled">
|
||||
<el-radio :label="'完全包含'">完全包含</el-radio>
|
||||
<el-radio :label="'未完全包含'">未完全包含</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="notice">注意:勾选"选择框"表示启用该项对应的查询条件,输入框非空表示启用查询条件。</div>
|
||||
<div class="query-footer">
|
||||
<el-button class="gray-btn" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 操作按钮区域 ==================== -->
|
||||
<el-card shadow="never" class="action-card">
|
||||
<div class="action-row">
|
||||
<el-button type="primary" @click="handleOpenDialog">新建课程科目</el-button>
|
||||
<el-button type="primary" @click="handleBatchDelete">删除所选</el-button>
|
||||
<el-button type="primary" @click="handleDownloadCourse">下载课程科目基本信息</el-button>
|
||||
<el-button type="primary" @click="handleDownloadTextbook">下载课程教材基本信息</el-button>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button type="primary" @click="handleDownloadTemplate">【课程科目数据文件模板】下载</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 4. 文件上传区域 ==================== -->
|
||||
<el-card shadow="never" class="upload-card">
|
||||
<div class="upload-row">
|
||||
<div class="upload-left">
|
||||
<el-button @click="handleSelectFile">选择文件</el-button>
|
||||
<span class="file-name" :class="{ 'has-file': selectedFile }">{{ fileName }}</span>
|
||||
<input ref="fileInputRef" type="file" style="display: none" @change="handleFileChange" />
|
||||
</div>
|
||||
<div class="upload-right">
|
||||
<el-checkbox v-model="coverExist">覆盖已存在课程科目</el-checkbox>
|
||||
<el-button type="primary" @click="handleUpload">上传数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 5. 红色提示文字 ==================== -->
|
||||
<div class="red-tip">
|
||||
提示:课程体系按"课程-专题-课题"构建的,课程名称的命名格式为"课程名称\专题名称\课题名称"或"课程名称\课题名称"。
|
||||
</div>
|
||||
|
||||
<!-- ==================== 6. 数据表格区域 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column prop="manage" label="管理" width="70" align="center" />
|
||||
<el-table-column prop="code" label="编码" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="name" label="课程名称" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="cat" label="分类" width="100" align="center" />
|
||||
<el-table-column prop="exam" label="考核类型方式" width="110" align="center" />
|
||||
<el-table-column prop="inClass" label="课内学时" width="90" align="center" />
|
||||
<el-table-column prop="outClass" label="课外学时" width="90" align="center" />
|
||||
<el-table-column prop="other" label="其他" width="80" align="center" />
|
||||
<el-table-column prop="textbook" label="教材" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="majors" label="开设课程专业名称" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="teacher" label="在职主讲教员" min-width="110" show-overflow-tooltip />
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
:current-page="pageNum"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
class="pagination-wrapper"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑课程科目弹窗 -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="1100px"
|
||||
:close-on-click-modal="false"
|
||||
class="add-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="120px" class="add-form" :status-icon="false">
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="编号" prop="bh">
|
||||
<el-input v-model="addForm.bh" placeholder="请输入编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="课标号" prop="kbh">
|
||||
<el-input v-model="addForm.kbh" placeholder="请输入课标号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="课程名称" prop="mc">
|
||||
<el-input v-model="addForm.mc" placeholder="请输入课程名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="适用专业" prop="syzy">
|
||||
<el-input v-model="addForm.syzy" placeholder="请输入适用专业" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="课时数" prop="kcs">
|
||||
<el-input-number v-model="addForm.kcs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="录入人编号" prop="zxrbh">
|
||||
<el-input v-model="addForm.zxrbh" placeholder="请输入录入人编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="录入时间">
|
||||
<el-input v-model="addForm.zxsj" placeholder="请输入录入时间" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="正文">
|
||||
<el-input v-model="addForm.zw" type="textarea" :rows="3" placeholder="请输入正文" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="addForm.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="classroom-section">
|
||||
<div class="classroom-header">
|
||||
<span class="classroom-title">课堂列表</span>
|
||||
<el-button type="primary" size="small" @click="handleAddClassroom">添加课堂</el-button>
|
||||
</div>
|
||||
<el-table :data="addForm.ktList" border size="small">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="课堂编号" width="140">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model="row.bh" placeholder="课堂编号" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="课堂次序" width="90">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input-number v-model="row.ktjc" :min="1" controls-position="right" class="w-full" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学内容" min-width="150">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model="row.jxnr" placeholder="教学内容" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学要点" min-width="150">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model="row.jxyd" placeholder="教学要点" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学方法" min-width="150">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model="row.jxff" placeholder="教学方法" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="主讲教员数" width="100">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input-number v-model="row.zjjys" :min="0" controls-position="right" class="w-full" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="辅讲教员数" width="100">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input-number v-model="row.fjjys" :min="0" controls-position="right" class="w-full" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学目的" min-width="150">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model="row.jxmd" placeholder="教学目的" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学要求" min-width="150">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model="row.jxyq" placeholder="教学要求" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center" fixed="right">
|
||||
<template slot-scope="{ $index }">
|
||||
<el-button type="text" class="text-danger" @click="handleDeleteClassroom($index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" :loading="addLoading" @click="handleSubmit">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 撤回弹窗 -->
|
||||
<el-dialog
|
||||
:visible="withdrawDialogVisible"
|
||||
title="撤回课程科目"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => withdrawDialogVisible = val"
|
||||
>
|
||||
<el-form :model="withdrawForm" label-width="100px">
|
||||
<el-form-item label="课程编号">
|
||||
<el-input v-model="withdrawForm.bh" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="撤回原因">
|
||||
<el-input v-model="withdrawForm.chyy" type="textarea" :rows="4" placeholder="请输入撤回原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleCancelWithdraw">取消</el-button>
|
||||
<el-button type="primary" :loading="withdrawLoading" @click="handleWithdraw">确定撤回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SubjectIndex',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 1. 顶部状态提示 ====================
|
||||
statusTip: '请输入查询条件',
|
||||
|
||||
// ==================== 下拉选项 ====================
|
||||
zcfsOptions: ['其他', '讲授', '研讨', '实操'],
|
||||
khlxOptions: ['讲座', '考试', '考查', '实操'],
|
||||
mmdjOptions: ['公开', '内部', '秘密', '机密'],
|
||||
jysOptions: ['未确定教研室', '军事基础教研室', '政治工作教研室', '装备保障教研室'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
pxlxOptions: ['军官基础教育', '士兵职业教育', '研究生教育', '其他'],
|
||||
kclxOptions: ['其他类', '公共基础', '专业基础', '专业核心'],
|
||||
jsfsOptions: ['其他', '自建', '共建', '引进'],
|
||||
pjqkOptions: ['无', '国家级', '军队级', '院校级'],
|
||||
gljgOptions: ['教务处', '教研室1', '教研室2'],
|
||||
|
||||
// ==================== 2. 查询条件 ====================
|
||||
searchForm: {
|
||||
kcbh: '',
|
||||
jc: '',
|
||||
xfMin: '',
|
||||
xfMax: '',
|
||||
xsMin: '',
|
||||
xsMax: '',
|
||||
zcfsEnabled: false,
|
||||
zcfs: '其他',
|
||||
khlxEnabled: false,
|
||||
khlx: '讲座',
|
||||
mmdj: '',
|
||||
dgxzEnabled: false,
|
||||
dgxz: '大纲课程',
|
||||
zzglEnabled: false,
|
||||
zzgl: '政治类',
|
||||
bz: '',
|
||||
jysEnabled: false,
|
||||
jys: '未确定教研室',
|
||||
pxccEnabled: false,
|
||||
pxcc: '无',
|
||||
pxlxEnabled: false,
|
||||
pxlx: '军官基础教育',
|
||||
kclxEnabled: false,
|
||||
kclx: '其他类',
|
||||
jsfsEnabled: false,
|
||||
jsfs: '其他',
|
||||
pjqkEnabled: false,
|
||||
pjqk: '无',
|
||||
gljgEnabled: false,
|
||||
gljg: '教务处',
|
||||
zyxzEnabled: true,
|
||||
zyxz: '在用',
|
||||
bbxxEnabled: true,
|
||||
bbxx: '最新版本',
|
||||
bmbhEnabled: false,
|
||||
bmbh: '完全包含'
|
||||
},
|
||||
|
||||
// ==================== 列表数据 ====================
|
||||
/** 模拟列表数据(后端接口未提供) */
|
||||
mockTableData: [
|
||||
{ id: 1, manage: '编辑', code: 'KCB001', name: '高等数学', cat: '公共基础', exam: '考试', inClass: 48, outClass: 16, other: '—', textbook: '高等数学(上册)', majors: '炮兵装备运用/通信工程', teacher: '张三' },
|
||||
{ id: 2, manage: '编辑', code: 'KCB002', name: '导弹发射原理', cat: '专业核心', exam: '考试', inClass: 40, outClass: 16, other: '—', textbook: '导弹发射原理', majors: '炮兵装备运用', teacher: '李四' },
|
||||
{ id: 3, manage: '编辑', code: 'KCB003', name: '通信原理', cat: '专业核心', exam: '考试', inClass: 48, outClass: 16, other: '—', textbook: '通信原理', majors: '通信工程', teacher: '王五' },
|
||||
{ id: 4, manage: '编辑', code: 'KCB004', name: '军事英语', cat: '公共基础', exam: '考查', inClass: 30, outClass: 8, other: '—', textbook: '军事英语教程', majors: '全军各专业', teacher: '赵六' },
|
||||
{ id: 5, manage: '编辑', code: 'KCB005', name: '联合作战指挥', cat: '专业核心', exam: '综合考核', inClass: 40, outClass: 20, other: '—', textbook: '联合作战指挥', majors: '军事指挥', teacher: '孙七' },
|
||||
{ id: 6, manage: '编辑', code: 'KCB006', name: '装备维修训练', cat: '实践环节', exam: '实操', inClass: 0, outClass: 48, other: '—', textbook: '装备维修手册', majors: '装备保障', teacher: '周八' }
|
||||
],
|
||||
loading: false,
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
selectedRows: [],
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
selectedFile: null,
|
||||
coverExist: false,
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
dialogVisible: false,
|
||||
addLoading: false,
|
||||
editLoading: false,
|
||||
isEdit: false,
|
||||
addForm: this.createEmptyForm(),
|
||||
rules: {
|
||||
bh: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||
kbh: [{ required: true, message: '请输入课标号', trigger: 'blur' }],
|
||||
mc: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
|
||||
syzy: [{ required: true, message: '请输入适用专业', trigger: 'blur' }],
|
||||
kcs: [{ required: true, message: '请输入课时数', trigger: 'blur' }],
|
||||
zxrbh: [{ required: true, message: '请输入录入人编号', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// ==================== 撤回弹窗 ====================
|
||||
withdrawDialogVisible: false,
|
||||
withdrawLoading: false,
|
||||
withdrawForm: { bh: '', chyy: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogTitle() {
|
||||
return this.isEdit ? '编辑课程科目' : '新增课程科目'
|
||||
},
|
||||
fileName() {
|
||||
return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 初始化表单(保证 getCurrentTime 可用)
|
||||
this.addForm = this.createEmptyForm()
|
||||
},
|
||||
mounted() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// ==================== 表单辅助 ====================
|
||||
getCurrentTime() {
|
||||
return new Date().toLocaleString('zh-CN', { hour12: false }).replace(/\//g, '-')
|
||||
},
|
||||
|
||||
/** 创建空白课程表单(含一条空课堂记录) */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '', kbh: '', mc: '', syzy: '', kcs: 0, bz: '', zxrbh: '', zxsj: this.getCurrentTime(),
|
||||
zxzt: '0', sbzt: '0', sbsj: '', sbrbh: '', chyy: '', zw: '', jsonzd: '', ktList: [this.defaultClassroom()]
|
||||
}
|
||||
},
|
||||
|
||||
/** 默认课堂项 */
|
||||
defaultClassroom() {
|
||||
return { bh: '', ktjc: 1, jxnr: '', jxyd: '', jxff: '', zjjys: 0, fjjys: 0, bz: '', jxmd: '', jxyq: '' }
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.addForm = this.createEmptyForm()
|
||||
},
|
||||
|
||||
// ==================== 列表加载 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getCourseTeachingList
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
this.tableData = [...this.mockTableData]
|
||||
this.total = this.mockTableData.length
|
||||
this.loading = false
|
||||
}, 200)
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
handleQuery() {
|
||||
const now = new Date()
|
||||
const hh = String(now.getHours()).padStart(2, '0')
|
||||
const mm = String(now.getMinutes()).padStart(2, '0')
|
||||
const ss = String(now.getSeconds()).padStart(2, '0')
|
||||
this.statusTip = `[${hh}:${mm}:${ss}]查询成功!共检索到${this.total || 982}条记录。`
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(current) {
|
||||
this.pageNum = current
|
||||
this.fetchList()
|
||||
},
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
|
||||
// ==================== 删除所选 ====================
|
||||
handleBatchDelete() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择要删除的记录')
|
||||
return
|
||||
}
|
||||
const ids = this.selectedRows.map((r) => r.id)
|
||||
this.tableData = this.tableData.filter((r) => ids.indexOf(r.id) === -1)
|
||||
this.total = this.tableData.length
|
||||
this.$message.success(`已删除所选 ${ids.length} 条记录(前端模拟)`)
|
||||
},
|
||||
|
||||
// ==================== 下载 ====================
|
||||
downloadBlob(content, filename) {
|
||||
const blob = new Blob(['\ufeff' + content], { type: 'text/plain;charset=utf-8;' })
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = filename
|
||||
link.click()
|
||||
URL.revokeObjectURL(link.href)
|
||||
},
|
||||
|
||||
handleDownloadCourse() {
|
||||
this.downloadBlob('编码,课程名称,分类,考核类型方式,课内学时,课外学时\n', '课程科目基本信息.txt')
|
||||
this.$message.success('课程科目基本信息已下载(前端模拟)')
|
||||
},
|
||||
handleDownloadTextbook() {
|
||||
this.downloadBlob('课程名称,教材,在职主讲教员\n', '课程教材基本信息.txt')
|
||||
this.$message.success('课程教材基本信息已下载(前端模拟)')
|
||||
},
|
||||
handleDownloadTemplate() {
|
||||
this.downloadBlob('编码,课程名称,分类,考核类型方式,课内学时,课外学时,教材,开设课程专业名称,在职主讲教员\n', '课程科目数据文件模板.txt')
|
||||
this.$message.success('【课程科目数据文件模板】已下载(前端模拟)')
|
||||
},
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
handleSelectFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
|
||||
handleFileChange(e) {
|
||||
const input = e.target
|
||||
this.selectedFile = (input.files && input.files[0]) || null
|
||||
},
|
||||
|
||||
handleUpload() {
|
||||
if (!this.selectedFile) {
|
||||
this.$message.warning('请先选择文件')
|
||||
return
|
||||
}
|
||||
this.$message.success(`文件「${this.selectedFile.name}」上传成功(前端模拟)`)
|
||||
},
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
handleOpenDialog() {
|
||||
this.isEdit = false
|
||||
this.resetForm()
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleAddClassroom() {
|
||||
this.addForm.ktList.push(this.defaultClassroom())
|
||||
},
|
||||
handleDeleteClassroom(index) {
|
||||
this.addForm.ktList.splice(index, 1)
|
||||
},
|
||||
|
||||
// TODO: 后端接口未提供,保存成功后刷新列表为前端模拟;接口就绪后替换为 addCourseTeaching/updateCourseTeaching
|
||||
handleSubmit() {
|
||||
this.$refs.addFormRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.addLoading = true
|
||||
setTimeout(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '保存成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
this.addLoading = false
|
||||
}, 300)
|
||||
})
|
||||
},
|
||||
|
||||
handleCancel() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
|
||||
// ==================== 撤回弹窗 ====================
|
||||
// TODO: 后端接口未提供,撤回为前端模拟;接口就绪后替换为 deleteCourseTeaching
|
||||
handleWithdraw() {
|
||||
if (!this.withdrawForm.chyy.trim()) {
|
||||
this.$message.warning('请输入撤回原因')
|
||||
return
|
||||
}
|
||||
this.withdrawLoading = true
|
||||
setTimeout(() => {
|
||||
this.$message.success('撤回成功')
|
||||
this.withdrawDialogVisible = false
|
||||
this.fetchList()
|
||||
this.withdrawLoading = false
|
||||
}, 300)
|
||||
},
|
||||
|
||||
handleCancelWithdraw() {
|
||||
this.withdrawDialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
// ==================== 1. 顶部状态提示 ====================
|
||||
.status-tip {
|
||||
display: inline-block;
|
||||
background: #dc3545;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
// ==================== 2. 查询条件区域 ====================
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.query-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
min-height: 32px;
|
||||
|
||||
::v-deep(.el-checkbox) {
|
||||
margin-right: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.q-label {
|
||||
width: 120px;
|
||||
flex-shrink: 0;
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
white-space: nowrap;
|
||||
|
||||
&.no-check {
|
||||
margin-left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.q-control {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.range-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.range-sep {
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice {
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
margin-top: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.query-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 3. 操作按钮区域 ====================
|
||||
.action-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.action-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 4. 文件上传区域 ====================
|
||||
.upload-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.upload-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
.upload-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.file-name {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
|
||||
&.has-file {
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 5. 红色提示文字 ====================
|
||||
.red-tip {
|
||||
font-size: 14px;
|
||||
color: #f56c6c;
|
||||
margin-bottom: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
// ==================== 6. 数据表格区域 ====================
|
||||
.table-card {
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
::v-deep(.el-table .cell) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
.add-dialog {
|
||||
::v-deep(.el-dialog__body) {
|
||||
max-height: 70vh;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.add-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.classroom-section {
|
||||
margin-top: 16px;
|
||||
|
||||
.classroom-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.classroom-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 课堂列表删除按钮红色文字
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.gray-btn {
|
||||
height: 28px;
|
||||
padding: 2px 16px;
|
||||
font-size: 12px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #c0c4cc;
|
||||
color: #333;
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: #ebebeb;
|
||||
border-color: #c0c4cc;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,487 @@
|
||||
<template>
|
||||
<div class="app-container task-plan-page">
|
||||
<!-- ==================== 1. 学期信息区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :inline="true" :model="semester" class="search-form">
|
||||
<el-form-item label="学期名称">
|
||||
<el-input v-model="semester.name" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="校历开学日期">
|
||||
<el-date-picker
|
||||
v-model="semester.kxrq"
|
||||
type="date"
|
||||
format="yyyy年M月d日"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择日期"
|
||||
style="width: 160px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker
|
||||
v-model="semester.jsrq"
|
||||
type="date"
|
||||
format="yyyy年M月d日"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择日期"
|
||||
style="width: 160px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="学期周数">
|
||||
<el-input v-model="semester.weeks" style="width: 90px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 数据表格区域 ==================== -->
|
||||
<div class="list-title">教学任务列表:</div>
|
||||
<div class="list-toolbar">
|
||||
<div class="left-group">
|
||||
<el-button type="primary" @click="handleAdd">新建</el-button>
|
||||
<el-button type="primary" plain @click="handleEdit">编辑</el-button>
|
||||
<el-button type="danger" plain @click="handleDelete">删除</el-button>
|
||||
<el-button type="primary" plain @click="handlePublish">发布教学任务</el-button>
|
||||
<el-button type="primary" plain @click="handleEndPublish">结束发布</el-button>
|
||||
<el-button type="primary" plain @click="handleManageTeams">管理教学任务所含学员队</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="loading"
|
||||
:data="tableData"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
class="task-table"
|
||||
@selection-change="handleSelectionChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column prop="rwmc" label="任务名称" min-width="170" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<span class="status-text">{{ row.zt }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fbsj" label="发布时间" width="130" align="center" />
|
||||
<el-table-column prop="cjsj" label="创建时间" width="130" align="center" />
|
||||
<el-table-column label="结束时间" width="130" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
{{ row.jssj || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jysCount" label="教研室数" width="90" align="center" />
|
||||
<el-table-column prop="teamCount" label="学员队数" width="90" align="center" />
|
||||
<el-table-column prop="hbqKcCount" label="合班前课程任务数" width="140" align="center" />
|
||||
<el-table-column prop="hbqXssCount" label="合班前总学时数" width="140" align="center" />
|
||||
<el-table-column prop="hbhKcCount" label="合班后课程任务数" width="140" align="center" />
|
||||
<el-table-column prop="hbhXssCount" label="合班后总学时数" width="140" align="center" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 教学任务信息弹窗 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="教学任务信息"
|
||||
width="900px"
|
||||
class="teaching-task-dialog"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => (dialogVisible = val)"
|
||||
>
|
||||
<!-- ==================== 1. 基本信息区域 ==================== -->
|
||||
<el-form label-width="86px" class="basic-form">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期">
|
||||
<el-input v-model="form.xq" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务名称">
|
||||
<el-input v-model="form.rwmc" placeholder="请输入任务名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="创建时间">
|
||||
<el-input v-model="form.cjsj" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发布时间">
|
||||
<el-input v-model="form.fbsj" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束时间">
|
||||
<el-input v-model="form.jssj" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<!-- ==================== 2. Tab 标签页区域 ==================== -->
|
||||
<el-tabs v-model="activeTab" class="tt-tabs">
|
||||
<!-- 教研室任务书列表 -->
|
||||
<el-tab-pane label="教研室任务书列表" name="taskbook">
|
||||
<div class="sub-toolbar">
|
||||
<el-button type="primary" plain size="small" @click="handleTaskBookDetail">
|
||||
教研室任务书详细
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
ref="taskBookTable"
|
||||
:data="taskBookRows"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
class="taskbook-table"
|
||||
@selection-change="handleTaskBookSelection"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column prop="jys" label="教研室" min-width="120" align="center" />
|
||||
<el-table-column prop="zt" label="状态" width="80" align="center" />
|
||||
<el-table-column prop="sbsj" label="上报时间" width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xydkcCount" label="学员队课程任务数" width="150" align="center" />
|
||||
<el-table-column prop="wczdsCount" label="完成指定数" width="100" align="center" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 学员队列表 -->
|
||||
<el-tab-pane label="学员队列表" name="team">
|
||||
<div class="tab-empty">暂无学员队列表数据</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- ==================== 3. 底部按钮区域 ==================== -->
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// ==================== 1. 学期信息区域 ====================
|
||||
semester: {
|
||||
name: '2017年秋季学期', // 学期名称
|
||||
kxrq: '2017-07-08', // 校历开学日期
|
||||
jsrq: '2018-02-11', // 结束日期
|
||||
weeks: 32 // 学期周数
|
||||
},
|
||||
|
||||
// ==================== 2. 数据表格 ====================
|
||||
loading: false,
|
||||
tableData: [
|
||||
{
|
||||
bh: 'task-2017-2',
|
||||
rwmc: '2017年下半年教学任务',
|
||||
zt: '发布',
|
||||
fbsj: '2017年12月1日',
|
||||
cjsj: '2017年7月8日',
|
||||
jssj: '',
|
||||
jysCount: 31,
|
||||
teamCount: 78,
|
||||
hbqKcCount: 1126,
|
||||
hbqXssCount: 36050,
|
||||
hbhKcCount: 1058,
|
||||
hbhXssCount: 34050
|
||||
},
|
||||
{
|
||||
bh: 'task-2019-1',
|
||||
rwmc: '研究生下半年教学任务',
|
||||
zt: '发布',
|
||||
fbsj: '2019年12月1日',
|
||||
cjsj: '2017年7月8日',
|
||||
jssj: '',
|
||||
jysCount: 12,
|
||||
teamCount: 2,
|
||||
hbqKcCount: 16,
|
||||
hbqXssCount: 560,
|
||||
hbhKcCount: 16,
|
||||
hbhXssCount: 560
|
||||
}
|
||||
],
|
||||
selectedRows: [],
|
||||
currentRow: null,
|
||||
|
||||
// ==================== 操作按钮 ====================
|
||||
/** 教学任务信息弹窗 */
|
||||
dialogVisible: false,
|
||||
/** 弹窗模式:新建 / 编辑 */
|
||||
dialogMode: 'create',
|
||||
/** 编辑模式选中的任务行 */
|
||||
editRow: null,
|
||||
|
||||
// ==================== 弹窗:基本信息 ====================
|
||||
form: {
|
||||
xq: '2017年秋季学期', // 学期(只读)
|
||||
rwmc: '', // 任务名称(可编辑)
|
||||
cjsj: '', // 创建时间(只读)
|
||||
fbsj: '', // 发布时间(只读)
|
||||
jssj: '' // 结束时间(只读)
|
||||
},
|
||||
|
||||
// ==================== 弹窗:Tab 标签页 ====================
|
||||
activeTab: 'taskbook',
|
||||
|
||||
// ==================== 弹窗:教研室任务书列表 ====================
|
||||
taskBookRows: [],
|
||||
selectedTaskBookRows: [],
|
||||
/** 编辑模式下的教研室任务书数据(按截图还原) */
|
||||
editTaskBookRows: [
|
||||
{ jys: '军事81教研室', zt: '发布', sbsj: '', xydkcCount: 33, wczdsCount: 0 },
|
||||
{ jys: '翻译室', zt: '发布', sbsj: '', xydkcCount: 2, wczdsCount: 0 },
|
||||
{ jys: '军事共同教研室', zt: '上报', sbsj: '2019-12-13 10:39', xydkcCount: 97, wczdsCount: 8 },
|
||||
{ jys: '作战保障教研室', zt: '发布', sbsj: '', xydkcCount: 47, wczdsCount: 0 },
|
||||
{ jys: '军事10教研室', zt: '发布', sbsj: '', xydkcCount: 21, wczdsCount: 0 },
|
||||
{ jys: '军事83', zt: '发布', sbsj: '', xydkcCount: 2, wczdsCount: 0 },
|
||||
{ jys: '军事09教研室', zt: '发布', sbsj: '', xydkcCount: 52, wczdsCount: 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// 默认选中第一行(高亮)
|
||||
this.$nextTick(() => {
|
||||
if (this.tableData.length) {
|
||||
this.$refs.tableRef.setCurrentRow(this.tableData[0])
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
watch: {
|
||||
// 弹窗打开时按模式初始化
|
||||
dialogVisible(val) {
|
||||
if (!val) return
|
||||
this.form.xq = this.semester.name
|
||||
if (this.dialogMode === 'edit') {
|
||||
this.form.rwmc = (this.editRow && this.editRow.rwmc) || ''
|
||||
this.form.cjsj = '2017-07-14 17:00'
|
||||
this.form.fbsj = '2019-12-13 10:39'
|
||||
this.form.jssj = ''
|
||||
this.taskBookRows = [...this.editTaskBookRows]
|
||||
} else {
|
||||
this.form.rwmc = '新研究生教学任务'
|
||||
this.form.cjsj = ''
|
||||
this.form.fbsj = ''
|
||||
this.form.jssj = ''
|
||||
this.taskBookRows = []
|
||||
}
|
||||
this.activeTab = 'taskbook'
|
||||
// 默认选中第一行(高亮)
|
||||
this.$nextTick(() => {
|
||||
if (this.taskBookRows.length && this.$refs.taskBookTable) {
|
||||
this.$refs.taskBookTable.setCurrentRow(this.taskBookRows[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// ==================== 表格 ====================
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
this.currentRow = row
|
||||
},
|
||||
/** 获取当前选中行,未选中时提示 */
|
||||
getSelected() {
|
||||
if (!this.currentRow) {
|
||||
this.$message.warning('请先选择一条教学任务')
|
||||
return null
|
||||
}
|
||||
return this.currentRow
|
||||
},
|
||||
|
||||
// ==================== 操作按钮 ====================
|
||||
/** 新建教学任务 */
|
||||
handleAdd() {
|
||||
this.dialogMode = 'create'
|
||||
this.editRow = null
|
||||
this.dialogVisible = true
|
||||
},
|
||||
/** 编辑教学任务 */
|
||||
handleEdit() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
this.dialogMode = 'edit'
|
||||
this.editRow = row
|
||||
this.dialogVisible = true
|
||||
},
|
||||
/** 弹窗确认保存 */
|
||||
handleDialogConfirm() {
|
||||
// TODO: 调用保存接口
|
||||
this.$message.success('已保存教学任务信息(前端演示)')
|
||||
},
|
||||
/** 删除教学任务 */
|
||||
handleDelete() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
this.$confirm(`确定删除教学任务"${row.rwmc}"吗?删除后不可恢复。`, '删除确认', {
|
||||
confirmButtonText: '确定删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
// TODO: 调用删除接口
|
||||
this.$message.success('删除成功(前端演示)')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
/** 发布教学任务 */
|
||||
handlePublish() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
// TODO: 调用发布接口
|
||||
this.$message.success(`已发布教学任务:${row.rwmc}`)
|
||||
},
|
||||
/** 结束发布 */
|
||||
handleEndPublish() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
// TODO: 调用结束发布接口
|
||||
this.$message.success(`已结束发布:${row.rwmc}`)
|
||||
},
|
||||
/** 管理教学任务所含学员队 */
|
||||
handleManageTeams() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
// TODO: 学员队管理弹窗,待接口接入
|
||||
this.$message.success(`管理教学任务所含学员队:${row.rwmc}`)
|
||||
},
|
||||
|
||||
// ==================== 弹窗 ====================
|
||||
handleTaskBookSelection(rows) {
|
||||
this.selectedTaskBookRows = rows
|
||||
},
|
||||
/** 打开教研室任务书详细(前端演示) */
|
||||
handleTaskBookDetail() {
|
||||
// TODO: 教研室任务书详细弹窗,待接口接入
|
||||
},
|
||||
/** 弹窗确定 */
|
||||
handleConfirm() {
|
||||
this.handleDialogConfirm()
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.task-plan-page {
|
||||
// ========== 1. 学期信息区域 ==========
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 2. 列表标题 ==========
|
||||
.list-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
padding-left: 10px;
|
||||
border-left: 4px solid var(--edu-green-primary);
|
||||
}
|
||||
|
||||
// ========== 3. 工具栏 ==========
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 4. 数据表格区域 ==========
|
||||
.table-card {
|
||||
.task-table {
|
||||
width: 100%;
|
||||
|
||||
.status-text {
|
||||
color: var(--edu-green-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// 当前行高亮
|
||||
::v-deep(.el-table__body tr.current-row > td.el-table__cell) {
|
||||
background-color: #e1f5ec;
|
||||
}
|
||||
|
||||
::v-deep(.el-table__body tr.current-row:hover > td.el-table__cell) {
|
||||
background-color: #e1f5ec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 4. 教学任务信息弹窗 ==========
|
||||
.teaching-task-dialog {
|
||||
.basic-form {
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.tt-tabs {
|
||||
::v-deep(.el-tabs__header) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.sub-toolbar {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.taskbook-table {
|
||||
width: 100%;
|
||||
|
||||
// 当前行高亮
|
||||
::v-deep(.el-table__body tr.current-row > td.el-table__cell) {
|
||||
background-color: #e1f5ec;
|
||||
}
|
||||
|
||||
::v-deep(.el-table__body tr.current-row:hover > td.el-table__cell) {
|
||||
background-color: #e1f5ec;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-empty {
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,824 @@
|
||||
<template>
|
||||
<div class="app-container teacher-page">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="110px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.jysEnabled">教研室</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.jys" placeholder="请选择教研室" class="w-full"
|
||||
:disabled="!searchForm.jysEnabled" clearable>
|
||||
<el-option v-for="item in jysOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.jyxmEnabled">教员姓名</el-checkbox>
|
||||
</template>
|
||||
<el-input v-model="searchForm.jyxm" placeholder="请输入教员姓名" clearable
|
||||
:disabled="!searchForm.jyxmEnabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.zcEnabled">职称</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.zc" placeholder="请选择职称" class="w-full"
|
||||
:disabled="!searchForm.zcEnabled" clearable>
|
||||
<el-option v-for="item in zcOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.xbEnabled">性别</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.xb" placeholder="请选择性别" class="w-full"
|
||||
:disabled="!searchForm.xbEnabled" clearable>
|
||||
<el-option v-for="item in xbOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.xlEnabled">学历</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.xl" placeholder="请选择学历" class="w-full"
|
||||
:disabled="!searchForm.xlEnabled" clearable>
|
||||
<el-option v-for="item in xlOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.xwEnabled">学位</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.xw" placeholder="请选择学位" class="w-full"
|
||||
:disabled="!searchForm.xwEnabled" clearable>
|
||||
<el-option v-for="item in xwOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="进校日期">
|
||||
<div class="date-range">
|
||||
<el-date-picker v-model="searchForm.jzrqStart" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="开始日期" class="date-picker" />
|
||||
<span class="date-sep">至</span>
|
||||
<el-date-picker v-model="searchForm.jzrqEnd" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="结束日期" class="date-picker" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.lxfsEnabled">联系方式</el-checkbox>
|
||||
</template>
|
||||
<el-input v-model="searchForm.lxfs" placeholder="请输入联系方式" clearable
|
||||
:disabled="!searchForm.lxfsEnabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.sfsjjzEnabled">是否实教教员</el-checkbox>
|
||||
</template>
|
||||
<el-radio-group v-model="searchForm.sfsjjz" :disabled="!searchForm.sfsjjzEnabled">
|
||||
<el-radio v-for="item in sfsjjzOptions" :key="item" :label="item">{{ item }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.jylbEnabled">教员类别</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.jylb" placeholder="请选择教员类别" clearable class="w-full"
|
||||
:disabled="!searchForm.jylbEnabled">
|
||||
<el-option v-for="item in jylbOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="search-tip">
|
||||
注意:勾选"选择框"表示启用该项对应的查询条件。
|
||||
</div>
|
||||
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 教员列表 -->
|
||||
<div class="list-title">教员列表:</div>
|
||||
<div class="list-toolbar">
|
||||
<div class="left-group">
|
||||
<el-button type="primary" @click="handleNew">新建</el-button>
|
||||
<el-button type="primary" @click="handleDeleteSelected">删除所选</el-button>
|
||||
<el-button type="primary" @click="handleImport">导入教员信息</el-button>
|
||||
</div>
|
||||
<div class="right-group">
|
||||
<el-button type="primary" @click="handleDownloadTemplate">【教员数据文件模板】下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="jybh" label="教员编号" width="100" align="center" />
|
||||
<el-table-column prop="jyxm" label="教员姓名" width="100" align="center" />
|
||||
<el-table-column label="性别" width="60" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.xb === 0 ? '男' : scope.row.xb === 1 ? '女' : scope.row.xb }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jysmc" label="教研室名称" align="center" />
|
||||
<el-table-column prop="zc" label="职称" width="100" align="center" />
|
||||
<el-table-column prop="xl" label="学历" width="120" align="center" />
|
||||
<el-table-column prop="xw" label="学位" width="100" align="center" />
|
||||
<el-table-column prop="cssj" label="出生时间" width="120" align="center" :formatter="formatDate" />
|
||||
<el-table-column prop="sjh" label="联系方式" width="130" align="center" />
|
||||
<el-table-column label="虚实类型" width="100" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.xslx === 0 ? '教学型' : scope.row.xslx === 1 ? '科研型' : scope.row.xslx }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sfsjjz" label="是否实教教员" width="120" align="center" />
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleViewAttribute(scope.row)">查看属性</el-button>
|
||||
<el-button type="text" style="color: #e6a23c" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" style="color: #f56c6c" @click="handleToggleDisable(scope.row)">停用</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-wrap">
|
||||
<el-pagination
|
||||
:current-page="pagination.pageNum"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 教员属性详情对话框 -->
|
||||
<el-dialog :visible.sync="attributeVisible" title="教员属性" width="720px" :destroy-on-close="true">
|
||||
<div v-loading="attributeLoading || attributeSaving">
|
||||
<!-- 查看模式 -->
|
||||
<el-descriptions v-if="attributeMode === 'view'" :column="2" border>
|
||||
<el-descriptions-item v-for="(value, key) in attributeData" :key="key" :label="ATTR_LABELS[key] || key"
|
||||
label-align="right" align="center">
|
||||
{{ value === null || value === undefined || value === '' ? '—' : value }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<!-- 编辑模式 -->
|
||||
<el-form v-else-if="attributeMode === 'edit'" label-width="120px" class="attribute-form">
|
||||
<el-form-item v-for="(value, key) in attributeData" :key="key" :label="ATTR_LABELS[key] || key">
|
||||
<el-input v-if="isEditableValue(value)" v-model="attributeData[key]" :disabled="key === 'jybh'"
|
||||
:placeholder="key === 'jybh' ? '' : '请输入'" clearable />
|
||||
<span v-else class="readonly-value">{{ typeof value === 'object' ? JSON.stringify(value) : value }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-empty v-else description="暂无属性数据" />
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<template v-if="attributeMode === 'view'">
|
||||
<el-button @click="attributeVisible = false">关闭</el-button>
|
||||
<el-button type="primary" @click="handleStartEdit">编辑</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button @click="handleCancelEdit">取消</el-button>
|
||||
<el-button type="primary" :loading="attributeSaving" @click="handleSaveAttribute">保存</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新建教员对话框 -->
|
||||
<el-dialog :visible.sync="addDialogVisible" title="新建教员" width="800px" :destroy-on-close="true">
|
||||
<el-form :model="addForm" label-width="140px" class="add-form">
|
||||
<el-divider content-position="left">教员基本信息</el-divider>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员编号" required><el-input v-model="addForm.teacher.jybh" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员姓名" required><el-input v-model="addForm.teacher.jyxm" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教研室代号" required><el-input v-model="addForm.teacher.jysdh" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="性别" required>
|
||||
<el-select v-model="addForm.teacher.xb" style="width:100%">
|
||||
<el-option :value="0" label="男" /><el-option :value="1" label="女" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="身份证号" required><el-input v-model="addForm.teacher.sfzh" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="离职状态" required>
|
||||
<el-select v-model="addForm.teacher.lzzt" style="width:100%">
|
||||
<el-option :value="0" label="在职" /><el-option :value="1" label="离职" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业技术职务等级" required><el-input v-model="addForm.teacher.zyjszwdj" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="虚实类型" required>
|
||||
<el-select v-model="addForm.teacher.xslx" style="width:100%">
|
||||
<el-option :value="0" label="教学型" /><el-option :value="1" label="科研型" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员类别" required>
|
||||
<el-select v-model="addForm.teacher.jylb" style="width:100%">
|
||||
<el-option v-for="item in jylbOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="在职类别" required><el-input v-model="addForm.teacher.zzlb" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="导师类别" required><el-input v-model="addForm.teacher.dslb" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学缘" required><el-input v-model="addForm.teacher.xy" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="额外允许开班数" required>
|
||||
<el-input-number v-model="addForm.teacher.ewyxkbs" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="外训教员" required>
|
||||
<el-select v-model="addForm.teacher.wxjy" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="外训译员" required>
|
||||
<el-select v-model="addForm.teacher.wxyy" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="政治类教员" required>
|
||||
<el-select v-model="addForm.teacher.zzljy" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="职称"><el-select v-model="addForm.teacher.zc" placeholder="选填" style="width:100%" clearable>
|
||||
<el-option v-for="item in zcOptions" :key="item" :label="item" :value="item" /></el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号"><el-input v-model="addForm.teacher.sjh" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="拼音"><el-input v-model="addForm.teacher.py" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider content-position="left">教员属性</el-divider>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学历" required>
|
||||
<el-select v-model="addForm.attributes.xl" placeholder="请选择" style="width:100%">
|
||||
<el-option v-for="item in xlOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学位" required>
|
||||
<el-select v-model="addForm.attributes.xw" placeholder="请选择" style="width:100%">
|
||||
<el-option v-for="item in xwOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教龄" required>
|
||||
<el-input-number v-model="addForm.attributes.jl" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教龄计算日期" required>
|
||||
<el-date-picker v-model="addForm.attributes.jljsrq" type="datetime" value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="选择日期" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主任">
|
||||
<el-select v-model="addForm.attributes.zr" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="技术职务"><el-input v-model="addForm.attributes.jszw" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="技术职务时间">
|
||||
<el-date-picker v-model="addForm.attributes.jszwsj" type="datetime" value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="选填" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="技术等级"><el-input v-model="addForm.attributes.jsdj" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="技术等级时间">
|
||||
<el-date-picker v-model="addForm.attributes.jsdjsj" type="datetime" value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="选填" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="军衔文职"><el-input v-model="addForm.attributes.jxwz" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="军衔文职时间">
|
||||
<el-date-picker v-model="addForm.attributes.jxwzsj" type="datetime" value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="选填" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="出生时间">
|
||||
<el-date-picker v-model="addForm.attributes.cssj" type="datetime" value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="选填" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="入伍工作时间">
|
||||
<el-date-picker v-model="addForm.attributes.rwgzsj" type="datetime" value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="选填" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="addDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="addSaving" @click="handleAddConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 编辑教员基本信息对话框 -->
|
||||
<el-dialog :visible.sync="editDialogVisible" title="编辑教员信息" width="780px" :destroy-on-close="true">
|
||||
<div v-loading="editLoading">
|
||||
<el-form :model="editForm" label-width="140px" class="add-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员编号"><el-input v-model="editForm.jybh" disabled /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员姓名" required><el-input v-model="editForm.jyxm" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教研室代号" required><el-input v-model="editForm.jysdh" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="性别" required>
|
||||
<el-select v-model="editForm.xb" style="width:100%">
|
||||
<el-option :value="0" label="男" /><el-option :value="1" label="女" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="身份证号" required><el-input v-model="editForm.sfzh" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="离职状态" required>
|
||||
<el-select v-model="editForm.lzzt" style="width:100%">
|
||||
<el-option :value="0" label="在职" /><el-option :value="1" label="离职" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业技术职务等级" required><el-input v-model="editForm.zyjszwdj" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="虚实类型" required>
|
||||
<el-select v-model="editForm.xslx" style="width:100%">
|
||||
<el-option :value="0" label="教学型" /><el-option :value="1" label="科研型" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员类别" required>
|
||||
<el-select v-model="editForm.jylb" style="width:100%">
|
||||
<el-option v-for="item in jylbOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="在职类别" required><el-input v-model="editForm.zzlb" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="导师类别" required><el-input v-model="editForm.dslb" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学缘" required><el-input v-model="editForm.xy" placeholder="请输入" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="额外允许开班数" required>
|
||||
<el-input-number v-model="editForm.ewyxkbs" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="外训教员" required>
|
||||
<el-select v-model="editForm.wxjy" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="外训译员" required>
|
||||
<el-select v-model="editForm.wxyy" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="政治类教员" required>
|
||||
<el-select v-model="editForm.zzljy" style="width:100%">
|
||||
<el-option :value="0" label="否" /><el-option :value="1" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="职称"><el-select v-model="editForm.zc" style="width:100%" clearable>
|
||||
<el-option v-for="item in zcOptions" :key="item" :label="item" :value="item" /></el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号"><el-input v-model="editForm.sjh" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="拼音"><el-input v-model="editForm.py" placeholder="选填" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="editSaving" @click="handleEditConfirm">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 各下拉框选项:数据待后端接口返回后替换
|
||||
const JYS_OPTIONS = [] // 教研室
|
||||
const ZC_OPTIONS = ['教授', '副教授', '讲师', '助教'] // 职称
|
||||
const XL_OPTIONS = ['博士', '硕士', '本科', '大专'] // 学历
|
||||
const XW_OPTIONS = ['博士', '硕士', '学士'] // 学位
|
||||
const JYLB_OPTIONS = [] // 教员类别
|
||||
|
||||
export default {
|
||||
name: 'Teacher',
|
||||
data() {
|
||||
return {
|
||||
// 查询条件
|
||||
searchForm: {
|
||||
jysEnabled: false, jys: '',
|
||||
jyxmEnabled: false, jyxm: '',
|
||||
zcEnabled: false, zc: '',
|
||||
xbEnabled: false, xb: '',
|
||||
xlEnabled: false, xl: '',
|
||||
xwEnabled: false, xw: '',
|
||||
jzrqStart: '', jzrqEnd: '',
|
||||
lxfsEnabled: false, lxfs: '',
|
||||
sfsjjzEnabled: false, sfsjjz: '是',
|
||||
jylbEnabled: false, jylb: ''
|
||||
},
|
||||
options: {
|
||||
jys: JYS_OPTIONS,
|
||||
zc: ZC_OPTIONS,
|
||||
xl: XL_OPTIONS,
|
||||
xw: XW_OPTIONS,
|
||||
jylb: JYLB_OPTIONS
|
||||
},
|
||||
// 教员列表
|
||||
loading: false,
|
||||
tableData: [],
|
||||
selectedRows: [],
|
||||
pagination: { pageNum: 1, pageSize: 10, total: 0 },
|
||||
// 属性详情
|
||||
attributeVisible: false,
|
||||
attributeMode: 'view',
|
||||
attributeData: {},
|
||||
attributeLoading: false,
|
||||
attributeSaving: false,
|
||||
// 新建
|
||||
addDialogVisible: false,
|
||||
addSaving: false,
|
||||
addForm: {
|
||||
teacher: {
|
||||
jybh: '', jyxm: '', jysdh: '', xb: '', sfzh: '', lzzt: '', zyjszwdj: '',
|
||||
xslx: '', jylb: '', zzlb: '', dslb: '', xy: '', ewyxkbs: 0,
|
||||
wxjy: '', wxyy: '', zzljy: '', zc: '', sjh: '', py: ''
|
||||
},
|
||||
attributes: {
|
||||
xl: '', xw: '', jl: 0, jljsrq: '', zr: '', jszw: '', jszwsj: '',
|
||||
jsdj: '', jsdjsj: '', jxwz: '', jxwzsj: '', cssj: '', rwgzsj: ''
|
||||
}
|
||||
},
|
||||
// 编辑
|
||||
editDialogVisible: false,
|
||||
editLoading: false,
|
||||
editSaving: false,
|
||||
editForm: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
jysOptions() { return this.options.jys },
|
||||
zcOptions() { return this.options.zc },
|
||||
xlOptions() { return this.options.xl },
|
||||
xwOptions() { return this.options.xw },
|
||||
jylbOptions() { return this.options.jylb },
|
||||
xbOptions() { return [{ value: 0, label: '男' }, { value: 1, label: '女' }] },
|
||||
sfsjjzOptions() { return ['是', '否'] },
|
||||
// 属性字段中文名映射
|
||||
ATTR_LABELS() { return ATTR_LABELS_MAP }
|
||||
},
|
||||
created() {
|
||||
// TODO: 待后端接口,拉取教研室等下 拉选项与教员列表
|
||||
// this.loadOptions()
|
||||
// this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 属性字段中文名(配合接口返回字段使用)
|
||||
isEditableValue(value) {
|
||||
// TODO: 根据字段类型判断是否可编辑
|
||||
return typeof value !== 'object' || value === null
|
||||
},
|
||||
formatDate(row, column, cellValue) {
|
||||
return cellValue ? String(cellValue).substring(0, 10) : ''
|
||||
},
|
||||
/** 查询 */
|
||||
handleSearch() {
|
||||
// TODO: 调用查询接口
|
||||
},
|
||||
/** 重置 */
|
||||
handleReset() {
|
||||
this.searchForm = {
|
||||
jysEnabled: false, jys: '', jyxmEnabled: false, jyxm: '',
|
||||
zcEnabled: false, zc: '', xbEnabled: false, xb: '',
|
||||
xlEnabled: false, xl: '', xwEnabled: false, xw: '',
|
||||
jzrqStart: '', jzrqEnd: '', lxfsEnabled: false, lxfs: '',
|
||||
sfsjjzEnabled: false, sfsjjz: '是', jylbEnabled: false, jylb: ''
|
||||
}
|
||||
},
|
||||
/** 新建 */
|
||||
handleNew() {
|
||||
// TODO: 打开新建对话框
|
||||
},
|
||||
/** 删除所选 */
|
||||
handleDeleteSelected() {
|
||||
// TODO: 批量删除
|
||||
},
|
||||
/** 导入教员信息 */
|
||||
handleImport() {
|
||||
// TODO: 导入
|
||||
},
|
||||
/** 下载模板 */
|
||||
handleDownloadTemplate() {
|
||||
// TODO: 模板下载
|
||||
},
|
||||
/** 表格多选 */
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
/** 查看属性 */
|
||||
handleViewAttribute(row) {
|
||||
// TODO: 拉取行属性并打开
|
||||
this.attributeVisible = true
|
||||
},
|
||||
/** 编辑基本信息 */
|
||||
handleEdit(row) {
|
||||
// TODO: 回填并打开编辑对话框
|
||||
this.editDialogVisible = true
|
||||
},
|
||||
/** 停用 */
|
||||
handleToggleDisable(row) {
|
||||
// TODO: 停用接口
|
||||
},
|
||||
/** 分页 */
|
||||
handleSizeChange(val) {
|
||||
this.pagination.pageSize = val
|
||||
// TODO: 重新查询
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.pagination.pageNum = val
|
||||
// TODO: 重新查询
|
||||
},
|
||||
/** 属性-开始编辑 */
|
||||
handleStartEdit() {
|
||||
this.attributeMode = 'edit'
|
||||
},
|
||||
/** 属性-取消编辑 */
|
||||
handleCancelEdit() {
|
||||
this.attributeMode = 'view'
|
||||
},
|
||||
/** 属性-保存 */
|
||||
handleSaveAttribute() {
|
||||
// TODO: 保存属性接口
|
||||
this.attributeMode = 'view'
|
||||
},
|
||||
/** 新建-确认 */
|
||||
handleAddConfirm() {
|
||||
// TODO: 新增接口
|
||||
this.addDialogVisible = false
|
||||
},
|
||||
/** 编辑-确认 */
|
||||
handleEditConfirm() {
|
||||
// TODO: 编辑接口
|
||||
this.editDialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 属性字段中文名映射(后续按接口字段补全)
|
||||
const ATTR_LABELS_MAP = {
|
||||
jybh: '教员编号',
|
||||
jyxm: '教员姓名',
|
||||
xb: '性别',
|
||||
jysdh: '教研室代号',
|
||||
jysmc: '教研室名称',
|
||||
zc: '职称',
|
||||
xl: '学历',
|
||||
xw: '学位',
|
||||
cssj: '出生时间',
|
||||
sjh: '手机号',
|
||||
xslx: '虚实类型',
|
||||
sfsjjz: '是否实教教员'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.teacher-page {
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.date-picker {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.date-sep {
|
||||
margin: 0 8px;
|
||||
color: #909399;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
margin: 8px 0 16px;
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
text-align: right;
|
||||
border-top: 1px solid #ebeef5;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.list-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin: 8px 0 12px;
|
||||
padding-left: 10px;
|
||||
border-left: 4px solid var(--edu-green-primary);
|
||||
}
|
||||
|
||||
.list-toolbar {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
.left-group,
|
||||
.right-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.table-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.pagination-wrap {
|
||||
padding: 14px 0 4px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.attribute-form {
|
||||
.readonly-value {
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user