分组教学任务和教学任务计划管理
This commit is contained in:
@@ -1,25 +1,49 @@
|
||||
<template>
|
||||
<div class="app-container teaching-task-page">
|
||||
<!-- 页面标题 -->
|
||||
<div class="page-title">分组课列表</div>
|
||||
<!-- ==================== 页面标题 ==================== -->
|
||||
<div class="page-title">教学任务列表</div>
|
||||
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="80px" class="search-form">
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="任务名称">
|
||||
<el-input v-model="searchForm.rwmc" placeholder="请输入任务名称" clearable @keyup.enter.native="handleQuery" />
|
||||
<el-input
|
||||
v-model="searchForm.rwmc"
|
||||
placeholder="请输入任务名称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="年度">
|
||||
<el-input-number v-model="searchForm.nd" :controls="false" placeholder="请输入年度" clearable class="w-full" />
|
||||
<el-select
|
||||
v-model="searchForm.nd"
|
||||
placeholder="请选择年度"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="状态">
|
||||
<el-input v-model="searchForm.zt" placeholder="请输入状态" clearable @keyup.enter.native="handleQuery" />
|
||||
<el-select
|
||||
v-model="searchForm.zt"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in statusOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -29,38 +53,30 @@
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 操作区域 ==================== -->
|
||||
<el-card shadow="never" class="action-card">
|
||||
<div class="action-left">
|
||||
<el-button type="primary" @click="handleAdd">新增教学任务</el-button>
|
||||
<el-button type="danger" plain :disabled="selectedRows.length === 0" @click="handleBatchDelete">批量删除</el-button>
|
||||
<el-button type="primary" plain @click="handleDownloadGroupCourseList">下载分组班列表</el-button>
|
||||
<el-button type="primary" plain @click="handleDownloadWord">下载分组班学员名单Word</el-button>
|
||||
<el-button type="primary" plain @click="handleDownloadExcel">下载分组班学员名单Excel</el-button>
|
||||
<el-button type="primary" plain @click="handleDownloadTemplate">【分组课数据文件模板】下载</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 数据表格 ==================== -->
|
||||
<!-- ==================== 2. 数据表格 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="loading" :data="tableData" border stripe highlight-current-row
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<template slot="empty">
|
||||
<span>无数据!</span>
|
||||
</template>
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="bh" label="编号" width="140" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rwmc" label="任务名称" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column prop="bh" label="编号" width="200" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="rwmc" label="任务名称" min-width="160" align="left" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nd" label="年度" width="90" align="center" />
|
||||
<el-table-column prop="zt" label="状态" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="fbsj" label="发布时间" width="150" align="center" :formatter="formatDateTime" />
|
||||
<el-table-column prop="cjsj" label="创建时间" width="150" align="center" :formatter="formatDateTime" />
|
||||
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="handlePublish(row)">发布</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
<el-tag :type="row.zt === '发布' ? 'success' : 'info'" size="small">
|
||||
{{ row.zt || '-' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fbsj" label="发布时间" width="150" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="jssj" label="结束时间" width="150" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="cjsj" label="创建时间" width="150" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="jcxqscsj" label="教材需求生成时间" width="170" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column label="操作" width="80" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleDetail(row)">详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -77,102 +93,107 @@
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 4. 新增/修改对话框 ==================== -->
|
||||
<!-- ==================== 3. 详情对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="520px"
|
||||
:visible="detailVisible"
|
||||
title="教学任务详情"
|
||||
width="620px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
@update:visible="val => detailVisible = val"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="add-form">
|
||||
<el-form-item label="编号" prop="bh">
|
||||
<el-input v-model="form.bh" placeholder="请输入编号" :disabled="isEdit" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="任务名称" prop="rwmc">
|
||||
<el-input v-model="form.rwmc" placeholder="请输入任务名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-input-number v-model="form.nd" :min="0" :controls="false" placeholder="请输入年度" class="w-full" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-input v-model="form.zt" placeholder="请输入状态(选填)" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-descriptions v-if="detailData.bh" :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailData.bh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务名称">{{ detailData.rwmc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年度">{{ fmtVal(detailData.nd) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{ detailData.zt || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="发布时间">{{ fmtVal(detailData.fbsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">{{ fmtVal(detailData.jssj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ fmtVal(detailData.cjsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教材需求生成时间">{{ fmtVal(detailData.jcxqscsj) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-else v-loading="detailLoading" class="detail-empty">加载中...</div>
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
<el-button type="primary" @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listTeachingTask,
|
||||
addTeachingTask,
|
||||
updateTeachingTask,
|
||||
deleteTeachingTask,
|
||||
batchDeleteTeachingTask,
|
||||
publishTeachingTask
|
||||
} from '@/api/teachBusiness/teachingTask'
|
||||
/**
|
||||
* 教学任务列表(只读查询页)
|
||||
* 对应菜单:teachBusiness/teachingTask(原「分组课列表」页,下载类功能后端无接口已移除)
|
||||
* 仅提供 分页查询 list + 详情 get?bh=,不做增删改发(避免与教学任务计划管理页重复操作同一实体)
|
||||
* 增删改发统一在 src/views/teachOffice/taskPlan/index.vue(教学任务计划管理)完成
|
||||
*/
|
||||
import { listTeachingTask, getTeachingTask } from '@/api/teachBusiness/teachingTask'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
|
||||
export default {
|
||||
name: 'TeachingTask',
|
||||
data() {
|
||||
return {
|
||||
pageTitle: '分组课列表',
|
||||
|
||||
// ==================== 1. 查询条件 ====================
|
||||
searchForm: {
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: ''
|
||||
},
|
||||
yearOptions: [],
|
||||
statusOptions: [
|
||||
{ label: '未发布', value: '未发布' },
|
||||
{ label: '发布', value: '发布' }
|
||||
],
|
||||
|
||||
// ==================== 2. 批量选择 ====================
|
||||
selectedRows: [],
|
||||
|
||||
// ==================== 3. 表格数据 ====================
|
||||
// ==================== 2. 表格数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
|
||||
// ==================== 4. 新增/修改表单 ====================
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新增教学任务',
|
||||
isEdit: false,
|
||||
saving: false,
|
||||
form: this.createEmptyForm(),
|
||||
rules: {
|
||||
bh: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||
rwmc: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
||||
nd: [{ required: true, message: '请输入年度', trigger: 'blur' }]
|
||||
}
|
||||
// ==================== 3. 详情 ====================
|
||||
detailVisible: false,
|
||||
detailLoading: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchList()
|
||||
created() {
|
||||
this.loadYearOptions().then(() => this.fetchList())
|
||||
},
|
||||
methods: {
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: ''
|
||||
}
|
||||
/* ---------- 年度下拉(数据来自 /semester/all,禁止硬编码) ---------- */
|
||||
loadYearOptions() {
|
||||
return listAllSemester().then(response => {
|
||||
const list = response.data || []
|
||||
const map = {}
|
||||
list.forEach(item => {
|
||||
if (item.nd !== null && item.nd !== undefined && item.nd !== '') map[item.nd] = item
|
||||
})
|
||||
const arr = Object.keys(map).sort((a, b) => String(b).localeCompare(String(a)))
|
||||
this.yearOptions = arr
|
||||
// 默认年度:优先当前学期(dqxq=true),否则取最新年度
|
||||
const current = list.find(item => item.dqxq === true)
|
||||
const defaultNd = (current && current.nd) || arr[0]
|
||||
if (!this.searchForm.nd) this.searchForm.nd = defaultNd
|
||||
return arr
|
||||
}).catch(() => {
|
||||
this.yearOptions = []
|
||||
return []
|
||||
})
|
||||
},
|
||||
|
||||
/** 后端 LocalDateTime 规范化显示:去掉 T,截断到分钟 */
|
||||
formatDateTime(row, column, cellValue) {
|
||||
/* ---------- 通用格式化 ---------- */
|
||||
fmtDateTime(row, column, cellValue) {
|
||||
if (cellValue === null || cellValue === undefined || cellValue === '') return '-'
|
||||
return String(cellValue).replace('T', ' ').slice(0, 16)
|
||||
},
|
||||
fmtVal(val) {
|
||||
if (val === null || val === undefined || val === '') return '-'
|
||||
return String(val).replace('T', ' ').slice(0, 16)
|
||||
},
|
||||
|
||||
// ==================== 列表加载 ====================
|
||||
/* ---------- 列表加载 ---------- */
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
@@ -193,10 +214,6 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
this.handleQuery()
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
@@ -213,124 +230,17 @@ export default {
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// ==================== 选择 ====================
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
|
||||
// ==================== 新增 / 修改 ====================
|
||||
handleAdd() {
|
||||
this.form = this.createEmptyForm()
|
||||
this.isEdit = false
|
||||
this.dialogTitle = '新增教学任务'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
/* ---------- 详情(只读,走真实 get?bh= 接口) ---------- */
|
||||
handleDetail(row) {
|
||||
this.detailVisible = true
|
||||
this.detailLoading = true
|
||||
this.detailData = {}
|
||||
getTeachingTask(row.bh).then(res => {
|
||||
this.detailData = (res && res.data) || {}
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
this.form = {
|
||||
bh: row.bh || '',
|
||||
rwmc: row.rwmc || '',
|
||||
nd: row.nd,
|
||||
zt: row.zt || ''
|
||||
}
|
||||
this.isEdit = true
|
||||
this.dialogTitle = '修改教学任务'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
const payload = this.buildPayload()
|
||||
this.saving = true
|
||||
const req = this.isEdit ? updateTeachingTask(payload) : addTeachingTask(payload)
|
||||
req.then(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '新增成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/** 构建请求体,仅含实体非空字段(时间字段后端自动维护,不传) */
|
||||
buildPayload() {
|
||||
const f = this.form
|
||||
const payload = {}
|
||||
if (f.bh && String(f.bh).trim()) payload.bh = String(f.bh).trim()
|
||||
if (f.rwmc && String(f.rwmc).trim()) payload.rwmc = String(f.rwmc).trim()
|
||||
if (f.nd !== undefined && f.nd !== null && f.nd !== '') payload.nd = f.nd
|
||||
if (f.zt && String(f.zt).trim()) payload.zt = String(f.zt).trim()
|
||||
return payload
|
||||
},
|
||||
|
||||
// ==================== 删除 ====================
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除「${row.rwmc || row.bh || '该记录'}」吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => deleteTeachingTask(row.bh)).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
handleBatchDelete() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择数据')
|
||||
return
|
||||
}
|
||||
this.$confirm(`确定要删除选中的 ${this.selectedRows.length} 条记录吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const bhList = this.selectedRows.map(r => r.bh)
|
||||
return batchDeleteTeachingTask(bhList)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 发布 ====================
|
||||
handlePublish(row) {
|
||||
this.$confirm(`确定要发布教学任务「${row.rwmc || row.bh || '该记录'}」吗?发布后将同步更新关联教研室任务书状态。`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => publishTeachingTask(row.bh)).then(() => {
|
||||
this.$message.success('发布成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 无后端接口功能 ====================
|
||||
handleDownloadGroupCourseList() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleDownloadWord() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleDownloadExcel() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleDownloadTemplate() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -355,10 +265,6 @@ export default {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
@@ -368,29 +274,22 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 操作区域 ====================
|
||||
.action-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.action-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 3. 数据表格 ====================
|
||||
// ==================== 2. 数据表格 ====================
|
||||
.table-card {
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
// ==================== 3. 详情 ====================
|
||||
.detail-empty {
|
||||
min-height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,4 +309,4 @@ export default {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user