forked from liweijie/education
前端文件
This commit is contained in:
@@ -0,0 +1,554 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<!-- 查询条件 -->
|
||||
<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 label="开始日期">
|
||||
<el-date-picker v-model="searchForm.startDate" type="date" value-format="yyyy-MM-dd" placeholder="选择开始日期"
|
||||
class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="searchForm.endDate" type="date" value-format="yyyy-MM-dd" placeholder="选择结束日期"
|
||||
class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课程名称">
|
||||
<el-input v-model="searchForm.courseName" placeholder="请输入课程名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学方法">
|
||||
<el-select v-model="searchForm.teachMethod" placeholder="请选择教学方法" clearable class="w-full">
|
||||
<el-option v-for="item in teachMethodOptions" :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="改动情况">
|
||||
<el-select v-model="searchForm.change" placeholder="请选择改动情况" clearable class="w-full">
|
||||
<el-option v-for="item in changeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务类别">
|
||||
<el-select v-model="searchForm.taskCategory" placeholder="请选择任务类别" clearable class="w-full">
|
||||
<el-option v-for="item in taskCategoryOptions" :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="教研室">
|
||||
<el-select v-model="searchForm.dept" placeholder="请选择教研室" clearable class="w-full">
|
||||
<el-option v-for="item in deptOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="授课教员">
|
||||
<el-select v-model="searchForm.teacher" placeholder="请选择授课教员" clearable class="w-full">
|
||||
<el-option v-for="item in teacherOptions" :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="培训班">
|
||||
<el-input v-model="searchForm.className" placeholder="请输入培训班" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="search-actions">
|
||||
<div class="left-group">
|
||||
<el-button v-if="!isTeacher" type="primary" @click="handleBatchAudit">审核通过所选</el-button>
|
||||
<el-button icon="el-icon-download" @click="handleExport">导出到 Word</el-button>
|
||||
</div>
|
||||
<div class="right-group">
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<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 v-if="!isTeacher" type="selection" width="50" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="rwlb" label="任务类别" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jyxm" label="主讲教员" width="100" align="center" />
|
||||
<el-table-column prop="rq" label="日期" width="150" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.rq ? formatDate(scope.row.rq) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="节次" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.qsjc && scope.row.jsjc ? `${scope.row.qsjc}-${scope.row.jsjc}节` : (scope.row.qsjc || '-') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kcmc" label="课程名称" width="80" show-overflow-tooltip />
|
||||
<el-table-column prop="pxqbxx" label="培训期班信息" show-overflow-tooltip />
|
||||
<el-table-column label="人数" width="80" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.sdrs || scope.row.ydrs || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="分组指导教员" width="100" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.fzyzdjy || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jsfs" label="教学方法" width="80" align="center" />
|
||||
<el-table-column prop="zt" label="日志状态" width="100" align="center" />
|
||||
<el-table-column prop="gdqk" label="变动汇总" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="jxrzcjfs" label="创建方式" width="100" align="center" />
|
||||
<el-table-column v-if="!isTeacher" label="操作" width="160" align="center" fixed="right" class-name="table-action-column">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleAudit(scope.row)">审核</el-button>
|
||||
<el-button type="text" @click="handleReject(scope.row)">退回</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-wrapper">
|
||||
<el-pagination :current-page="pageNum" :page-size="pageSize" :total="total" :page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="handlePageChange"
|
||||
@size-change="handleSizeChange" />
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 日志详情对话框 -->
|
||||
<el-dialog :visible.sync="detailVisible" title="教学日志详情" width="700px" destroy-on-close>
|
||||
<div v-loading="detailLoading">
|
||||
<el-descriptions v-if="!detailLoading" :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailData.bh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="统一编号">{{ detailData.tybh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教员编号">{{ detailData.jybh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教员姓名">{{ detailData.jyxm || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="课程名称">{{ detailData.kcmc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务类别">{{ detailData.rwlb || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="日期">{{ detailData.rq || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="节次">
|
||||
{{ detailData.qsjc && detailData.jsjc ? `${detailData.qsjc}-${detailData.jsjc}节` : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="教学方法">{{ detailData.jsfs || detailData.jxff || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建方式">{{ detailData.jxrzcjfs || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="应到人数">{{ detailData.ydrs || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="实到人数">{{ detailData.sdrs || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训期班信息" :span="2">{{ detailData.pxqbxx || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="授课地点" :span="2">{{ detailData.skdd || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{ detailData.zt || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室">{{ detailData.jysmc || detailData.jys || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="变动汇总" :span="2">{{ detailData.gdqk || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="变动详细情况" :span="2">{{ detailData.gdxxqk || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="退回意见" :span="2">{{ detailData.thyj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ detailData.cjsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="修改时间">{{ detailData.xgsj || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="detailVisible = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { formatDate } from '@/utils/index'
|
||||
import {
|
||||
getReportedTeachingLogList,
|
||||
rejectTeachingLog,
|
||||
exportTeachingLog,
|
||||
getTeachingLogByBh,
|
||||
batchAuditTeachingLog
|
||||
} from '@/api/log'
|
||||
|
||||
export default {
|
||||
name: 'ReportedView',
|
||||
props: {
|
||||
/** 当前用户是否为教员角色,用于隐藏审核相关操作 */
|
||||
isTeacher: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// ==================== 查询表单 ====================
|
||||
searchForm: {
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
courseName: '',
|
||||
teachMethod: '',
|
||||
change: '',
|
||||
taskCategory: '',
|
||||
dept: '',
|
||||
teacher: '',
|
||||
className: ''
|
||||
},
|
||||
|
||||
teachMethodOptions: ['理论讲授', '实践教学', '研讨教学', '案例教学', '实操演练'],
|
||||
changeOptions: [
|
||||
'与教学计划一致',
|
||||
'已改动教学计划',
|
||||
'手动拟制',
|
||||
'教员变动',
|
||||
'时间变动',
|
||||
'课程变动',
|
||||
'授课方式变动',
|
||||
'任务类别变动',
|
||||
'期班变动',
|
||||
'地点变动',
|
||||
'课题变动'
|
||||
],
|
||||
taskCategoryOptions: ['全军院校训练规划内任务', '其他任务(含研究生导师指导)'],
|
||||
deptOptions: ['教务处', '指挥系', '政治工作教研室', '军事基础教研室', '装备保障教研室'],
|
||||
teacherOptions: ['教务处', '张三', '李四', '王五', '赵六', '孙七'],
|
||||
|
||||
// ==================== 数据表格 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
selectedRows: [],
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
|
||||
// ==================== 退回意见 ====================
|
||||
remark: '',
|
||||
|
||||
// ==================== 详情 ====================
|
||||
detailVisible: false,
|
||||
detailLoading: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
|
||||
/** 组件方法:包一层全局 formatDate,供模板调用 */
|
||||
formatDate(val) {
|
||||
return formatDate(val)
|
||||
},
|
||||
|
||||
/** 根据已填写的查询值构建实际查询参数 */
|
||||
buildSearchParams() {
|
||||
const form = this.searchForm
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
if (form.startDate) params.ksrq = form.startDate
|
||||
if (form.endDate) params.jsrq = form.endDate
|
||||
if (form.courseName) params.kcmc = form.courseName
|
||||
if (form.teachMethod) params.jxff = form.teachMethod
|
||||
if (form.change) params.gdqk = form.change
|
||||
if (form.taskCategory) params.rwlb = form.taskCategory
|
||||
if (form.dept) params.jys = form.dept
|
||||
if (form.teacher) params.skjy = form.teacher
|
||||
if (form.className) params.pxqb = form.className
|
||||
return params
|
||||
},
|
||||
|
||||
extractListData(res) {
|
||||
const data = res.data || res
|
||||
const list = data.records || data.list || data.rows || []
|
||||
const totalCount = data.total ?? data.totalCount ?? data.totalRows ?? 0
|
||||
return { list, total: totalCount }
|
||||
},
|
||||
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
return getReportedTeachingLogList(this.buildSearchParams())
|
||||
.then((res) => {
|
||||
// 列表接口返回裸 PageResult(无 code 包装),拦截器已保证成功,直接取数据
|
||||
const { list, total } = this.extractListData(res)
|
||||
this.tableData = list
|
||||
this.total = total
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleReset() {
|
||||
this.searchForm = {
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
courseName: '',
|
||||
teachMethod: '',
|
||||
change: '',
|
||||
taskCategory: '',
|
||||
dept: '',
|
||||
teacher: '',
|
||||
className: ''
|
||||
}
|
||||
this.remark = ''
|
||||
this.handleSearch()
|
||||
},
|
||||
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
getSelectedBhs() {
|
||||
const ids = this.selectedRows.map((row) => row.bh).filter(Boolean)
|
||||
if (ids.length === 0) {
|
||||
this.$message.warning('请先选择记录')
|
||||
return []
|
||||
}
|
||||
return ids
|
||||
},
|
||||
|
||||
handleDelete() {
|
||||
// 后端暂未提供删除接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleBatchAudit() {
|
||||
const ids = this.getSelectedBhs()
|
||||
if (ids.length === 0) return
|
||||
this.$confirm(`确定要审核通过选中的 ${ids.length} 条记录吗?`, '审核确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
// 批量审核教学日志
|
||||
return batchAuditTeachingLog(ids)
|
||||
})
|
||||
.then(() => {
|
||||
this.$message.success(`已审核通过 ${ids.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
handleAudit(row) {
|
||||
const bh = row && row.bh
|
||||
if (!bh) {
|
||||
this.$message.warning('记录编号不存在,无法审核')
|
||||
return
|
||||
}
|
||||
this.$confirm('确定要审核通过该条教学日志吗?', '审核确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => batchAuditTeachingLog([String(bh)]))
|
||||
.then(() => {
|
||||
this.$message.success('审核通过成功')
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
handleReject(row) {
|
||||
const bh = row && row.bh
|
||||
if (!bh) {
|
||||
this.$message.warning('记录编号不存在,无法退回')
|
||||
return
|
||||
}
|
||||
this.$prompt('请输入退回原因/意见', '退回确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: /\S/,
|
||||
inputErrorMessage: '退回原因不能为空'
|
||||
})
|
||||
.then(({ value }) => rejectTeachingLog(String(bh), value.trim()))
|
||||
.then(() => {
|
||||
this.$message.success('退回成功')
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
handleWithdraw() {
|
||||
const ids = this.getSelectedBhs()
|
||||
if (ids.length === 0) return
|
||||
if (!this.remark.trim()) {
|
||||
this.$message.warning('请填写退回原因/意见')
|
||||
return
|
||||
}
|
||||
const opinion = this.remark.trim()
|
||||
let settled = Promise.resolve()
|
||||
ids.forEach((bh) => {
|
||||
settled = settled.then(() => rejectTeachingLog(bh, opinion))
|
||||
})
|
||||
this.$confirm(`确定要撤回重填选中的 ${ids.length} 条记录吗?`, '撤回确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => settled)
|
||||
.then(() => {
|
||||
this.$message.success(`已撤回 ${ids.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
handleRecheck() {
|
||||
// 后端暂未提供重新检查接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
downloadBlob(blob, fileName) {
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = fileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
window.URL.revokeObjectURL(url)
|
||||
},
|
||||
|
||||
handleExport() {
|
||||
const params = this.buildSearchParams()
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
exportTeachingLog(params)
|
||||
.then((blob) => {
|
||||
this.downloadBlob(blob, `已上报教学日志_${new Date().toISOString().slice(0, 10)}.xls`)
|
||||
this.$message.success('导出成功')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
handleDetail(row) {
|
||||
this.detailData = { ...row }
|
||||
this.detailVisible = true
|
||||
const bh = row.bh
|
||||
if (!bh) return
|
||||
this.detailLoading = true
|
||||
getTeachingLogByBh(String(bh))
|
||||
.then((res) => {
|
||||
if ((res.code === 200 || res.code === 0) && res.data) {
|
||||
this.detailData = res.data
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .el-row {
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-col {
|
||||
border-right: 1px solid #ebeef5;
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
white-space: normal;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
padding: 6px 12px 0;
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
|
||||
.left-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.action-input {
|
||||
width: 240px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-card {
|
||||
.el-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 16px 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user