班次学期信息管理

This commit is contained in:
2026-08-23 21:02:15 +08:00
parent 499518a2a6
commit 526b9082df
6 changed files with 1601 additions and 1504 deletions
@@ -1,369 +1,591 @@
<template>
<div class="app-container shift-semester-page">
<!-- ==================== 1. 学年学期标题 ==================== -->
<div class="list-title">{{ semesterName }}</div>
<!-- ==================== 页面标题 ==================== -->
<div class="page-title">班次学期信息管理</div>
<!-- ==================== 2. 校历 / 预设日期信息区 ==================== -->
<!-- ==================== 1. 查询条件区域 ==================== -->
<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 :inline="true" :model="searchForm" class="search-form">
<el-form-item label="班次编号">
<el-input
v-model="searchForm.xydbh"
placeholder="请输入班次编号(模糊)"
clearable
style="width: 220px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="年度">
<el-select v-model="filterYear" placeholder="全部年度" clearable style="width: 140px" @change="handleYearChange">
<el-option v-for="y in yearFilterOptions" :key="y" :label="`${y}年`" :value="y" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- ==================== 3. 工具栏按钮区 ==================== -->
<!-- ==================== 2. 工具栏按钮区 ==================== -->
<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>
<el-button type="primary" icon="el-icon-plus" @click="handleBatchAdd">批量创建班次学期</el-button>
<el-button type="primary" plain icon="el-icon-document-add" @click="handleAdd">新增</el-button>
<el-button type="primary" plain icon="el-icon-edit" :disabled="!currentRow" @click="handleEdit">编辑</el-button>
<el-button type="danger" plain icon="el-icon-delete" :disabled="!selection.length" @click="handleDelete">删除所选</el-button>
<el-button type="primary" plain icon="el-icon-date" :disabled="!selection.length" @click="handleQuickSetDates">快速设定学期日期</el-button>
<el-button type="primary" plain icon="el-icon-notebook-2" :disabled="!selection.length" @click="handleSetJxrw">批量设置教学任务</el-button>
</div>
<div class="right-group">
<el-button type="success" plain icon="el-icon-calendar" :disabled="!currentRow" @click="handleEditCalendar">编辑班历</el-button>
</div>
</div>
<!-- ==================== 4. 班次学期信息列表 ==================== -->
<!-- ==================== 3. 班次学期信息列表 ==================== -->
<el-card shadow="never" class="table-card">
<el-table
ref="tableRef"
v-loading="loading"
:data="displayData"
border
stripe
highlight-current-row
:span-method="spanMethod"
:row-class-name="rowClassName"
:header-cell-class-name="headerCellClassName"
size="small"
max-height="480"
class="class-table"
@selection-change="handleSelectionChange"
@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" header-align="center" 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>
<template slot="empty">
<span>无数据</span>
</template>
<el-table-column type="selection" width="44" align="center" />
<el-table-column type="index" label="序号" width="55" align="center" />
<el-table-column prop="xydbh" label="班次编号" min-width="150" align="left" header-align="center" show-overflow-tooltip />
<el-table-column prop="nd" label="年度" width="80" align="center" show-overflow-tooltip />
<el-table-column label="学期第次" width="90" align="center">
<template slot-scope="{ row }">{{ xqdcLabel(row.xqdc) }}</template>
</el-table-column>
<el-table-column prop="kxrq" label="开学日期" width="110" align="center" :formatter="fmtDate" />
<el-table-column prop="jsrq" label="结束日期" width="110" align="center" :formatter="fmtDate" />
<el-table-column prop="zyjsbh" label="专用教室" width="100" align="center" show-overflow-tooltip />
<el-table-column label="教学任务" min-width="160" align="left" header-align="center" show-overflow-tooltip>
<template slot-scope="{ row }">{{ taskName(row.jxrwbh) }}</template>
</el-table-column>
<el-table-column label="开放教员排课" width="110" align="center">
<template slot-scope="{ row }">
<el-tag v-if="Number(row.kfjypk) === 1" type="success" size="small">开放</el-tag>
<el-tag v-else type="info" size="small">关闭</el-tag>
</template>
</el-table-column>
<el-table-column prop="bz" label="备注" min-width="120" align="left" header-align="center" show-overflow-tooltip />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template slot-scope="{ row }">
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="text" size="small" @click="handleEditCalendar(row)">班历</el-button>
<el-button type="text" size="small" class="text-danger" @click="handleDeleteRow(row)">删除</el-button>
</template>
</el-table-column>
<el-table-column prop="zxf" label="总学分" width="70" align="center" show-overflow-tooltip />
</el-table>
<el-pagination
class="list-pagination"
:current-page="pageNum"
:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handlePageChange"
/>
</el-card>
<!-- ==================== 教学班次学期信息明细弹窗新添 ==================== -->
<!-- ==================== 班次学期新增/编辑弹窗 ==================== -->
<ClassSemesterDetailDialog
:visible="detailVisible"
:class-info="selectedNewClass"
:semester-name="semesterName"
:mode="detailMode"
:semester="detailSemester"
:team-info="detailTeamInfo"
:year-options="yearOptions"
:task-options="taskOptions"
@update:visible="val => detailVisible = val"
@confirm="handleDetailConfirm"
@submit="handleDetailSubmit"
/>
<!-- ==================== 班历设置弹窗编辑班历 ==================== -->
<!-- ==================== 班历管理弹窗 ==================== -->
<ClassCalendarDialog
:visible="calendarVisible"
:bc="currentRow ? currentRow.bc : ''"
:semester-name="semesterName"
:semester="calendarSemester"
:semester-options="semesterOptions"
@update:visible="val => calendarVisible = val"
/>
<!-- ==================== 预设合班弹窗 ==================== -->
<ClassTeamSelectDialog
:visible="teamVisible"
@update:visible="val => teamVisible = val"
@confirm="handleTeamConfirm"
/>
<!-- ==================== 批量创建班次学期弹窗 ==================== -->
<el-dialog
:visible="batchAddVisible"
title="批量创建班次学期"
width="520px"
:close-on-click-modal="false"
@update:visible="val => batchAddVisible = val"
>
<el-form ref="batchAddFormRef" :model="batchAddForm" :rules="batchAddRules" label-width="100px">
<el-form-item label="年度" prop="nd">
<el-select v-model="batchAddForm.nd" placeholder="请选择年度" style="width: 100%">
<el-option v-for="y in yearOptions" :key="y" :label="`${y}年`" :value="y" />
</el-select>
</el-form-item>
<el-form-item label="学期" prop="xqdc">
<el-select v-model="batchAddForm.xqdc" placeholder="请选择学期" style="width: 100%">
<el-option label="春季学期" value="春季学期" />
<el-option label="夏季学期" value="夏季学期" />
<el-option label="秋季学期" value="秋季学期" />
</el-select>
</el-form-item>
<el-form-item label="开始日期" prop="startTime">
<el-date-picker v-model="batchAddForm.startTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择开始日期" style="width: 100%" />
</el-form-item>
<el-form-item label="结束日期" prop="endTime">
<el-date-picker v-model="batchAddForm.endTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择结束日期" style="width: 100%" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="batchAddVisible = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="handleBatchAddSubmit">确定</el-button>
</div>
</el-dialog>
<!-- ==================== 班次学期配档编辑弹窗 ==================== -->
<PeidangEditDialog
:visible="peidangVisible"
:semester-name="semesterName"
:class-label="peidangClassLabel"
@update:visible="val => peidangVisible = val"
@confirm="handleAction('配档编辑')"
/>
<!-- ==================== 快速设定学期日期弹窗 ==================== -->
<el-dialog
:visible="dateRangeVisible"
title="快速设定学期日期"
width="480px"
:close-on-click-modal="false"
@update:visible="val => dateRangeVisible = val"
>
<el-alert
type="info"
:closable="false"
show-icon
:title="`将对选中的 ${selection.length} 条班次学期统一设定开学/结束日期`"
style="margin-bottom: 16px"
/>
<el-form ref="dateRangeFormRef" :model="dateRangeForm" :rules="dateRangeRules" label-width="100px">
<el-form-item label="开学日期" prop="kxrq">
<el-date-picker v-model="dateRangeForm.kxrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择开学日期" style="width: 100%" />
</el-form-item>
<el-form-item label="结束日期" prop="jsrq">
<el-date-picker v-model="dateRangeForm.jsrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择结束日期" style="width: 100%" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="dateRangeVisible = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="handleDateRangeSubmit">确定</el-button>
</div>
</el-dialog>
<!-- ==================== 批量设置教学任务弹窗 ==================== -->
<el-dialog
:visible="jxrwVisible"
title="批量设置教学任务"
width="480px"
:close-on-click-modal="false"
@update:visible="val => jxrwVisible = val"
>
<el-alert
type="info"
:closable="false"
show-icon
:title="`将对选中的 ${selection.length} 条班次学期统一设置教学任务`"
style="margin-bottom: 16px"
/>
<el-form ref="jxrwFormRef" :model="jxrwForm" :rules="jxrwRules" label-width="100px">
<el-form-item label="教学任务" prop="jxrwbh">
<el-select v-model="jxrwForm.jxrwbh" placeholder="请选择教学任务" filterable style="width: 100%">
<el-option v-for="opt in taskOptions" :key="opt.bh" :label="opt.rwmc" :value="opt.bh" />
</el-select>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="jxrwVisible = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="handleJxrwSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import ClassSemesterDetailDialog from './ClassSemesterDetailDialog.vue'
import ClassCalendarDialog from './ClassCalendarDialog.vue'
import ClassTeamSelectDialog from './ClassTeamSelectDialog.vue'
import PeidangEditDialog from './PeidangEditDialog.vue'
import { listSemester, allSemester, addSemester, updateSemester, delSemester, batchDeleteSemester, batchUpdateDateRange, batchUpdateJxrwbh, batchAddFromElective } from '@/api/studentRecords/semester'
import { listAllSemester } from '@/api/teachBusiness/semester'
import { listTeachingTask } from '@/api/teachBusiness/teachingTask'
export default {
name: 'ShiftSemester',
components: {
ClassSemesterDetailDialog,
ClassCalendarDialog,
ClassTeamSelectDialog,
PeidangEditDialog
ClassCalendarDialog
},
data() {
return {
// ==================== 1. 学年学期标题区 ====================
semesterName: '2017-2018学年第一学期',
loading: false,
saving: false,
// ==================== 2. 校历 / 预设日期信息区 ====================
/** 校历日期 */
semester: {
kxrq: '2017-07-08', // 校历开学日期
jsrq: '2018-02-11', // 校历结束日期
weeks: 32 // 学期周数
},
/** 预设(班次)日期 */
preset: {
kxrq: '2017-07-08', // 预设开学日期
jsrq: '2018-02-11', // 预设结束日期
weeks: 32 // 预设学期周数
},
// ==================== 查询条件 ====================
searchForm: { xydbh: '' },
filterYear: undefined,
yearFilterOptions: [],
// ==================== 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,
// ==================== 列表与分页 ====================
tableData: [],
selection: [],
currentRow: null,
pageNum: 1,
pageSize: 10,
total: 0,
/** 预设合班弹窗 */
teamVisible: false,
// ==================== 下拉数据 ====================
/** 年度下拉(来自 /semester/all */
yearOptions: [],
/** 教学任务下拉({ bh, rwmc } */
taskOptions: [],
/** 全部班次学期(用于班历复制目标选择) */
semesterOptions: [],
/** 配档编辑弹窗(班次学期配档)显示状态 */
peidangVisible: false,
/** 配档编辑弹窗标题(班次学期配档——...——班次) */
peidangClassLabel: '',
// ==================== 班次学期新增/编辑 ====================
detailVisible: false,
detailMode: 'add',
detailSemester: null,
detailTeamInfo: null,
/** 排序方式:xh=序号排序 / bw=波次排序 */
sortType: 'xh',
// ==================== 班历管理 ====================
calendarVisible: false,
calendarSemester: null,
/** 波次背景色(同一波次使用同一颜色连在一起显示) */
bwColors: [
'#e3f2fd', // 浅蓝
'#e8f5e9', // 浅绿
'#fff8e1', // 浅黄
'#f3e5f5', // 浅紫
'#e0f2f1' // 浅青
],
// ==================== 批量创建班次学期 ====================
batchAddVisible: false,
batchAddForm: { nd: undefined, xqdc: '', startTime: '', endTime: '' },
batchAddRules: {
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
xqdc: [{ required: true, message: '请选择学期', trigger: 'change' }],
startTime: [{ required: true, message: '请选择开始日期', trigger: 'change' }],
endTime: [{ required: true, message: '请选择结束日期', trigger: 'change' }]
},
// ==================== 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 }
]
// ==================== 快速设定学期日期 ====================
dateRangeVisible: false,
dateRangeForm: { kxrq: '', jsrq: '' },
dateRangeRules: {
kxrq: [{ required: true, message: '请选择开学日期', trigger: 'change' }],
jsrq: [{ required: true, message: '请选择结束日期', trigger: 'change' }]
},
// ==================== 批量设置教学任务 ====================
jxrwVisible: false,
jxrwForm: { jxrwbh: undefined },
jxrwRules: {
jxrwbh: [{ required: true, message: '请选择教学任务', trigger: 'change' }]
}
}
},
computed: {
/** 排序方式标签 */
sortLabel() {
return this.sortType === 'bw' ? '波次排序' : '序号排序'
},
/** 根据排序方式展示列表:波次排序时按波次分组连排 */
/** 本地按年度过滤(后端 /semester/list 仅支持 xydbh 模糊筛选) */
displayData() {
if (this.sortType === 'bw') {
return [...this.tableData].sort((a, b) => a.bw - b.bw || a.xh - b.xh)
}
return this.tableData
if (!this.filterYear) return this.tableData
return this.tableData.filter(item => String(item.nd) === String(this.filterYear))
}
},
mounted() {
// 默认选中第一行 班次0150(高亮)
this.$nextTick(() => {
if (this.tableData.length && this.$refs.tableRef) {
this.$refs.tableRef.setCurrentRow(this.tableData[0])
}
})
this.loadYearOptions()
this.loadTaskOptions()
this.loadSemesterOptions()
this.loadList()
},
methods: {
// ==================== 2. 校历 / 预设日期 ====================
/** 吸取日期:将校历日期复制到预设日期 */
handleAbsorbDate() {
this.preset.kxrq = this.semester.kxrq
this.preset.jsrq = this.semester.jsrq
this.preset.weeks = this.semester.weeks
this.$message.success('已吸取校历日期到预设日期')
/* ==================== 格式化 ==================== */
fmtDate(val) {
if (!val) return '-'
return String(val).slice(0, 10)
},
xqdcLabel(val) {
if (val === 1 || val === '1') return '第1学期'
if (val === 2 || val === '2') return '第2学期'
if (val === 3 || val === '3') return '第3学期'
return val !== undefined && val !== null && val !== '' ? `${val}学期` : '-'
},
/** 教学任务编号 → 名称 */
taskName(bh) {
if (!bh) return '-'
const opt = this.taskOptions.find(o => o.bh === bh)
return opt ? opt.rwmc : bh
},
cleanPayload(obj) {
const payload = {}
Object.keys(obj).forEach(key => {
const value = obj[key]
if (value !== '' && value !== null && value !== undefined) {
payload[key] = value
}
})
return payload
},
/** 快速设定学期日期 */
handleQuickSetDates() {
this.$message.success('快速设定学期日期(前端演示)')
/* ==================== 下拉数据加载 ==================== */
loadYearOptions() {
listAllSemester().then(res => {
const list = (res && res.data) || []
const years = list.map(x => x.nd).filter(v => v !== undefined && v !== null && v !== '')
this.yearOptions = [...new Set(years)].sort((a, b) => Number(a) - Number(b))
}).catch(() => {
this.yearOptions = []
})
},
loadTaskOptions() {
listTeachingTask({ pageNum: 1, pageSize: 1000 }).then(res => {
const list = (res && res.data && res.data.records) || []
this.taskOptions = list.filter(o => o.bh)
}).catch(() => {
this.taskOptions = []
})
},
loadSemesterOptions() {
allSemester().then(res => {
this.semesterOptions = (res && res.data) || []
}).catch(() => {
this.semesterOptions = []
})
},
// ==================== 3. 工具栏按钮区 ====================
/** 通用操作(前端演示) */
handleAction(name) {
this.$message.success(`${name}(前端演示)`)
/* ==================== 列表加载 ==================== */
loadList() {
this.loading = true
const query = this.cleanPayload({
pageNum: this.pageNum,
pageSize: this.pageSize,
xydbh: this.searchForm.xydbh
})
listSemester(query).then(res => {
const data = (res && res.data) || {}
this.tableData = data.records || []
this.total = data.total || 0
this.buildYearFilterOptions()
this.loading = false
}).catch(() => {
this.tableData = []
this.total = 0
this.loading = false
})
},
/** 新添:从下拉选择班次后打开明细弹窗 */
handleNewCommand(item) {
if (typeof item === 'string') return
this.selectedNewClass = item
this.detailVisible = true
/** 本地年度过滤下拉(从当前数据动态生成,避免硬编码) */
buildYearFilterOptions() {
const years = this.tableData.map(r => r.nd).filter(v => v !== undefined && v !== null && v !== '')
this.yearFilterOptions = [...new Set(years)].sort((a, b) => Number(a) - Number(b))
},
handleDetailConfirm() {
this.$message.success('已创建班次学期信息(前端演示)')
handleYearChange() {
this.$nextTick(() => {
if (this.$refs.tableRef) this.$refs.tableRef.setCurrentRow(null)
this.currentRow = null
})
},
/** 编辑班历 */
handleEditCalendar() {
if (!this.currentRow) {
this.$message.warning('请先在列表中选择一条班次学期信息')
return
}
this.calendarVisible = true
handleSizeChange(size) {
this.pageSize = size
this.loadList()
},
/** 预设合班 */
handleMerge() {
this.teamVisible = true
handlePageChange(page) {
this.pageNum = page
this.loadList()
},
handleTeamConfirm(teams) {
this.$message.success(`预设合班已应用于 ${teams.length} 个班次(前端演示)`)
handleSelectionChange(rows) {
this.selection = rows
},
/** 配档编辑:选择班次后打开班次学期配档窗口 */
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 }
/* ==================== 查询 / 重置 ==================== */
handleQuery() {
this.pageNum = 1
this.loadList()
},
handleReset() {
this.searchForm.xydbh = ''
this.filterYear = undefined
this.pageNum = 1
this.loadList()
},
/** 表头特殊样式:总课程数 / 总课时数列红色框标注 */
headerCellClassName({ column }) {
if (column.property === 'kcrws' || column.property === 'kczs') {
return 'red-header-cell'
/* ==================== 新增 / 编辑 ==================== */
handleAdd() {
this.detailMode = 'add'
this.detailSemester = null
this.detailTeamInfo = null
this.detailVisible = true
},
handleEdit(row) {
const target = row || this.currentRow
if (!target) {
this.$message.warning('请先选择一条班次学期信息')
return
}
return ''
this.detailMode = 'edit'
this.detailSemester = target
this.detailTeamInfo = null
this.detailVisible = true
},
handleDetailSubmit(payload) {
this.saving = true
const req = this.detailMode === 'edit'
? updateSemester(payload)
: addSemester(payload)
req.then(() => {
this.saving = false
this.detailVisible = false
this.$message.success(this.detailMode === 'edit' ? '班次学期已更新' : '班次学期已新增')
this.loadList()
this.loadSemesterOptions()
}).catch(() => {
this.saving = false
})
},
/* ==================== 删除 ==================== */
handleDelete() {
if (!this.selection.length) {
this.$message.warning('请先勾选要删除的班次学期')
return
}
this.$confirm(`确定删除选中的 ${this.selection.length} 条班次学期吗?删除后其下班历记录将一并删除。`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const bhList = this.selection.map(r => r.bh)
batchDeleteSemester(bhList).then(() => {
this.$message.success('已删除')
this.loadList()
this.loadSemesterOptions()
})
}).catch(() => {})
},
handleDeleteRow(row) {
this.$confirm(`确定删除班次学期「${row.xydbh || row.bh}」吗?删除后其下班历记录将一并删除。`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delSemester(row.bh).then(() => {
this.$message.success('已删除')
this.loadList()
this.loadSemesterOptions()
})
}).catch(() => {})
},
/* ==================== 编辑班历 ==================== */
handleEditCalendar(row) {
const target = row || this.currentRow
if (!target) {
this.$message.warning('请先在列表中选择一条班次学期信息')
return
}
this.calendarSemester = target
this.calendarVisible = true
},
/* ==================== 批量创建班次学期 ==================== */
handleBatchAdd() {
this.batchAddForm = { nd: this.yearOptions[0] || undefined, xqdc: '', startTime: '', endTime: '' }
this.batchAddVisible = true
this.$nextTick(() => {
if (this.$refs.batchAddFormRef) this.$refs.batchAddFormRef.clearValidate()
})
},
handleBatchAddSubmit() {
this.$refs.batchAddFormRef.validate(valid => {
if (!valid) return
const f = this.batchAddForm
this.saving = true
batchAddFromElective({
nd: f.nd,
xqdc: f.xqdc,
startTime: f.startTime,
endTime: f.endTime
}).then(res => {
this.saving = false
this.batchAddVisible = false
const count = (res && res.data) || 0
this.$message.success(`已创建 ${count} 个班次学期`)
this.loadList()
this.loadSemesterOptions()
}).catch(() => {
this.saving = false
})
})
},
/* ==================== 快速设定学期日期 ==================== */
handleQuickSetDates() {
if (!this.selection.length) {
this.$message.warning('请先勾选要设定日期的班次学期')
return
}
this.dateRangeForm = { kxrq: '', jsrq: '' }
this.dateRangeVisible = true
this.$nextTick(() => {
if (this.$refs.dateRangeFormRef) this.$refs.dateRangeFormRef.clearValidate()
})
},
handleDateRangeSubmit() {
this.$refs.dateRangeFormRef.validate(valid => {
if (!valid) return
const f = this.dateRangeForm
this.saving = true
batchUpdateDateRange({
bhList: this.selection.map(r => r.bh),
xqkssj: f.kxrq,
xqjssj: f.jsrq
}).then(res => {
this.saving = false
this.dateRangeVisible = false
const count = (res && res.data) || 0
this.$message.success(`已更新 ${count} 条班次学期的日期`)
this.loadList()
}).catch(() => {
this.saving = false
})
})
},
/* ==================== 批量设置教学任务 ==================== */
handleSetJxrw() {
if (!this.selection.length) {
this.$message.warning('请先勾选要设置教学任务的班次学期')
return
}
this.jxrwForm = { jxrwbh: undefined }
this.jxrwVisible = true
this.$nextTick(() => {
if (this.$refs.jxrwFormRef) this.$refs.jxrwFormRef.clearValidate()
})
},
handleJxrwSubmit() {
this.$refs.jxrwFormRef.validate(valid => {
if (!valid) return
this.saving = true
batchUpdateJxrwbh({
bhList: this.selection.map(r => r.bh),
jxrwbh: this.jxrwForm.jxrwbh
}).then(res => {
this.saving = false
this.jxrwVisible = false
const count = (res && res.data) || 0
this.$message.success(`已更新 ${count} 条班次学期的教学任务`)
this.loadList()
}).catch(() => {
this.saving = false
})
})
}
}
}
@@ -375,8 +597,8 @@ export default {
}
.shift-semester-page {
// ========== 1. 学年学期标题 ==========
.list-title {
// ========== 页面标题 ==========
.page-title {
font-size: 16px;
font-weight: 600;
color: #303133;
@@ -385,44 +607,12 @@ export default {
border-left: 4px solid var(--edu-green-primary);
}
// ========== 2. 校历 / 预设日期信息区 ==========
// ========== 1. 查询条件区域 ==========
.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. 工具栏按钮区 ==========
// ========== 2. 工具栏按钮区 ==========
.list-toolbar {
display: flex;
align-items: center;
@@ -440,46 +630,19 @@ export default {
}
}
// ========== 新建下拉菜单 ==========
.new-class-menu {
max-height: 320px;
overflow-y: auto;
}
// ========== 4. 数据表格区 ==========
$bwColors: (#e3f2fd, #e8f5e9, #fff8e1, #f3e5f5, #e0f2f1);
// ========== 3. 数据表格区 ==========
.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);
}
.text-danger {
color: #f56c6c;
}
::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;
}
.list-pagination {
margin-top: 12px;
text-align: right;
}
}
}