1、校历的78、晚上、夜间等直接落库,

2、配当、任务书完善、排课窗完善;
3、任务书批量发布、删除等;
4、班历同步校历
This commit is contained in:
2026-09-18 10:38:39 +08:00
parent 911dfe911b
commit f3ae9fb2fd
62 changed files with 3508 additions and 143 deletions
@@ -31,7 +31,34 @@
:disabled="frozen || !selection.length"
@click="handleSplit"
>拆班</el-button>
<el-button
size="small"
icon="el-icon-user"
:disabled="frozen || !selection.length"
@click="openBatchTeacher"
>批量指定教员{{ selection.length }}</el-button>
<el-button
size="small"
icon="el-icon-office-building"
:disabled="frozen || !selection.length"
@click="openBatchRoom"
>批量指定场地{{ selection.length }}</el-button>
<el-button
size="small"
icon="el-icon-edit-outline"
:disabled="frozen || !selection.length"
@click="openBatchFill"
>批量填报{{ selection.length }}</el-button>
<el-button
type="danger"
size="small"
icon="el-icon-delete"
:disabled="frozen || !selection.length"
@click="handleDeleteRows"
>删除行{{ selection.length }}</el-button>
<el-button size="small" icon="el-icon-refresh" @click="loadRows">刷新</el-button>
<el-button size="small" icon="el-icon-download" @click="handleExport">导出</el-button>
<el-button size="small" icon="el-icon-printer" @click="handlePrint">打印</el-button>
<span v-if="frozen" class="tb-frozen-tip">教学任务未发布或已结束当前只读</span>
<span class="tb-tip">合班规则科目学时课类型成绩分制必须相同同合班行同色连显</span>
</div>
@@ -57,7 +84,9 @@
<el-table-column prop="zks" label="周课时" width="65" align="center" />
<el-table-column prop="cjfz" label="成绩分制" width="80" align="center" />
<el-table-column label="责任教员" width="110" align="center">
<template slot-scope="{ row }">{{ row.jyxm || '-' }}</template>
<template slot-scope="{ row }">
{{ row.jyxm || '-' }}<span v-if="row.zr === 1" class="tb-director" title="教研室主任"> *</span>
</template>
</el-table-column>
<el-table-column label="场地" width="130" align="center" show-overflow-tooltip>
<template slot-scope="{ row }">{{ row.jsmc || row.jsbh || '-' }}</template>
@@ -76,11 +105,12 @@
<template slot-scope="{ row }">{{ row.jysjhjyxm || '-' }}</template>
</el-table-column>
<el-table-column prop="jysjhbz" label="排课建议" min-width="120" align="center" show-overflow-tooltip />
<el-table-column label="操作" width="210" align="center" fixed="right">
<el-table-column label="操作" width="270" align="center" fixed="right">
<template slot-scope="{ row }">
<el-button type="text" size="small" :disabled="frozen" @click="openTeacher(row)">指定教员</el-button>
<el-button type="text" size="small" :disabled="frozen" @click="openRoom(row)">指定场地</el-button>
<el-button type="text" size="small" :disabled="frozen" @click="openFill(row)">填报</el-button>
<el-button type="text" size="small" style="color:#f56c6c" :disabled="frozen" @click="handleDeleteRows([row])">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -98,6 +128,9 @@
:close-on-click-modal="false"
>
<el-form label-width="110px">
<el-form-item v-if="teacherDialog.batch" label="选中行">
<span>{{ selection.length }} 行将统一指定责任教员</span>
</el-form-item>
<el-form-item label="指定方式">
<el-radio-group v-model="teacherDialog.mode" @change="loadTeacherOptions">
<el-radio label="unit">责任单位教员</el-radio>
@@ -122,7 +155,7 @@
</el-select>
</el-form-item>
<el-form-item v-else label="计划教员">
<span>{{ teacherDialog.planTeacherName || '(该行没有教研室计划教员)' }}</span>
<span>{{ teacherDialog.batch ? '应用各行教研室计划教员' : (teacherDialog.planTeacherName || '(该行没有教研室计划教员)') }}</span>
</el-form-item>
<el-form-item v-if="teacherDialog.row && teacherDialog.row.bz2 && teacherDialog.row.bz2 !== 0" label="同步范围">
<span class="tb-tip">该行已合班(组{{ teacherDialog.row.bz2 }}),保存后同组其它行同步</span>
@@ -143,6 +176,9 @@
:close-on-click-modal="false"
>
<el-form label-width="110px">
<el-form-item v-if="roomDialog.batch" label="选中行">
<span>{{ selection.length }} 行将统一指定场地</span>
</el-form-item>
<el-form-item label="场地类型">
<el-radio-group v-model="roomDialog.useSpecial">
<el-radio :label="true">班次专用教室</el-radio>
@@ -178,13 +214,16 @@
<!-- ==================== 填报子对话框 ==================== -->
<el-dialog
:visible.sync="fillDialog.visible"
title="教研室填报"
:title="fillDialog.batch ? `批量填报(${selection.length} 行)` : '教研室填报'"
width="520px"
append-to-body
:close-on-click-modal="false"
>
<el-form label-width="110px">
<el-form-item label="课程 / 学员队">
<el-form-item v-if="fillDialog.batch" label="选中行">
<span>{{ selection.length }} 行将统一应用下方填写的字段(留空字段不改动)</span>
</el-form-item>
<el-form-item v-else label="课程 / 学员队">
<span>{{ fillDialog.row ? `${fillDialog.row.kcmc} / ${fillDialog.row.xydmc}` : '' }}</span>
</el-form-item>
<el-form-item label="计划教员">
@@ -223,6 +262,15 @@
/>
</el-select>
</el-form-item>
<el-form-item label="课次序号">
<el-input-number
v-model="fillDialog.kcxh"
:min="1"
:max="999"
placeholder="课序"
style="width: 160px"
/>
</el-form-item>
<el-form-item label="排课建议">
<el-input
v-model="fillDialog.jysjhbz"
@@ -253,8 +301,13 @@ import {
taskBookSplit,
taskBookSetTeacher,
taskBookSetRoom,
taskBookBatchSetTeacher,
taskBookBatchSetRoom,
taskBookBatchFill,
taskBookDeleteRows,
taskBookFill
} from '@/api/teachBusiness/taskBook'
import { exportTaskBook } from '@/api/teachBusiness/teachingTask'
import { listTeacher } from '@/api/teachOffice/teacher'
import { listClassroom } from '@/api/teachBusiness/classroom'
@@ -275,6 +328,7 @@ export default {
selection: [],
teacherDialog: {
visible: false,
batch: false,
mode: 'unit',
jybh: '',
teachers: [],
@@ -283,6 +337,7 @@ export default {
},
roomDialog: {
visible: false,
batch: false,
useSpecial: true,
jsbh: '',
classrooms: [],
@@ -291,9 +346,11 @@ export default {
},
fillDialog: {
visible: false,
batch: false,
jysjhjybh: '',
jsbh: '',
jysjhbz: '',
kcxh: null,
useSpecial: false,
teachers: [],
classrooms: [],
@@ -369,15 +426,25 @@ export default {
// ---------- 指定教员 ----------
openTeacher(row) {
this.teacherDialog.row = row
this.teacherDialog.batch = false
this.teacherDialog.mode = 'unit'
this.teacherDialog.jybh = row.jybh || ''
this.teacherDialog.visible = true
this.loadTeacherOptions()
},
openBatchTeacher() {
this.teacherDialog.row = null
this.teacherDialog.batch = true
this.teacherDialog.mode = 'academy'
this.teacherDialog.jybh = ''
this.teacherDialog.visible = true
this.loadTeacherOptions()
},
loadTeacherOptions() {
const row = this.teacherDialog.row
if (!row) return
const params = this.teacherDialog.mode === 'unit' ? { jysdh: row.jysdh } : {}
const params = (!this.teacherDialog.batch && row && this.teacherDialog.mode === 'unit')
? { jysdh: row.jysdh }
: {}
this.teacherDialog.loading = true
listTeacher(params)
.then(res => {
@@ -389,7 +456,14 @@ export default {
},
submitTeacher() {
const d = this.teacherDialog
taskBookSetTeacher({ bh: d.row.bh, mode: d.mode, jybh: d.mode === 'plan' ? undefined : d.jybh })
const call = d.batch
? taskBookBatchSetTeacher({
bhList: this.selection.map(r => r.bh),
mode: d.mode,
jybh: d.mode === 'plan' ? undefined : d.jybh
})
: taskBookSetTeacher({ bh: d.row.bh, mode: d.mode, jybh: d.mode === 'plan' ? undefined : d.jybh })
call
.then(res => {
d.visible = false
this.reload(Promise.resolve(res))
@@ -399,9 +473,21 @@ export default {
// ---------- 指定场地 ----------
openRoom(row) {
this.roomDialog.row = row
this.roomDialog.batch = false
this.roomDialog.useSpecial = true
this.roomDialog.jsbh = ''
this.roomDialog.visible = true
this.loadRoomOptions()
},
openBatchRoom() {
this.roomDialog.row = null
this.roomDialog.batch = true
this.roomDialog.useSpecial = false
this.roomDialog.jsbh = ''
this.roomDialog.visible = true
this.loadRoomOptions()
},
loadRoomOptions() {
if (!this.roomDialog.classrooms.length) {
this.roomDialog.loading = true
listClassroom({ pageNum: 1, pageSize: 200 })
@@ -416,7 +502,14 @@ export default {
},
submitRoom() {
const d = this.roomDialog
taskBookSetRoom({ bh: d.row.bh, jsbh: d.jsbh, useSpecial: d.useSpecial })
const call = d.batch
? taskBookBatchSetRoom({
bhList: this.selection.map(r => r.bh),
jsbh: d.jsbh,
useSpecial: d.useSpecial
})
: taskBookSetRoom({ bh: d.row.bh, jsbh: d.jsbh, useSpecial: d.useSpecial })
call
.then(res => {
d.visible = false
this.reload(Promise.resolve(res))
@@ -426,9 +519,11 @@ export default {
// ---------- 填报 ----------
openFill(row) {
this.fillDialog.row = row
this.fillDialog.batch = false
this.fillDialog.jysjhjybh = row.jysjhjybh || ''
this.fillDialog.jsbh = row.jsbh || ''
this.fillDialog.jysjhbz = row.jysjhbz || ''
this.fillDialog.kcxh = row.kcxh || null
this.fillDialog.useSpecial = false
this.fillDialog.visible = true
this.fillDialog.loading = true
@@ -450,12 +545,57 @@ export default {
this.fillDialog.loading = false
})
},
openBatchFill() {
this.fillDialog.row = null
this.fillDialog.batch = true
this.fillDialog.jysjhjybh = ''
this.fillDialog.jsbh = ''
this.fillDialog.jysjhbz = ''
this.fillDialog.kcxh = null
this.fillDialog.useSpecial = false
this.fillDialog.visible = true
this.fillDialog.loading = true
Promise.all([
listTeacher({}).catch(() => null),
this.roomDialog.classrooms.length
? Promise.resolve(null)
: listClassroom({ pageNum: 1, pageSize: 200 }).catch(() => null)
])
.then(([tRes, cRes]) => {
if (tRes) this.fillDialog.teachers = (tRes.data && (tRes.data.records || tRes.data.rows || tRes.data)) || []
if (cRes) {
const data = cRes.data || {}
this.roomDialog.classrooms = data.records || data.rows || data.list || []
}
this.fillDialog.classrooms = this.roomDialog.classrooms
})
.finally(() => {
this.fillDialog.loading = false
})
},
submitFill() {
const d = this.fillDialog
if (d.batch) {
taskBookBatchFill({
bhList: this.selection.map(r => r.bh),
jysjhjybh: d.jysjhjybh || undefined,
jysjhbz: d.jysjhbz || undefined,
kcxh: d.kcxh || undefined,
jsbh: d.useSpecial ? undefined : (d.jsbh || undefined),
useSpecial: d.useSpecial
})
.then(res => {
d.visible = false
this.reload(Promise.resolve(res))
})
.catch(err => this.$message.error((err && err.message) || '保存失败'))
return
}
const base = {
bh: d.row.bh,
jysjhjybh: d.jysjhjybh || '',
jysjhbz: d.jysjhbz || ''
jysjhbz: d.jysjhbz || '',
kcxh: d.kcxh || undefined
}
// 专用教室走 setRoom(useSpecial) 才能取到班次专用教室编号;其它教室随 fill 同步
const call = d.useSpecial
@@ -467,6 +607,36 @@ export default {
this.reload(Promise.resolve(res))
})
.catch(err => this.$message.error((err && err.message) || '保存失败'))
},
// ---------- 行级删除 / 导出 / 打印 ----------
handleDeleteRows(rowsArg) {
const targets = Array.isArray(rowsArg) ? rowsArg : this.selection
const bhList = targets.map(r => r.bh)
if (!bhList.length) {
this.$message.warning('请先选择要删除的行')
return
}
this.$confirm(`确定删除选中的 ${bhList.length} 条课程任务行吗?已发布到运行课表的须先撤回。`, '删除课程任务行', {
type: 'warning'
})
.then(() => this.reload(taskBookDeleteRows(bhList)))
.catch(() => {})
},
handleExport() {
if (!this.jxrwbh) return
exportTaskBook(this.jxrwbh)
.then(res => {
const blob = new Blob([res.data || res], { type: 'application/vnd.ms-excel' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `教学任务书_${this.taskName || this.jxrwbh}.xls`
link.click()
URL.revokeObjectURL(link.href)
})
.catch(() => this.$message.error('导出失败'))
},
handlePrint() {
window.print()
}
}
}
@@ -499,4 +669,29 @@ export default {
color: #c0c4cc;
font-size: 12px;
}
.tb-director {
color: #e6a23c;
font-weight: bold;
}
</style>
<style>
@media print {
.tb-toolbar,
.el-dialog__headerbtn,
.el-dialog__footer,
.tb-table .el-table__fixed-right,
.v-modal {
display: none !important;
}
.el-dialog {
width: 100% !important;
margin: 0 !important;
box-shadow: none !important;
}
.el-dialog__body {
max-height: none !important;
overflow: visible !important;
}
}
</style>