forked from liweijie/education
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 215a48446d | |||
| 3ac8c9496e | |||
| a5cd5eab44 | |||
| 5e3217dc8f | |||
| ee25e06680 | |||
| 137528beb2 | |||
| a29c357ed2 | |||
| c2098878b1 | |||
| 08b1ea4606 | |||
| 43f1aab297 | |||
| 71257bdce0 | |||
| 526b9082df | |||
| 499518a2a6 | |||
| 18bbfd71ba | |||
| ec448a1977 | |||
| 0a25dac2c1 | |||
| a8aba532e2 | |||
| 8bf726a745 | |||
| 26fe8ea334 | |||
| 5fb95ae476 | |||
| 2d3150c566 | |||
| 0c3de2809e | |||
| 24ca73ffa5 | |||
| 24907a7621 | |||
| 4b952280b3 | |||
| 12214a326f | |||
| c7f334ed53 | |||
| 088a35c9e8 | |||
| 18f1faba5f | |||
| 0ea410ffec | |||
| 29387b3193 | |||
| 001a264f16 | |||
| 1abadfb3ff | |||
| cc623d5fdb | |||
| 370cb615d0 | |||
| 97562579dc | |||
| 7a453e4ac3 | |||
| a4b3c241a2 | |||
| fe008ce383 | |||
| 657774e1b1 | |||
| 4efb84e5d2 | |||
| 776ffaac4f | |||
| 8a8aa0c7ca | |||
| 61ef0c1214 |
+2
-11
@@ -1,20 +1,11 @@
|
||||
<template>
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
<theme-picker />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ThemePicker from "@/components/ThemePicker"
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: { ThemePicker }
|
||||
name: "App"
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
#app .theme-picker {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 课时补助核算:课时统计 / 课时费统计 ========================
|
||||
// 接口前缀 /ks,经 vue.config.js 代理转发为 /api/ks;返回行为 HourStatisticsVO。
|
||||
|
||||
// 分页查询课时统计(支持 nd 年度、xq 学期序号、jyxm 教员姓名)
|
||||
export function listHourStatistics(query) {
|
||||
return request({
|
||||
url: '/ks/hour-stat/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 导出课时统计 Excel(返回 Blob,文件名 课时统计.xlsx)
|
||||
export function exportHourStatistics(query) {
|
||||
return request({
|
||||
url: '/ks/hour-stat/export',
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 分页查询课时费统计(支持 nd、xq、jyxm、ksfbzbh 课时费标准编号)
|
||||
export function listFeeStatistics(query) {
|
||||
return request({
|
||||
url: '/ks/fee-stat/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 导出课时费统计 Excel(返回 Blob,文件名 课时费统计.xlsx)
|
||||
export function exportFeeStatistics(query) {
|
||||
return request({
|
||||
url: '/ks/fee-stat/export',
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 联教联训管理(课时补助项目) ========================
|
||||
// 接口前缀 /ks,经 vue.config.js 代理转发为 /api/ks;后端实体为 KSBZXM。
|
||||
|
||||
// 新增联教联训(编号为空时后端自动生成 UUID)
|
||||
export function addJointTraining(data) {
|
||||
return request({
|
||||
url: '/ks/yjlx/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除联教联训
|
||||
export function deleteJointTraining(bh) {
|
||||
return request({
|
||||
url: '/ks/yjlx/delete',
|
||||
method: 'post',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 修改联教联训
|
||||
export function updateJointTraining(data) {
|
||||
return request({
|
||||
url: '/ks/yjlx/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 按编号查询联教联训详情
|
||||
export function getJointTraining(bh) {
|
||||
return request({
|
||||
url: '/ks/yjlx/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 分页查询联教联训列表(支持名称模糊)
|
||||
export function listJointTraining(query) {
|
||||
return request({
|
||||
url: '/ks/yjlx/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 导入联教联训 Excel(multipart,字段名 file)
|
||||
export function importJointTraining(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request({
|
||||
url: '/ks/yjlx/import',
|
||||
method: 'post',
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
// 导出联教联训到 Excel(返回 Blob)
|
||||
export function exportJointTraining() {
|
||||
return request({
|
||||
url: '/ks/yjlx/export',
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 方案管理:课时费方案 / 课时方案 ========================
|
||||
// 接口前缀 /ks,经 vue.config.js 代理转发为 /api/ks。
|
||||
|
||||
// ---------- 课时费方案(KSFBZ) ----------
|
||||
// 分页列表(名称模糊)
|
||||
export function listFeeStandard(query) {
|
||||
return request({
|
||||
url: '/ks/fee-standard/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 详情
|
||||
export function getFeeStandard(bh) {
|
||||
return request({
|
||||
url: '/ks/fee-standard/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增(编号为空时后端自动生成 UUID)
|
||||
export function addFeeStandard(data) {
|
||||
return request({
|
||||
url: '/ks/fee-standard/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑(编号必传)
|
||||
export function updateFeeStandard(data) {
|
||||
return request({
|
||||
url: '/ks/fee-standard/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除
|
||||
export function deleteFeeStandard(bh) {
|
||||
return request({
|
||||
url: '/ks/fee-standard/delete',
|
||||
method: 'post',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// ---------- 课时方案(KSXSFA) ----------
|
||||
// 分页列表(名称模糊)
|
||||
export function listCoefficientPlan(query) {
|
||||
return request({
|
||||
url: '/ks/coefficient-plan/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 详情
|
||||
export function getCoefficientPlan(bh) {
|
||||
return request({
|
||||
url: '/ks/coefficient-plan/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增(编号为空时后端自动生成 UUID)
|
||||
export function addCoefficientPlan(data) {
|
||||
return request({
|
||||
url: '/ks/coefficient-plan/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑(编号必传)
|
||||
export function updateCoefficientPlan(data) {
|
||||
return request({
|
||||
url: '/ks/coefficient-plan/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
+39
-43
@@ -1,10 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 教学日志核心 ========================
|
||||
// 说明:以下接口均已与实际运行的后端 LogController 逐一核对(前缀 /log,
|
||||
// 经 vue.config.js 代理转发为 /api/log)。axios baseURL 为 /api(.env.development)。
|
||||
// ======================== 教学日志核心(以 api.txt 为准) ========================
|
||||
// 接口前缀 /log,经 vue.config.js 代理转发为 /api/log(axios baseURL 为 /api)。
|
||||
|
||||
// 分页条件查询教学日志列表(待上报 / 待审核视图)
|
||||
// 分页条件查询教学日志列表(待上报视图)
|
||||
// 支持参数:pageNum pageSize ksrq jsrq kcmc jys jxff skjy rzzt pxqb gdqk gdxxqk rwlb
|
||||
export function getTeachingLogList(query) {
|
||||
return request({
|
||||
@@ -32,7 +31,7 @@ export function getAuditedTeachingLogList(query) {
|
||||
})
|
||||
}
|
||||
|
||||
// 新增教学日志
|
||||
// 新增教学日志(请求体为 SSKCB_RZ 实体)
|
||||
export function addTeachingLog(data) {
|
||||
return request({
|
||||
url: '/log/teaching-log/add',
|
||||
@@ -41,21 +40,39 @@ export function addTeachingLog(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 批量上报教学日志(入参为 bh 编号数组,Content-Type: application/json)
|
||||
export function batchReportTeachingLog(bhList) {
|
||||
// 编辑教学日志(请求体为 SSKCB_RZ 实体,bh 必传)
|
||||
export function updateTeachingLog(data) {
|
||||
return request({
|
||||
url: '/log/teaching-log/batch-report',
|
||||
url: '/log/teaching-log/update',
|
||||
method: 'post',
|
||||
data: bhList
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量审核教学日志(入参为 bh 编号数组)
|
||||
export function batchAuditTeachingLog(bhList) {
|
||||
// 根据编号查询教学日志详情
|
||||
export function getTeachingLogByBh(bh) {
|
||||
return request({
|
||||
url: '/log/teaching-log/batch-audit',
|
||||
url: '/log/teaching-log/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 提交教学日志审核,接口形态:POST /log/teaching-log/submit?bh=&targetStatus=
|
||||
export function submitTeachingLog(bh, targetStatus) {
|
||||
return request({
|
||||
url: '/log/teaching-log/submit',
|
||||
method: 'post',
|
||||
data: bhList
|
||||
params: { bh: bh, targetStatus: targetStatus }
|
||||
})
|
||||
}
|
||||
|
||||
// 审核通过教学日志,接口形态:GET /log/teaching-log/approve?bh=&feedback=
|
||||
export function approveTeachingLog(bh, feedback) {
|
||||
return request({
|
||||
url: '/log/teaching-log/approve',
|
||||
method: 'get',
|
||||
params: { bh: bh, feedback: feedback }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -68,6 +85,15 @@ export function rejectTeachingLog(bh, thyj) {
|
||||
})
|
||||
}
|
||||
|
||||
// 根据课表自动创建教学日志,接口形态:POST /log/teaching-log/auto-create?tybh=
|
||||
export function autoCreateTeachingLog(tybh) {
|
||||
return request({
|
||||
url: '/log/teaching-log/auto-create',
|
||||
method: 'post',
|
||||
params: { tybh: tybh }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量导入教学日志 Excel,接口形态:POST /log/teaching-log/import-excel(multipart,字段名 file)
|
||||
export function importTeachingLogExcel(file) {
|
||||
const formData = new FormData()
|
||||
@@ -97,33 +123,3 @@ export function downloadTeachingLogTemplate() {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// ======================== TODO:后端暂未提供,保留占位待接 ========================
|
||||
|
||||
// TODO(后端缺接口):批量删除教学日志 —— 当前后端 LogController 无 delete 接口,
|
||||
// 待后端提供后确认入参与请求方式。
|
||||
export function deleteTeachingLog(bhList) {
|
||||
return request({
|
||||
url: '/log/teaching-log/delete',
|
||||
method: 'post',
|
||||
data: bhList
|
||||
})
|
||||
}
|
||||
|
||||
// TODO(后端缺接口):重新检查通报变更情况 —— 当前后端无 recheck 接口,待后端提供后确认。
|
||||
export function recheckTeachingLog() {
|
||||
return request({
|
||||
url: '/log/teaching-log/recheck',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// TODO(后端缺接口):根据编号查询教学日志详情 —— 当前后端无 teaching-log/get 接口。
|
||||
// 列表接口已含完整字段,组件以行数据兜底展示;待后端提供 get 接口后再联调。
|
||||
export function getTeachingLogByBh(bh) {
|
||||
return request({
|
||||
url: '/log/teaching-log/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 教学实施计划导入 ========================
|
||||
// 接口前缀 /teachingPlan,经 vue.config.js 代理转发为 /api/teachingPlan。
|
||||
|
||||
// 分页查询教学实施计划列表
|
||||
// 支持参数:pageNum pageSize nd kcmc bc zrdw skjy ytgjc ybdr(与后端 Mapper 一致)
|
||||
export function listTeachingPlan(query) {
|
||||
return request({
|
||||
url: '/teachingPlan/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 导入教学实施计划 Excel(multipart,字段名 file),返回导入条数
|
||||
export function importTeachingPlan(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request({
|
||||
url: '/teachingPlan/import',
|
||||
method: 'post',
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
// 下载教学实施计划导入模板(返回 Blob)
|
||||
export function downloadTeachingPlanTemplate() {
|
||||
return request({
|
||||
url: '/teachingPlan/template',
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 学员学籍异动申请(实体 XYXJYDSQB) ========================
|
||||
// 列表查询仅支持 bh / xybh / sqlx / zt 四个等值筛选。
|
||||
|
||||
// 分页查询学籍异动申请列表
|
||||
export function listApplication(query) {
|
||||
return request({
|
||||
url: '/student-records/application/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询学籍异动申请详情(bh 异动申请编号)
|
||||
export function getApplication(bh) {
|
||||
return request({
|
||||
url: '/student-records/application/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增学籍异动申请(请求体 XYXJYDSQB 实体;bh 需前端传入,创建/修改时间后端自动维护)
|
||||
export function addApplication(data) {
|
||||
return request({
|
||||
url: '/student-records/application/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑学籍异动申请(bh 异动申请编号必传,请求体 XYXJYDSQB 实体)
|
||||
export function updateApplication(data) {
|
||||
return request({
|
||||
url: '/student-records/application/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除学籍异动申请(bh 异动申请编号)
|
||||
export function delApplication(bh) {
|
||||
return request({
|
||||
url: '/student-records/application/delete',
|
||||
method: 'post',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 班历管理(实体 XYDRWB 学员队任务表) ========================
|
||||
// 接口依据:api2.txt「班次学期日历(班历)」分组 + StudentTeamTaskController
|
||||
// 每个班次学期(xydxqbh)下挂若干条课程任务记录:
|
||||
// bh 编号、nd 年度、xydbh 学员队编号、kbh 课编号、xqdc 学期第次、jybh 教员编号、kcxh 课次序号、
|
||||
// jsbh 教室编号、rs 人数、zks 周课时、xs 学时、klx 课类型、jc 简称、ksdd 考试地点、ksbh 考试编号、
|
||||
// jysdh 教研室代号、jysjhjybh 教研室计划教员编号、jysjhbz 教研室计划备注、jhkcxh 计划课次序号、
|
||||
// xhbs 序号标识、xydxqbh 学员队学期编号、bz 备注、xf 学分、cjsj/bdsj/kbbdsj 时间、
|
||||
// ksks 考试课时、bz2 编组、cjfz 成绩分制、bjrxypjf 不计入学员平均分、llxs 理论学时、sjxs 实践学时、
|
||||
// ksksbxs 考试课时不显示、pdxh 配档序号、pdqsz 配档起始周、pdaz 配档按周、pdzzksj 配档占正课时间、
|
||||
// pdbz 配档编组、pdtbykxxbz 配当同班异课选修编组、pdzdyxsfbsj 配档自定义学时分布数据、
|
||||
// pdqyzdyxs 配档启用自定义学时
|
||||
|
||||
// 查询某班次学期下的全部班历记录(xydxqbh 学员队学期编号)
|
||||
export function listClassCalendar(xydxqbh) {
|
||||
return request({
|
||||
url: '/classCalendar/all',
|
||||
method: 'get',
|
||||
params: { xydxqbh: xydxqbh }
|
||||
})
|
||||
}
|
||||
|
||||
// 根据主键查询班历记录
|
||||
export function getClassCalendar(bh) {
|
||||
return request({
|
||||
url: '/classCalendar/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 更新班历记录(请求体 XYDRWB,bh 必传)
|
||||
export function updateClassCalendar(data) {
|
||||
return request({
|
||||
url: '/classCalendar/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 选定区域设置应用于其它班次(请求体 { sourceBhList: 源记录编号, targetBhList: 目标班次学期编号 })
|
||||
export function batchCopyCalendar(data) {
|
||||
return request({
|
||||
url: '/classCalendar/batchCopy',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 整个班历应用于其它班次(请求体 { sourceXydxqbh: 源班次学期编号, targetBhList: 目标班次学期编号 })
|
||||
export function batchCopyCalendarBySemester(data) {
|
||||
return request({
|
||||
url: '/classCalendar/batchCopyBySemester',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// ======================== 学员队任务表操作(/studentTeamTask) ========================
|
||||
|
||||
// 新增班历记录(请求体 XYDRWB;bh 留空后端生成 UUID)
|
||||
export function addTeamTask(data) {
|
||||
return request({
|
||||
url: '/studentTeamTask/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除班历记录(bh 编号)
|
||||
export function delTeamTask(bh) {
|
||||
return request({
|
||||
url: '/studentTeamTask/delete',
|
||||
method: 'post',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量预设合班(请求体 { bhList },按年度排序生成统一课次序号)
|
||||
export function batchPresetMerge(bhList) {
|
||||
return request({
|
||||
url: '/studentTeamTask/batchPresetMerge',
|
||||
method: 'post',
|
||||
data: { bhList: bhList }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量预设拆班(请求体 { bhList },清空课次序号)
|
||||
export function batchPresetSplit(bhList) {
|
||||
return request({
|
||||
url: '/studentTeamTask/batchPresetSplit',
|
||||
method: 'post',
|
||||
data: { bhList: bhList }
|
||||
})
|
||||
}
|
||||
|
||||
// 自动生成必修课程(按学员队+学期第次从专业教学计划生成班历记录)
|
||||
export function autoGenerateRequiredCourses(xydbh, xqdc) {
|
||||
return request({
|
||||
url: '/studentTeamTask/autoGenerateRequiredCourses',
|
||||
method: 'post',
|
||||
params: { xydbh: xydbh, xqdc: xqdc }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 班次学期管理(实体 XYDNDXQJBXXB 学员队年度学期基本信息表) ========================
|
||||
// 接口依据:api1.txt「班次学期」分组,实际后端位于 StudentRecordsController (/student-records/semester/*)
|
||||
// 列表仅支持 xydbh(学员队编号)模糊筛选,无年度筛选,前端需本地过滤
|
||||
// 新增 bh 留空由后端生成 UUID;字段 nd 年度、xydbh 学员队编号、kxrq 开学日期、jsrq 结束日期、
|
||||
// xqdc 学期第次、zyjsbh 专用教室编号、jxrwbh 教学任务编号、bdsj 变动时间、bz 备注、
|
||||
// xhbs 序号标识、ysbbh 预设编班号、jclb 节次类别、xtms 系统模式、kfjypk 开放教员排课(0/1)、
|
||||
// jsonzd、fxbgscsj 分析报告生成时间、fxbgwd1bh/fxbgwd2bh/fxbgwd3bh 分析报告文档编号
|
||||
|
||||
// 分页查询班次学期列表(支持 xydbh 模糊)
|
||||
export function listSemester(query) {
|
||||
return request({
|
||||
url: '/student-records/semester/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询所有有效班次学期(DEL_FLAG = 0)
|
||||
export function allSemester() {
|
||||
return request({
|
||||
url: '/student-records/semester/all',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询班次学期详情(bh 编号)
|
||||
export function getSemester(bh) {
|
||||
return request({
|
||||
url: '/student-records/semester/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增班次学期(请求体 XYDNDXQJBXXB;bh 留空后端生成 UUID,delFlag 后端置 0)
|
||||
export function addSemester(data) {
|
||||
return request({
|
||||
url: '/student-records/semester/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑班次学期(bh 编号必传,请求体 XYDNDXQJBXXB)
|
||||
export function updateSemester(data) {
|
||||
return request({
|
||||
url: '/student-records/semester/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除班次学期(逻辑删除并级联删除其班历记录)
|
||||
export function delSemester(bh) {
|
||||
return request({
|
||||
url: '/student-records/semester/delete',
|
||||
method: 'post',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量删除班次学期(请求体为编号数组)
|
||||
export function batchDeleteSemester(bhList) {
|
||||
return request({
|
||||
url: '/student-records/semester/batchDelete',
|
||||
method: 'post',
|
||||
data: bhList
|
||||
})
|
||||
}
|
||||
|
||||
// 批量设定学期日期(请求体 { bhList, xqkssj, xqjssj })
|
||||
export function batchUpdateDateRange(data) {
|
||||
return request({
|
||||
url: '/student-records/semester/batchUpdateDateRange',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量修改开放教员排课状态(请求体 { bhList, kfjypk },0-否 1-是)
|
||||
export function batchUpdateKfjypk(data) {
|
||||
return request({
|
||||
url: '/student-records/semester/batchUpdateKfjypk',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量修改学期第次(请求体 { bhList, xqdc })
|
||||
export function batchUpdateXqdc(data) {
|
||||
return request({
|
||||
url: '/student-records/semester/batchUpdateXqdc',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量设置教学任务(请求体 { bhList, jxrwbh })
|
||||
export function batchUpdateJxrwbh(data) {
|
||||
return request({
|
||||
url: '/student-records/semester/batchUpdateJxrwbh',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量创建班次学期(按时间范围筛选可建班的学员队;xqdc 传 春季学期/夏季学期/秋季学期)
|
||||
// 参数:startTime 起始日、endTime 截止日、nd 年度、xqdc 学期
|
||||
export function batchAddFromElective(params) {
|
||||
return request({
|
||||
url: '/student-records/semester/batchAddFromElective',
|
||||
method: 'post',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 班次(学员队)管理(实体 XYDB) ========================
|
||||
// 分页列表查询条件为 XYDB 实体字段。
|
||||
|
||||
// 分页查询学员队列表
|
||||
export function listTeam(query) {
|
||||
return request({
|
||||
url: '/student-records/team/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询学员队详情(xydbh 学员队编号)
|
||||
export function getTeam(xydbh) {
|
||||
return request({
|
||||
url: '/student-records/team/get',
|
||||
method: 'get',
|
||||
params: { xydbh: xydbh }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增学员队(请求体 XYDB)
|
||||
export function addTeam(data) {
|
||||
return request({
|
||||
url: '/student-records/team/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑学员队(xydbh 学员队编号必传,请求体 XYDB)
|
||||
export function updateTeam(data) {
|
||||
return request({
|
||||
url: '/student-records/team/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除学员队(xydbh 学员队编号)
|
||||
export function delTeam(xydbh) {
|
||||
return request({
|
||||
url: '/student-records/team/delete',
|
||||
method: 'post',
|
||||
params: { xydbh: xydbh }
|
||||
})
|
||||
}
|
||||
|
||||
// 导入学员队 Excel(multipart,字段名 file)
|
||||
export function importTeam(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request({
|
||||
url: '/student-records/team/import',
|
||||
method: 'post',
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
// 导出学员队 Excel(查询条件为 XYDB 实体)
|
||||
export function exportTeam(query) {
|
||||
return request({
|
||||
url: '/student-records/team/export',
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ======================== 学员学籍预警结果(实体 XYXJYJGJG,查询:实体类) ========================
|
||||
|
||||
// 分页查询预警结果列表
|
||||
export function listWarningResult(query) {
|
||||
return request({
|
||||
url: '/student-records/warning-result/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询预警结果详情(bh 预警结果编号)
|
||||
export function getWarningResult(bh) {
|
||||
return request({
|
||||
url: '/student-records/warning-result/get',
|
||||
method: 'get',
|
||||
params: { bh: bh }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询学科专业列表
|
||||
export function listDiscipline(query) {
|
||||
return request({
|
||||
url: '/discipline/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询学科专业详情
|
||||
export function getDiscipline(bsh) {
|
||||
return request({
|
||||
url: '/discipline/get',
|
||||
method: 'get',
|
||||
params: { bsh: bsh }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增学科专业
|
||||
export function addDiscipline(data) {
|
||||
return request({
|
||||
url: '/discipline/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑学科专业
|
||||
export function updateDiscipline(data) {
|
||||
return request({
|
||||
url: '/discipline/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 停用学科专业
|
||||
export function disableDiscipline(bsh) {
|
||||
return request({
|
||||
url: '/discipline/disable',
|
||||
method: 'post',
|
||||
params: { bsh: bsh }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 教学场地/教室管理(JSB 教室表 /classroom)
|
||||
// 接口依据:classroom 控制器(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 新增教室
|
||||
* POST /classroom/add
|
||||
* 请求体(JSB):id/jsbh/jsmc 必填,其余字段可空;ty/xslx 为 Boolean
|
||||
*/
|
||||
export function addClassroom(data) {
|
||||
return request({
|
||||
url: '/classroom/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除教室(不提供批量删除接口)
|
||||
* POST /classroom/delete
|
||||
* @param id 教室编号(主键,必填)
|
||||
*/
|
||||
export function deleteClassroom(id) {
|
||||
return request({
|
||||
url: '/classroom/delete',
|
||||
method: 'post',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新教室
|
||||
* POST /classroom/update
|
||||
* 请求体(JSB):id 必传
|
||||
*/
|
||||
export function updateClassroom(data) {
|
||||
return request({
|
||||
url: '/classroom/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据编号查询教室详情
|
||||
* GET /classroom/get
|
||||
* @param id 教室编号
|
||||
*/
|
||||
export function getClassroom(id) {
|
||||
return request({
|
||||
url: '/classroom/get',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询教室列表
|
||||
* GET /classroom/list
|
||||
* 查询参数:jsbh(模糊)、jsmc(模糊)、jxldh(等值)、jxcdlx(等值)、ty(等值)、pageNum、pageSize
|
||||
* 返回:PageResult<JSB>(records/total)
|
||||
*/
|
||||
export function listClassroom(params) {
|
||||
return request({
|
||||
url: '/classroom/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询全部教室
|
||||
* GET /classroom/all
|
||||
* 返回:List<JSB>(无分页)
|
||||
*/
|
||||
export function listAllClassroom() {
|
||||
return request({
|
||||
url: '/classroom/all',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据教学楼代号查询教室
|
||||
* GET /classroom/listByJxldh
|
||||
* @param jxldh 教学楼代号(必填)
|
||||
*/
|
||||
export function listClassroomByJxldh(jxldh) {
|
||||
return request({
|
||||
url: '/classroom/listByJxldh',
|
||||
method: 'get',
|
||||
params: { jxldh }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 课程教学运行管理(CourseRunningController /course-running)
|
||||
// 接口依据:course-running 控制器(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 分页查询教学实施计划课次列表
|
||||
* GET /course-running/plan/list
|
||||
* 查询参数(TeachingPlanQueryDTO):
|
||||
* sskcbh 实施_课程编号、nd 年度、jxff 教学方法、
|
||||
* rqStart 日期范围开始、rqEnd 日期范围结束(均传 ISO 格式,如 2026-08-23T00:00:00)、
|
||||
* txzt 填写状态(0-未填写 1-已填写 2-已提交)、pageNum、pageSize
|
||||
* 返回:PageResult<TeachingPlanLessonVO>(records/total)
|
||||
*/
|
||||
export function listTeachingPlan(params) {
|
||||
return request({
|
||||
url: '/course-running/plan/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 调课申请管理 /course-running/adjust ====================
|
||||
// 接口依据:CourseRunningController(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 分页查询调课申请列表
|
||||
* GET /adjust/list
|
||||
* 查询参数(ScheduleAdjustQueryDTO):sskcbbh 课次编号、sqjybh 申请教员编号、nd 年度、
|
||||
* jyspzzt 教研室审批状态、jyscszt 教研室查收状态、jgspzt 机关审批状态、sczt 删除状态、
|
||||
* cjsjStart/cjsjEnd 申请日期范围(ISO 格式)、pageNum、pageSize
|
||||
* 返回:PageResult<ScheduleAdjustApplyVO>(records/total)
|
||||
*/
|
||||
export function listScheduleAdjust(params) {
|
||||
return request({
|
||||
url: '/course-running/adjust/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询可供调课课次
|
||||
* GET /adjust/lessons
|
||||
* 查询参数:nd 学期年度
|
||||
* 返回:List<AdjustableLessonVO>
|
||||
* 注意:后端当前未实现该接口,调用会报错(页面已做兜底提示)
|
||||
*/
|
||||
export function listAdjustableLessons(params) {
|
||||
return request({
|
||||
url: '/course-running/adjust/lessons',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询调课申请详情
|
||||
* GET /adjust/detail
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* 返回:ScheduleAdjustDetailVO
|
||||
*/
|
||||
export function getScheduleAdjustDetail(ssdksqbh) {
|
||||
return request({
|
||||
url: '/course-running/adjust/detail',
|
||||
method: 'get',
|
||||
params: { ssdksqbh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交调课申请
|
||||
* POST /adjust/submit
|
||||
* 请求体(ScheduleAdjustApplyDTO):sskcbbh 课次编号、sy 调课事由、rq 新日期、jc 新节次、
|
||||
* nd 年度、sqjybh 申请教员编号、jxnr 教学内容、jxyd 教学要点、jxff 教学方法、
|
||||
* jxbzbz 教学保障备注、ycxx 用车信息、bz 备注、roomList/teacherList/teamList/supportList
|
||||
*/
|
||||
export function submitScheduleAdjust(data) {
|
||||
return request({
|
||||
url: '/course-running/adjust/submit',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 教研室审批调课申请
|
||||
* POST /adjust/audit/jys
|
||||
* 请求体(ScheduleAdjustAuditDTO):ssdksqbh、auditRole=jys、spzt(1同意/2发回/3拒绝)、fhyj、sprbh
|
||||
*/
|
||||
export function auditByTeachingOffice(data) {
|
||||
return request({
|
||||
url: '/course-running/adjust/audit/jys',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 教研室查收调课申请
|
||||
* POST /adjust/receive/jys
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @param csrbh 查收人编号
|
||||
*/
|
||||
export function receiveByTeachingOffice(params) {
|
||||
return request({
|
||||
url: '/course-running/adjust/receive/jys',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 教学系审批调课申请
|
||||
* POST /adjust/audit/jxx
|
||||
* 请求体(ScheduleAdjustAuditDTO):ssdksqbh、auditRole=jxx、spzt、fhyj、sprbh
|
||||
*/
|
||||
export function auditByTeachingDepartment(data) {
|
||||
return request({
|
||||
url: '/course-running/adjust/audit/jxx',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 机关审批调课申请
|
||||
* POST /adjust/audit/jg
|
||||
* 请求体(ScheduleAdjustAuditDTO):ssdksqbh、auditRole=jg、spzt、fhyj、sprbh、jgbh(机关编号必填)
|
||||
*/
|
||||
export function auditByAuthority(data) {
|
||||
return request({
|
||||
url: '/course-running/adjust/audit/jg',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 机关查收调课申请
|
||||
* POST /adjust/receive/jg
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @param jgbh 机关编号
|
||||
* @param csrbh 查收人编号
|
||||
*/
|
||||
export function receiveByAuthority(params) {
|
||||
return request({
|
||||
url: '/course-running/adjust/receive/jg',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销调课申请
|
||||
* DELETE /adjust/cancel
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @param sqjybh 申请教员编号(权限校验)
|
||||
*/
|
||||
export function cancelScheduleAdjust(params) {
|
||||
return request({
|
||||
url: '/course-running/adjust/cancel',
|
||||
method: 'delete',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -9,6 +9,14 @@ export function listSemester(query) {
|
||||
})
|
||||
}
|
||||
|
||||
// 查询所有学期列表(年度下拉数据源,返回全部学期含 nd/dqxq,按年度倒序)
|
||||
export function listAllSemester() {
|
||||
return request({
|
||||
url: '/semester/all',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据主键查询学期
|
||||
export function getSemester(nd) {
|
||||
return request({
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 学员队任务表(StudentTeamTaskController /studentTeamTask)
|
||||
// 接口依据:studentTeamTask 控制器(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 分页查询学员队任务表(按班次/年度)
|
||||
* GET /studentTeamTask/list
|
||||
* 查询参数(XYDRWB 实体字段):xydbh 学员队编号、nd 年度、kcxh 课次序号、jhkcxh 计划课次序号、xs 学时等
|
||||
* 返回:Page<XYDRWB>(records/total)
|
||||
*/
|
||||
export function listStudentTeamTask(params) {
|
||||
return request({
|
||||
url: '/studentTeamTask/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 专业教学计划(教学大纲 ZYJXJHB)
|
||||
// 接口依据:/zyjxjhb/*(前端 baseURL 为 '/api',此处不再加前缀)
|
||||
|
||||
// 新增(bh 留空后端自动生成 UUID,ty 默认 0,qysj 默认当前时间)
|
||||
export function addSyllabus(data) {
|
||||
return request({
|
||||
url: '/zyjxjhb/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除(软删:置 ty=1 并写 tysj)
|
||||
export function deleteSyllabus(bh) {
|
||||
return request({
|
||||
url: '/zyjxjhb/delete',
|
||||
method: 'post',
|
||||
params: { bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量删除(软删)
|
||||
export function batchDeleteSyllabus(bhList) {
|
||||
return request({
|
||||
url: '/zyjxjhb/batchDelete',
|
||||
method: 'post',
|
||||
data: bhList
|
||||
})
|
||||
}
|
||||
|
||||
// 更新(bh 必传)
|
||||
export function updateSyllabus(data) {
|
||||
return request({
|
||||
url: '/zyjxjhb/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 根据编号查询
|
||||
export function getSyllabus(bh) {
|
||||
return request({
|
||||
url: '/zyjxjhb/get',
|
||||
method: 'get',
|
||||
params: { bh }
|
||||
})
|
||||
}
|
||||
|
||||
// 查询所有(返回 List,无分页,前端本地分页)
|
||||
export function listSyllabus() {
|
||||
return request({
|
||||
url: '/zyjxjhb/list',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据专业代号和停用标识查询(zydh、ty 均必填,等值匹配)
|
||||
export function listSyllabusByZydhAndTy(zydh, ty) {
|
||||
return request({
|
||||
url: '/zyjxjhb/listByZydhAndTy',
|
||||
method: 'get',
|
||||
params: { zydh, ty }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 教学任务管理(TeachingTaskController /teachingTask)
|
||||
// 接口依据:api.txt「教学任务管理」分组(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
// 实体:JXRW(bh 编号、rwmc 任务名称、nd 年度、zt 状态、
|
||||
// fbsj 发布时间、cjsj 创建时间、jssj 结束时间、jcxqscsj 教材需求生成时间)
|
||||
// 新增时 bh 留空由后端生成(api.txt 新增示例未传 bh),编辑/更新时 bh 必传
|
||||
|
||||
/**
|
||||
* 分页查询教学任务列表
|
||||
* GET /teachingTask/list
|
||||
* 查询参数(JXRW):rwmc 任务名称(模糊)、nd 年度(等值)、zt 状态(等值)、
|
||||
* pageNum、pageSize
|
||||
* 返回:PageResult<JXRW>(records/total)
|
||||
*/
|
||||
export function listTeachingTask(params) {
|
||||
return request({
|
||||
url: '/teachingTask/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据编号查询教学任务
|
||||
* GET /teachingTask/get?bh=
|
||||
* @param bh 编号
|
||||
* 返回:JXRW
|
||||
*/
|
||||
export function getTeachingTask(bh) {
|
||||
return request({
|
||||
url: '/teachingTask/get',
|
||||
method: 'get',
|
||||
params: { bh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增教学任务
|
||||
* POST /teachingTask/add
|
||||
* 请求体(JXRW):rwmc 任务名称(必填)、nd 年度(必填)、zt 状态、fbsj/jssj/jcxqscsj
|
||||
* 说明:bh 不传由后端自动生成;cjsj 创建时间由后端自动维护
|
||||
*/
|
||||
export function addTeachingTask(data) {
|
||||
return request({
|
||||
url: '/teachingTask/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新教学任务(根据主键)
|
||||
* POST /teachingTask/update
|
||||
* 请求体(JXRW):bh 编号(必填)、rwmc、nd、zt
|
||||
*/
|
||||
export function updateTeachingTask(data) {
|
||||
return request({
|
||||
url: '/teachingTask/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 级联删除教学任务和教研室任务书
|
||||
* POST /teachingTask/delete?bh=
|
||||
* @param bh 编号
|
||||
*/
|
||||
export function deleteTeachingTask(bh) {
|
||||
return request({
|
||||
url: '/teachingTask/delete',
|
||||
method: 'post',
|
||||
params: { bh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 教学任务发布(需要先填写教研室任务书)
|
||||
* POST /teachingTask/batchPublish?bh=
|
||||
* @param bh 教学任务编号
|
||||
* 返回:更新数量
|
||||
*/
|
||||
export function publishTeachingTask(bh) {
|
||||
return request({
|
||||
url: '/teachingTask/batchPublish',
|
||||
method: 'post',
|
||||
params: { bh }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 课表(课程表 KCB)管理(KCBController /kcb)
|
||||
// 接口依据:KCBController + KCBServiceImpl
|
||||
// 说明:KCB 实体主键为 bh(编号,IdType.INPUT);新增时后端强制 setBh(UUID) 覆盖、cjsj/bdsj 自动生成;
|
||||
// delete/get/update 中的 URL 参数 kbh 实为 bh(编号)值;list 无分页返回全部记录
|
||||
|
||||
/**
|
||||
* 新增课程表
|
||||
* POST /kcb/add
|
||||
* body 为 KCB 实体;bh 可留空(后端自动生成 UUID),cjsj/bdsj 后端自动维护
|
||||
*/
|
||||
export function addKcb(data) {
|
||||
return request({
|
||||
url: '/kcb/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除课程表
|
||||
* POST /kcb/delete?kbh= (kbh 实为 bh 编号值)
|
||||
*/
|
||||
export function deleteKcb(kbh) {
|
||||
return request({
|
||||
url: '/kcb/delete',
|
||||
method: 'post',
|
||||
params: { kbh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除课程表
|
||||
* POST /kcb/batchDelete
|
||||
* body 为 bh(编号)字符串数组
|
||||
*/
|
||||
export function batchDeleteKcb(kbhList) {
|
||||
return request({
|
||||
url: '/kcb/batchDelete',
|
||||
method: 'post',
|
||||
data: kbhList
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新课程表
|
||||
* POST /kcb/update
|
||||
* body 为 KCB 实体,bh 编号必传
|
||||
*/
|
||||
export function updateKcb(data) {
|
||||
return request({
|
||||
url: '/kcb/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据编号查询课程表详情
|
||||
* GET /kcb/get?kbh= (kbh 实为 bh 编号值)
|
||||
*/
|
||||
export function getKcb(kbh) {
|
||||
return request({
|
||||
url: '/kcb/get',
|
||||
method: 'get',
|
||||
params: { kbh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有课程表数据
|
||||
* GET /kcb/list
|
||||
* 返回 List<KCB>,无分页,页面做本地过滤与本地分页
|
||||
*/
|
||||
export function listKcb() {
|
||||
return request({
|
||||
url: '/kcb/list',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 课表冲突检查:单维度检查(POST /timetable-conflict/check)
|
||||
// body: { nd 年度(必填), dimensionCode 维度编码(必填), writeToDb?(落库), jcpch?(批次号) }
|
||||
// 返回 TimetableConflictCardVO { dimensionCode, title, description, checked, conflictCount }
|
||||
export function checkConflict(data) {
|
||||
return request({
|
||||
url: '/timetable-conflict/check',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 课表冲突检查:执行全部维度检查(POST /timetable-conflict/check-all)
|
||||
// body: { nd 年度(必填), writeToDb? }
|
||||
// 返回 TimetableConflictSummaryVO { nd, cards[], totalConflictCount, fullyChecked }
|
||||
export function checkAllConflict(data) {
|
||||
return request({
|
||||
url: '/timetable-conflict/check-all',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 课表冲突检查:重置检查结果(POST /timetable-conflict/reset)
|
||||
// body: { nd 年度(必填), clearDb? 是否同时清空落库表 }
|
||||
// 返回 TimetableConflictSummaryVO(所有卡片未检查状态)
|
||||
export function resetConflict(data) {
|
||||
return request({
|
||||
url: '/timetable-conflict/reset',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 课表冲突检查:分页查询冲突明细(GET /timetable-conflict/details)
|
||||
// params: { nd 年度(必填), dimensionCode? 维度编码, pageNum?, pageSize?, useDb?, jcpch? }
|
||||
// 返回 PageResult<TimetableConflictDetailVO>
|
||||
export function getConflictDetails(params) {
|
||||
return request({
|
||||
url: '/timetable-conflict/details',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 人才培养方案(专业表 ZYB /training)
|
||||
// 接口依据:TrainingProgramController(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 新增培养方案(专业)
|
||||
* POST /training/add
|
||||
* 请求体(ZYB):zydh/zymc/zydm/pxcc/pxlx 必填;
|
||||
* 主键 zydh 需手动传入(留空时后端自动生成 UUID,后端同时置 ty=false、qysj=当前时间)
|
||||
*/
|
||||
export function addTraining(data) {
|
||||
return request({
|
||||
url: '/training/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 停用(逻辑删除)培养方案
|
||||
* POST /training/disable?zydh=
|
||||
* @param zydh 专业代号(必填)
|
||||
*/
|
||||
export function disableTraining(zydh) {
|
||||
return request({
|
||||
url: '/training/disable',
|
||||
method: 'post',
|
||||
params: { zydh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新培养方案
|
||||
* POST /training/update
|
||||
* 请求体(ZYB):zydh 必传
|
||||
*/
|
||||
export function updateTraining(data) {
|
||||
return request({
|
||||
url: '/training/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据专业代号查询培养方案详情
|
||||
* GET /training/get?zydh=
|
||||
* @param zydh 专业代号
|
||||
*/
|
||||
export function getTraining(zydh) {
|
||||
return request({
|
||||
url: '/training/get',
|
||||
method: 'get',
|
||||
params: { zydh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页条件查询培养方案列表
|
||||
* GET /training/list
|
||||
* 查询参数:zymc(模糊)、zydm(模糊)、pxlx(精确)、pxcc(精确)、pageNum、pageSize
|
||||
* 返回:PageResult<ZYB>(records/total)
|
||||
*/
|
||||
export function listTraining(params) {
|
||||
return request({
|
||||
url: '/training/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 课程科目(课标 KB)管理(JYSController /jys/kb)
|
||||
// 接口依据:JYSController 控制器(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
// 实体 KB 主键为 kbh(课编号);新增时 kbh 留空由后端生成 UUID;xhbs 字段无需传递(后端 NEVER)
|
||||
|
||||
/**
|
||||
* 新增课程科目
|
||||
* POST /jys/kb/add
|
||||
* body 为 KB 实体;kbh 可留空(后端生成 UUID)
|
||||
*/
|
||||
export function addSubject(data) {
|
||||
return request({
|
||||
url: '/jys/kb/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除课程科目
|
||||
* POST /jys/kb/delete?kbh=
|
||||
*/
|
||||
export function deleteSubject(kbh) {
|
||||
return request({
|
||||
url: '/jys/kb/delete',
|
||||
method: 'post',
|
||||
params: { kbh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑课程科目
|
||||
* POST /jys/kb/update
|
||||
* body 为 KB 实体,kbh 课编号必传
|
||||
*/
|
||||
export function updateSubject(data) {
|
||||
return request({
|
||||
url: '/jys/kb/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询课程科目详情
|
||||
* GET /jys/kb/get?kbh=
|
||||
*/
|
||||
export function getSubject(kbh) {
|
||||
return request({
|
||||
url: '/jys/kb/get',
|
||||
method: 'get',
|
||||
params: { kbh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询课程科目(课标 KB)
|
||||
* GET /jys/kb/list
|
||||
* 查询参数:pageNum、pageSize、kmc 课名称(模糊)、jc 简称(模糊)、kmdm 科目代码(模糊)、
|
||||
* jysdh 教研室代号(等值)、kclx 课程类型、pxlx 培训类型、pxcc 培训层次
|
||||
* 返回:PageResult<KB>(records/total)
|
||||
*/
|
||||
export function listSubject(params) {
|
||||
return request({
|
||||
url: '/jys/kb/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 教员管理:教员(JYB)+ 教员属性(JYSX)
|
||||
// 接口依据:/jys/teacher/*(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 分页查询教员列表
|
||||
* GET /jys/teacher/list
|
||||
* 查询参数(JYBMapper.xml 支持):jyxm 模糊、jysdh 等值、zc 模糊、jylb 等值
|
||||
*/
|
||||
export function listTeacher(params) {
|
||||
return request({
|
||||
url: '/jys/teacher/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 根据教员编号查询教员详情 GET /jys/teacher/get?jybh= */
|
||||
export function getTeacher(jybh) {
|
||||
return request({
|
||||
url: '/jys/teacher/get',
|
||||
method: 'get',
|
||||
params: { jybh }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增教员 POST /jys/teacher/add
|
||||
* body 为 AddTeacherDTO:{ teacher: JYB, attributes: JYSX }
|
||||
* lzzt 前端不传,后端自动置 0
|
||||
*/
|
||||
export function addTeacher(data) {
|
||||
return request({
|
||||
url: '/jys/teacher/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 更新教员基本信息 POST /jys/teacher/update(body 为 JYB,jybh 必传) */
|
||||
export function updateTeacher(data) {
|
||||
return request({
|
||||
url: '/jys/teacher/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 教员离职(逻辑删除)POST /jys/teacher/disable?jybh= */
|
||||
export function disableTeacher(jybh) {
|
||||
return request({
|
||||
url: '/jys/teacher/disable',
|
||||
method: 'post',
|
||||
params: { jybh }
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询教员属性 GET /jys/teacher/attribute/get?jybh= */
|
||||
export function getTeacherAttribute(jybh) {
|
||||
return request({
|
||||
url: '/jys/teacher/attribute/get',
|
||||
method: 'get',
|
||||
params: { jybh }
|
||||
})
|
||||
}
|
||||
|
||||
/** 更新教员属性 POST /jys/teacher/attribute/update(body 为 JYSX,jybh 必传) */
|
||||
export function updateTeacherAttribute(data) {
|
||||
return request({
|
||||
url: '/jys/teacher/attribute/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 教材管理:教材信息(JCXX 实体)
|
||||
// 接口依据 api.txt:/teachingMaterial/*(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
/**
|
||||
* 教材信息分页查询
|
||||
* GET /teachingMaterial/list
|
||||
* 查询参数(TeachingMaterialMapper.xml 支持):bh/mc/isbn/cbs/zz 模糊,jcfl/jclx 等值,ty 等值
|
||||
*/
|
||||
export function listTeachingMaterial(params) {
|
||||
return request({
|
||||
url: '/teachingMaterial/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 根据编号查询 GET /teachingMaterial/getByBh?bh= */
|
||||
export function getTeachingMaterialByBh(bh) {
|
||||
return request({
|
||||
url: '/teachingMaterial/getByBh',
|
||||
method: 'get',
|
||||
params: { bh }
|
||||
})
|
||||
}
|
||||
|
||||
/** 根据ID查询 GET /teachingMaterial/getById?id= */
|
||||
export function getTeachingMaterialById(id) {
|
||||
return request({
|
||||
url: '/teachingMaterial/getById',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/** 新增教材信息 POST /teachingMaterial/add */
|
||||
export function addTeachingMaterial(data) {
|
||||
return request({
|
||||
url: '/teachingMaterial/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 根据ID修改 POST /teachingMaterial/update(body 需携带 id) */
|
||||
export function updateTeachingMaterial(data) {
|
||||
return request({
|
||||
url: '/teachingMaterial/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除 POST /teachingMaterial/delete?id= */
|
||||
export function deleteTeachingMaterial(id) {
|
||||
return request({
|
||||
url: '/teachingMaterial/delete',
|
||||
method: 'post',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/** 教材导入模板下载 GET /teachingMaterial/template */
|
||||
export function downloadTeachingMaterialTemplate() {
|
||||
return request({
|
||||
url: '/teachingMaterial/template',
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
/** 教材导入 POST /teachingMaterial/import(form-data,字段名 file) */
|
||||
export function importTeachingMaterial(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request({
|
||||
url: '/teachingMaterial/import',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 教材库存:库存单(JCKCD)+ 库存明细项(JCKCMXX)
|
||||
// 接口依据 api.txt:/teachingStock/*(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||
|
||||
// ==================== 教材库存单(JCKCD) ====================
|
||||
|
||||
/**
|
||||
* 分页查询库存单
|
||||
* GET /teachingStock/list
|
||||
* 查询参数(TeachingStockMapper.xml 支持):bh/mc 模糊,lb/zb/zt 等值
|
||||
*/
|
||||
export function listTeachingStock(params) {
|
||||
return request({
|
||||
url: '/teachingStock/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 根据ID查询库存单 GET /teachingStock/get?id= */
|
||||
export function getTeachingStock(id) {
|
||||
return request({
|
||||
url: '/teachingStock/get',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/** 新增库存单 POST /teachingStock/add(bh 留空由后端自动生成) */
|
||||
export function addTeachingStock(data) {
|
||||
return request({
|
||||
url: '/teachingStock/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 修改库存单 POST /teachingStock/update(body 需携带 id) */
|
||||
export function updateTeachingStock(data) {
|
||||
return request({
|
||||
url: '/teachingStock/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除库存单 POST /teachingStock/delete?id= */
|
||||
export function deleteTeachingStock(id) {
|
||||
return request({
|
||||
url: '/teachingStock/delete',
|
||||
method: 'post',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 教材库存明细项(JCKCMXX) ====================
|
||||
|
||||
/**
|
||||
* 分页查询库存明细项
|
||||
* GET /teachingStock/detail/list
|
||||
* 查询参数(TeachingStockDetailMapper.xml 支持):bh 模糊,jckcdbbh 等值,jcxxbh 模糊,hwbw 等值
|
||||
*/
|
||||
export function listTeachingStockDetail(params) {
|
||||
return request({
|
||||
url: '/teachingStock/detail/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 根据ID查询库存明细项 GET /teachingStock/detail/get?id= */
|
||||
export function getTeachingStockDetail(id) {
|
||||
return request({
|
||||
url: '/teachingStock/detail/get',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/** 新增库存明细项 POST /teachingStock/detail/add(bh 留空由后端自动生成) */
|
||||
export function addTeachingStockDetail(data) {
|
||||
return request({
|
||||
url: '/teachingStock/detail/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 修改库存明细项 POST /teachingStock/detail/update(body 需携带 id) */
|
||||
export function updateTeachingStockDetail(data) {
|
||||
return request({
|
||||
url: '/teachingStock/detail/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除库存明细项 POST /teachingStock/detail/delete?id= */
|
||||
export function deleteTeachingStockDetail(id) {
|
||||
return request({
|
||||
url: '/teachingStock/detail/delete',
|
||||
method: 'post',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@import './variables.scss';
|
||||
@import './variables.scss';
|
||||
@import './mixin.scss';
|
||||
@import './transition.scss';
|
||||
@import './element-ui.scss';
|
||||
@@ -41,6 +41,60 @@ html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* ================= 全局自适应加固 =================
|
||||
与 src/utils/adaptive.js 的视口等比缩放配合,
|
||||
兜底避免极端情况下出现页面级横向溢出与内容崩塌。 */
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
/* 禁止页面级横向滚动,防止因个别固定宽度元素把整页撑破;
|
||||
表格自身的横向滚动由 el-table 内部滚动容器承担,不受影响 */
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* 弹性布局子项允许收缩,避免 flex 容器被子项固有宽度撑破 */
|
||||
#app,
|
||||
.app-wrapper,
|
||||
.main-container,
|
||||
.lower-container {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ===== Element 浮层逆缩放(配合 adaptive.js) =====
|
||||
挂到 body 的浮层(下拉/气泡/日期/对话框/消息等)基于 getBoundingClientRect 定位,
|
||||
该值受 html 的 zoom 缩放影响;若浮层自身也继承同一 zoom,坐标会被“重复缩放”而错位。
|
||||
这里用 adaptive.js 注入的 --adaptive-scale-inv(= 1/当前缩放倍数)把这些浮层还原为 1:1,
|
||||
使其与触发元素在视觉坐标上正确对齐。缩放=1 时该变量为 1,不产生任何影响。 */
|
||||
:root {
|
||||
--adaptive-scale: 1;
|
||||
}
|
||||
|
||||
.el-popper,
|
||||
.el-select-dropdown,
|
||||
.el-dropdown-menu,
|
||||
.el-picker-panel,
|
||||
.el-cascader__dropdown,
|
||||
.el-message-box__wrapper,
|
||||
.el-dialog__wrapper,
|
||||
.el-message,
|
||||
.el-notification,
|
||||
.el-loading-mask,
|
||||
.v-modal {
|
||||
zoom: var(--adaptive-scale-inv, 1);
|
||||
}
|
||||
|
||||
/* 通用长文本换行,避免 url/数字/英文长串将布局撑破 */
|
||||
a,
|
||||
.el-button,
|
||||
.el-table .cell,
|
||||
.el-form-item__content,
|
||||
.el-form-item__label {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* 通用css样式布局处理
|
||||
* Copyright (c) 2019 roomroot
|
||||
*/
|
||||
@@ -93,6 +93,11 @@
|
||||
}
|
||||
|
||||
.el-table {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
@@ -108,6 +113,20 @@
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
// 表格横向拖拽滚动:拖拽过程中保持默认光标,不显示“抓手”,避免干扰操作手感
|
||||
.el-table__body-wrapper.is-dragging,
|
||||
.el-table__fixed-body-wrapper.is-dragging {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
/* 原生表格同样禁止选中文本,避免横向滑动/滚动时误触发复制前的文本选中 */
|
||||
table {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/** 表单布局 **/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* 通用css样式布局处理
|
||||
* Copyright (c) 2019 roomroot
|
||||
*/
|
||||
@@ -93,13 +93,16 @@
|
||||
}
|
||||
|
||||
.el-table {
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9;
|
||||
color: #515a6e;
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9;
|
||||
color: #515a6e;
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
|
||||
.cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,9 +92,6 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
theme() {
|
||||
return this.$store.state.settings.theme
|
||||
},
|
||||
routes() {
|
||||
return this.$store.getters.defaultRoutes
|
||||
}
|
||||
@@ -213,7 +210,7 @@ export default {
|
||||
activeStyle(index) {
|
||||
if (index !== this.activeIndex) return {}
|
||||
return {
|
||||
'background-color': this.theme,
|
||||
'background-color': '#00875A',
|
||||
'color': '#fff'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
<template>
|
||||
<el-color-picker
|
||||
v-model="theme"
|
||||
:predefine="['#00875A', '#006B47', '#007F4F', '#11a983', '#13c2c2', '#6959CD', '#f5222d', '#212121', ]"
|
||||
class="theme-picker"
|
||||
popper-class="theme-picker-dropdown"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const ORIGINAL_THEME = '#00875A' // default color
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
chalk: '', // content of theme-chalk css
|
||||
theme: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
defaultTheme() {
|
||||
return this.$store.state.settings.theme
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultTheme: {
|
||||
handler: function(val, oldVal) {
|
||||
this.theme = val
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
async theme(val) {
|
||||
await this.setTheme(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.defaultTheme !== ORIGINAL_THEME) {
|
||||
this.setTheme(this.defaultTheme)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async setTheme(val) {
|
||||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
|
||||
if (typeof val !== 'string') return
|
||||
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
||||
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
||||
|
||||
const getHandler = (variable, id) => {
|
||||
return () => {
|
||||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
|
||||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
|
||||
|
||||
let styleTag = document.getElementById(id)
|
||||
if (!styleTag) {
|
||||
styleTag = document.createElement('style')
|
||||
styleTag.setAttribute('id', id)
|
||||
document.head.appendChild(styleTag)
|
||||
}
|
||||
styleTag.innerText = newStyle
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.chalk) {
|
||||
const url = `/styles/theme-chalk/index.css`
|
||||
await this.getCSSString(url, 'chalk')
|
||||
}
|
||||
|
||||
const chalkHandler = getHandler('chalk', 'chalk-style')
|
||||
chalkHandler()
|
||||
|
||||
const styles = [].slice.call(document.querySelectorAll('style'))
|
||||
.filter(style => {
|
||||
const text = style.innerText
|
||||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
|
||||
})
|
||||
styles.forEach(style => {
|
||||
const { innerText } = style
|
||||
if (typeof innerText !== 'string') return
|
||||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
||||
})
|
||||
|
||||
this.$emit('change', val)
|
||||
},
|
||||
|
||||
updateStyle(style, oldCluster, newCluster) {
|
||||
let newStyle = style
|
||||
oldCluster.forEach((color, index) => {
|
||||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
|
||||
})
|
||||
return newStyle
|
||||
},
|
||||
|
||||
getCSSString(url, variable) {
|
||||
return new Promise(resolve => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
xhr.open('GET', url)
|
||||
xhr.send()
|
||||
})
|
||||
},
|
||||
|
||||
getThemeCluster(theme) {
|
||||
const tintColor = (color, tint) => {
|
||||
let red = parseInt(color.slice(0, 2), 16)
|
||||
let green = parseInt(color.slice(2, 4), 16)
|
||||
let blue = parseInt(color.slice(4, 6), 16)
|
||||
|
||||
if (tint === 0) { // when primary color is in its rgb space
|
||||
return [red, green, blue].join(',')
|
||||
} else {
|
||||
red += Math.round(tint * (255 - red))
|
||||
green += Math.round(tint * (255 - green))
|
||||
blue += Math.round(tint * (255 - blue))
|
||||
|
||||
red = red.toString(16)
|
||||
green = green.toString(16)
|
||||
blue = blue.toString(16)
|
||||
|
||||
return `#${red}${green}${blue}`
|
||||
}
|
||||
}
|
||||
|
||||
const shadeColor = (color, shade) => {
|
||||
let red = parseInt(color.slice(0, 2), 16)
|
||||
let green = parseInt(color.slice(2, 4), 16)
|
||||
let blue = parseInt(color.slice(4, 6), 16)
|
||||
|
||||
red = Math.round((1 - shade) * red)
|
||||
green = Math.round((1 - shade) * green)
|
||||
blue = Math.round((1 - shade) * blue)
|
||||
|
||||
red = red.toString(16)
|
||||
green = green.toString(16)
|
||||
blue = blue.toString(16)
|
||||
|
||||
return `#${red}${green}${blue}`
|
||||
}
|
||||
|
||||
const clusters = [theme]
|
||||
for (let i = 0; i <= 9; i++) {
|
||||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
|
||||
}
|
||||
clusters.push(shadeColor(theme, 0.1))
|
||||
return clusters
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.theme-message,
|
||||
.theme-picker-dropdown {
|
||||
z-index: 99999 !important;
|
||||
}
|
||||
|
||||
.theme-picker .el-color-picker__trigger {
|
||||
height: 26px !important;
|
||||
width: 26px !important;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.theme-picker-dropdown .el-color-dropdown__link-btn {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,10 @@
|
||||
import hasRole from './permission/hasRole'
|
||||
import hasRole from './permission/hasRole'
|
||||
import hasPermi from './permission/hasPermi'
|
||||
import dialogDrag from './dialog/drag'
|
||||
import dialogDragWidth from './dialog/dragWidth'
|
||||
import dialogDragHeight from './dialog/dragHeight'
|
||||
import clipboard from './module/clipboard'
|
||||
import tableDrag from './tableDrag'
|
||||
|
||||
const install = function(Vue) {
|
||||
Vue.directive('hasRole', hasRole)
|
||||
@@ -12,6 +13,8 @@ const install = function(Vue) {
|
||||
Vue.directive('dialogDrag', dialogDrag)
|
||||
Vue.directive('dialogDragWidth', dialogDragWidth)
|
||||
Vue.directive('dialogDragHeight', dialogDragHeight)
|
||||
// 全局表格横向拖拽滚动:通过 document 事件委托自动作用于所有 el-table
|
||||
tableDrag()
|
||||
}
|
||||
|
||||
if (window.Vue) {
|
||||
|
||||
@@ -6,17 +6,15 @@
|
||||
</keep-alive>
|
||||
</transition>
|
||||
<iframe-toggle />
|
||||
<copyright />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import copyright from "./Copyright/index"
|
||||
import iframeToggle from "./IframeToggle/index"
|
||||
|
||||
export default {
|
||||
name: 'AppMain',
|
||||
components: { iframeToggle, copyright },
|
||||
components: { iframeToggle },
|
||||
computed: {
|
||||
cachedViews() {
|
||||
return this.$store.state.tagsView.cachedViews
|
||||
@@ -64,10 +62,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.app-main:has(.copyright) {
|
||||
padding-bottom: 36px;
|
||||
}
|
||||
|
||||
.hasTagsView {
|
||||
.app-main {
|
||||
/* tags-view 高度 34px,AppMain 在 flex 列中由父容器约束高度 */
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<template>
|
||||
<footer v-if="visible" class="copyright">
|
||||
<span>{{ content }}</span>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
visible() {
|
||||
return this.$store.state.settings.footerVisible
|
||||
},
|
||||
content() {
|
||||
return this.$store.state.settings.footerContent
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.copyright {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 36px;
|
||||
padding: 10px 20px;
|
||||
text-align: right;
|
||||
background-color: #f8f8f8;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
border-top: 1px solid #e7e7e7;
|
||||
z-index: 999;
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="navbar" :class="['nav' + navType, { 'header-mode': headerMode }]">
|
||||
<div class="navbar" :class="[{ 'header-mode': headerMode }]">
|
||||
<hamburger v-if="!headerMode" id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||
|
||||
<breadcrumb v-if="!headerMode && navType == 1" id="breadcrumb-container" class="breadcrumb-container" />
|
||||
<top-nav v-if="!headerMode && navType == 2" id="topmenu-container" class="topmenu-container" />
|
||||
<breadcrumb v-if="!headerMode" id="breadcrumb-container" class="breadcrumb-container" />
|
||||
<div class="right-menu">
|
||||
<template v-if="device!=='mobile'">
|
||||
<el-tooltip content="菜单搜索" effect="dark" placement="bottom">
|
||||
@@ -34,9 +33,6 @@
|
||||
<router-link to="/user/profile">
|
||||
<el-dropdown-item icon="el-icon-user">个人中心</el-dropdown-item>
|
||||
</router-link>
|
||||
<el-dropdown-item v-if="setting" icon="el-icon-s-tools" @click.native="setLayout">
|
||||
<span>布局设置</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-lock" @click.native="lockScreen">
|
||||
<span>锁定屏幕</span>
|
||||
</el-dropdown-item>
|
||||
@@ -52,7 +48,6 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import TopNav from './TopNav'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
import Screenfull from '@/components/Screenfull'
|
||||
import Search from '@/components/HeaderSearch'
|
||||
@@ -61,7 +56,6 @@ import HeaderNotice from './HeaderNotice'
|
||||
export default {
|
||||
components: {
|
||||
Breadcrumb,
|
||||
TopNav,
|
||||
Hamburger,
|
||||
Screenfull,
|
||||
Search,
|
||||
@@ -85,16 +79,6 @@ export default {
|
||||
'nickName',
|
||||
'roles'
|
||||
]),
|
||||
setting: {
|
||||
get() {
|
||||
return this.$store.state.settings.showSettings
|
||||
}
|
||||
},
|
||||
navType: {
|
||||
get() {
|
||||
return this.$store.state.settings.navType
|
||||
}
|
||||
},
|
||||
// 用户角色标签:根据 roles 数组智能映射为友好文本
|
||||
userRoleLabel() {
|
||||
const roleMap = {
|
||||
@@ -112,9 +96,6 @@ export default {
|
||||
toggleSideBar() {
|
||||
this.$store.dispatch('app/toggleSideBar')
|
||||
},
|
||||
setLayout(event) {
|
||||
this.$emit('setLayout')
|
||||
},
|
||||
handleCommand(command) {
|
||||
// 预留:下拉菜单 command 事件入口
|
||||
},
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:visible.sync="visible"
|
||||
direction="rtl"
|
||||
size="280px"
|
||||
:title="'布局设置'"
|
||||
class="drawer-setting"
|
||||
:with-header="false"
|
||||
:modal-append-to-body="false"
|
||||
>
|
||||
<div class="setting-drawer-index">
|
||||
<div class="setting-drawer-index__title">主题色</div>
|
||||
<div class="setting-drawer-index__main-color theme-color">
|
||||
<ul class="ul-color">
|
||||
<li
|
||||
v-for="item in colorList"
|
||||
:key="item.color"
|
||||
class="li-theme"
|
||||
:class="{ active: item.color === theme }"
|
||||
:style="{ background: item.color }"
|
||||
@click="changeTheme(item.color)"
|
||||
>
|
||||
<i v-show="item.color === theme" class="icon-check el-icon-check" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="setting-drawer-index__title">界面功能</div>
|
||||
<div class="setting-item">
|
||||
<span class="setting-item__label">侧边栏颜色</span>
|
||||
<el-dropdown trigger="click" @command="handleSideTheme">
|
||||
<span class="setting-item__value">
|
||||
{{ sideThemeLabel }}
|
||||
<i class="el-icon-arrow-down" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="theme-dark">深色主题</el-dropdown-item>
|
||||
<el-dropdown-item command="theme-light">浅色主题</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<span class="setting-item__label">导航栏模式</span>
|
||||
<el-dropdown trigger="click" @command="handleNavType">
|
||||
<span class="setting-item__value">
|
||||
{{ navTypeLabel }}
|
||||
<i class="el-icon-arrow-down" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="1">侧边栏模式</el-dropdown-item>
|
||||
<el-dropdown-item command="2">顶部导航模式</el-dropdown-item>
|
||||
<el-dropdown-item command="3">侧栏+顶栏</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<span class="setting-item__label"> TagsView 标签栏</span>
|
||||
<el-switch
|
||||
:value="tagsView"
|
||||
@change="changeSetting({ key: 'tagsView', value: !tagsView })"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<span class="setting-item__label"> 侧边栏 Logo</span>
|
||||
<el-switch
|
||||
:value="sidebarLogo"
|
||||
@change="changeSetting({ key: 'sidebarLogo', value: !sidebarLogo })"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<span class="setting-item__label"> 固定 Header</span>
|
||||
<el-switch
|
||||
:value="fixedHeader"
|
||||
@change="changeSetting({ key: 'fixedHeader', value: !fixedHeader })"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Settings',
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
/**
|
||||
* 主题色列表
|
||||
*/
|
||||
colorList: [
|
||||
{ color: '#00875A', title: '教育绿' },
|
||||
{ color: '#304156', title: '深蓝' },
|
||||
{ color: '#409EFF', title: '亮蓝' },
|
||||
{ color: '#626AEF', title: '亮紫' },
|
||||
{ color: '#EB2F96', title: '粉红' },
|
||||
{ color: '#F8721F', title: '橙色' },
|
||||
{ color: '#CD201F', title: '红色' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
theme: state => state.settings.theme,
|
||||
sideTheme: state => state.settings.sideTheme,
|
||||
navType: state => state.settings.navType,
|
||||
tagsView: state => state.settings.tagsView,
|
||||
sidebarLogo: state => state.settings.sidebarLogo,
|
||||
fixedHeader: state => state.settings.fixedHeader
|
||||
}),
|
||||
sideThemeLabel() {
|
||||
return this.sideTheme === 'theme-dark' ? '深色主题' : '浅色主题'
|
||||
},
|
||||
navTypeLabel() {
|
||||
const map = { 1: '侧边栏模式', 2: '顶部导航模式', 3: '侧栏+顶栏' }
|
||||
return map[this.navType] || '侧边栏模式'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openSetting() {
|
||||
this.visible = true
|
||||
},
|
||||
closeSetting() {
|
||||
this.visible = false
|
||||
},
|
||||
// 修改主题色
|
||||
changeTheme(color) {
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'theme', value: color })
|
||||
},
|
||||
handleSideTheme(command) {
|
||||
this.changeSetting({ key: 'sideTheme', value: command })
|
||||
},
|
||||
handleNavType(command) {
|
||||
this.changeSetting({ key: 'navType', value: Number(command) })
|
||||
},
|
||||
// 修改布局设置,并持久化到本地存储
|
||||
changeSetting(data) {
|
||||
this.$store.dispatch('settings/changeSetting', data)
|
||||
const setting = JSON.parse(localStorage.getItem('layout-setting') || '{}')
|
||||
setting[data.key] = data.value
|
||||
localStorage.setItem('layout-setting', JSON.stringify(setting))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-drawer-index {
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__title {
|
||||
margin-top: 26px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&__main-color {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.theme-color {
|
||||
.ul-color {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.li-theme {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 6px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
&.active {
|
||||
box-shadow: 0 0 0 2px #fff, 0 0 0 4px currentColor;
|
||||
}
|
||||
|
||||
.icon-check {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
|
||||
&__value {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 0 12px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dcdfe6;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,430 +0,0 @@
|
||||
<template>
|
||||
<el-drawer size="280px" :visible="showSettings" :with-header="false" :append-to-body="true" :before-close="closeSetting" :lock-scroll="false">
|
||||
<div class="drawer-container">
|
||||
<div>
|
||||
<div class="setting-drawer-content">
|
||||
<div class="setting-drawer-title">
|
||||
<h3 class="drawer-title">菜单导航设置</h3>
|
||||
</div>
|
||||
<div class="nav-wrap">
|
||||
<el-tooltip content="左侧菜单" placement="bottom">
|
||||
<div class="item left" @click="handleNavType(1)" :style="{'--theme': theme}" :class="{ activeItem: navType == 1 }">
|
||||
<b></b><b></b>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="混合菜单" placement="bottom">
|
||||
<div class="item mix" @click="handleNavType(2)" :style="{'--theme': theme}" :class="{ activeItem: navType == 2 }">
|
||||
<b></b><b></b>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="顶部菜单" placement="bottom">
|
||||
<div class="item top" @click="handleNavType(3)" :style="{'--theme': theme}" :class="{ activeItem: navType == 3 }">
|
||||
<b></b><b></b>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="setting-drawer-title">
|
||||
<h3 class="drawer-title">主题风格设置</h3>
|
||||
</div>
|
||||
<div class="setting-drawer-block-checbox">
|
||||
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
|
||||
<img src="@/assets/images/dark.svg" alt="dark">
|
||||
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
|
||||
<i aria-label="图标: check" class="anticon anticon-check">
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class="">
|
||||
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
|
||||
<img src="@/assets/images/light.svg" alt="light">
|
||||
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
|
||||
<i aria-label="图标: check" class="anticon anticon-check">
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class="">
|
||||
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>主题颜色</span>
|
||||
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-divider/>
|
||||
|
||||
<h3 class="drawer-title">系统布局配置</h3>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>开启页签</span>
|
||||
<el-switch v-model="tagsView" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>持久化标签页</span>
|
||||
<el-switch v-model="tagsViewPersist" :disabled="!tagsView" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>显示页签图标</span>
|
||||
<el-switch v-model="tagsIcon" :disabled="!tagsView" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>标签页样式</span>
|
||||
<el-radio-group v-model="tagsViewStyle" :disabled="!tagsView" size="mini" class="drawer-switch">
|
||||
<el-radio-button label="card">卡片</el-radio-button>
|
||||
<el-radio-button label="chrome">谷歌</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>固定 Header</span>
|
||||
<el-switch v-model="fixedHeader" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>显示 Logo</span>
|
||||
<el-switch v-model="sidebarLogo" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>动态标题</span>
|
||||
<el-switch v-model="dynamicTitle" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>底部版权</span>
|
||||
<el-switch v-model="footerVisible" class="drawer-switch" />
|
||||
</div>
|
||||
|
||||
<el-divider/>
|
||||
|
||||
<el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">保存配置</el-button>
|
||||
<el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">重置配置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ThemePicker from '@/components/ThemePicker'
|
||||
|
||||
export default {
|
||||
components: { ThemePicker },
|
||||
expose: ['openSetting'],
|
||||
data() {
|
||||
return {
|
||||
theme: this.$store.state.settings.theme,
|
||||
sideTheme: this.$store.state.settings.sideTheme,
|
||||
navType: this.$store.state.settings.navType,
|
||||
showSettings: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fixedHeader: {
|
||||
get() {
|
||||
return this.$store.state.settings.fixedHeader
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'fixedHeader',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
},
|
||||
tagsViewPersist: {
|
||||
get() {
|
||||
return this.$store.state.settings.tagsViewPersist
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'tagsViewPersist',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
},
|
||||
tagsView: {
|
||||
get() {
|
||||
return this.$store.state.settings.tagsView
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'tagsView',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
},
|
||||
tagsIcon: {
|
||||
get() {
|
||||
return this.$store.state.settings.tagsIcon
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'tagsIcon',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
},
|
||||
tagsViewStyle: {
|
||||
get() {
|
||||
return this.$store.state.settings.tagsViewStyle
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'tagsViewStyle',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
},
|
||||
sidebarLogo: {
|
||||
get() {
|
||||
return this.$store.state.settings.sidebarLogo
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'sidebarLogo',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
},
|
||||
dynamicTitle: {
|
||||
get() {
|
||||
return this.$store.state.settings.dynamicTitle
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'dynamicTitle',
|
||||
value: val
|
||||
})
|
||||
this.$store.dispatch('settings/setTitle', this.$store.state.settings.title)
|
||||
}
|
||||
},
|
||||
footerVisible: {
|
||||
get() {
|
||||
return this.$store.state.settings.footerVisible
|
||||
},
|
||||
set(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'footerVisible',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
navType: {
|
||||
handler(val) {
|
||||
if (val == 1) {
|
||||
this.$store.dispatch("app/toggleSideBarHide", false)
|
||||
}
|
||||
if (val == 2) {
|
||||
}
|
||||
if (val == 3) {
|
||||
this.$store.dispatch("app/toggleSideBarHide", true)
|
||||
}
|
||||
if ([1, 3].includes(val)) {
|
||||
this.$store.commit("SET_SIDEBAR_ROUTERS",this.$store.state.permission.defaultRoutes)
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
themeChange(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'theme',
|
||||
value: val
|
||||
})
|
||||
this.theme = val
|
||||
},
|
||||
handleTheme(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'sideTheme',
|
||||
value: val
|
||||
})
|
||||
this.sideTheme = val
|
||||
},
|
||||
handleNavType(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'navType',
|
||||
value: val
|
||||
})
|
||||
this.navType = val
|
||||
},
|
||||
openSetting() {
|
||||
this.showSettings = true
|
||||
},
|
||||
closeSetting(){
|
||||
this.showSettings = false
|
||||
},
|
||||
saveSetting() {
|
||||
this.$modal.loading("正在保存到本地,请稍候...")
|
||||
if (!this.tagsViewPersist) {
|
||||
this.$cache.local.remove('tags-view-visited')
|
||||
}
|
||||
this.$cache.local.set(
|
||||
"layout-setting",
|
||||
`{
|
||||
"navType":${this.navType},
|
||||
"tagsView":${this.tagsView},
|
||||
"tagsIcon":${this.tagsIcon},
|
||||
"tagsViewStyle":"${this.tagsViewStyle}",
|
||||
"tagsViewPersist":${this.tagsViewPersist},
|
||||
"fixedHeader":${this.fixedHeader},
|
||||
"sidebarLogo":${this.sidebarLogo},
|
||||
"dynamicTitle":${this.dynamicTitle},
|
||||
"footerVisible":${this.footerVisible},
|
||||
"sideTheme":"${this.sideTheme}",
|
||||
"theme":"${this.theme}"
|
||||
}`
|
||||
)
|
||||
setTimeout(this.$modal.closeLoading(), 1000)
|
||||
},
|
||||
resetSetting() {
|
||||
this.$modal.loading("正在清除设置缓存并刷新,请稍候...")
|
||||
this.$cache.local.remove('tags-view-visited')
|
||||
this.$cache.local.remove("layout-setting")
|
||||
setTimeout("window.location.reload()", 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-drawer-content {
|
||||
.setting-drawer-title {
|
||||
margin-bottom: 12px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.setting-drawer-block-checbox {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.setting-drawer-block-checbox-item {
|
||||
position: relative;
|
||||
margin-right: 16px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.setting-drawer-block-checbox-selectIcon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top: 15px;
|
||||
padding-left: 24px;
|
||||
color: #00875A;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-container {
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
|
||||
.drawer-title {
|
||||
margin-bottom: 12px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.drawer-item {
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.drawer-switch {
|
||||
float: right
|
||||
}
|
||||
}
|
||||
|
||||
// 导航模式
|
||||
.nav-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.activeItem {
|
||||
border: 2px solid #{'var(--theme)'} !important;
|
||||
}
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
margin-right: 16px;
|
||||
cursor: pointer;
|
||||
width: 56px;
|
||||
height: 48px;
|
||||
border-radius: 4px;
|
||||
background: #f0f2f5;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.left {
|
||||
b:first-child {
|
||||
display: block;
|
||||
height: 30%;
|
||||
background: #fff;
|
||||
}
|
||||
b:last-child {
|
||||
width: 30%;
|
||||
background: #1b2a47;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
}
|
||||
.mix {
|
||||
b:first-child {
|
||||
border-radius: 4px 4px 0 0;
|
||||
display: block;
|
||||
height: 30%;
|
||||
background: #1b2a47;
|
||||
}
|
||||
b:last-child {
|
||||
width: 30%;
|
||||
background: #1b2a47;
|
||||
position: absolute;
|
||||
height: 70%;
|
||||
border-radius: 0 0 0 4px;
|
||||
}
|
||||
}
|
||||
.top {
|
||||
b:first-child {
|
||||
display: block;
|
||||
height: 30%;
|
||||
background: #1b2a47;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div :class="['sidebar-theme-wrapper', settings.sideTheme]" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
|
||||
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
|
||||
<template>
|
||||
<div :class="['sidebar-theme-wrapper', 'theme-dark']" :style="{ backgroundColor: variables.menuBackground }">
|
||||
<el-scrollbar class="theme-dark" wrap-class="scrollbar-wrapper">
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
:collapse="isCollapse"
|
||||
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
|
||||
:text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
|
||||
:background-color="variables.menuBackground"
|
||||
:text-color="variables.menuColor"
|
||||
:unique-opened="true"
|
||||
:active-text-color="settings.sideTheme === 'theme-dark' ? '#ffffff' : settings.theme"
|
||||
:active-text-color="'#ffffff'"
|
||||
:collapse-transition="false"
|
||||
mode="vertical"
|
||||
>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="tags-view-container" class="tags-view-container" :class="{ 'tags-view-container--chrome': tagsViewStyle === 'chrome' }" :style="chromeVars">
|
||||
<template>
|
||||
<div id="tags-view-container" class="tags-view-container">
|
||||
<!-- 左切换箭头 -->
|
||||
<span class="tags-nav-btn tags-nav-btn--left" :class="{ disabled: !canScrollLeft }" @click="scrollLeft">
|
||||
<i class="el-icon-arrow-left" />
|
||||
@@ -11,7 +11,7 @@
|
||||
v-for="tag in visitedViews"
|
||||
ref="tag"
|
||||
:key="tag.path"
|
||||
:class="{ 'active': isActive(tag), 'has-icon': tagsIcon }"
|
||||
:class="{ 'active': isActive(tag) }"
|
||||
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
||||
tag="span"
|
||||
class="tags-view-item"
|
||||
@@ -19,7 +19,6 @@
|
||||
@click.middle.native="!isAffix(tag) ? closeSelectedTag(tag) : ''"
|
||||
@contextmenu.prevent.native="openMenu(tag, $event)"
|
||||
>
|
||||
<svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon" style="margin-right: 3px;" />
|
||||
{{ tag.title }}
|
||||
<span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
|
||||
</router-link>
|
||||
@@ -91,26 +90,8 @@ export default {
|
||||
routes() {
|
||||
return this.$store.state.permission.routes
|
||||
},
|
||||
theme() {
|
||||
return this.$store.state.settings.theme
|
||||
},
|
||||
tagsIcon() {
|
||||
return this.$store.state.settings.tagsIcon
|
||||
},
|
||||
tagsViewStyle() {
|
||||
return this.$store.state.settings.tagsViewStyle
|
||||
},
|
||||
selectedDropdownTag() {
|
||||
return this.visitedViews.find(v => this.isActive(v)) || {}
|
||||
},
|
||||
chromeVars() {
|
||||
if (this.tagsViewStyle !== 'chrome') return {}
|
||||
const primary = this.theme || '#00875A'
|
||||
return {
|
||||
'--chrome-tab-active-bg': this.mixHexWithWhite(primary, 0.15),
|
||||
'--chrome-tab-text-active': primary,
|
||||
'--chrome-wing-r': '10px'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -148,24 +129,14 @@ export default {
|
||||
this.toggleFullscreen()
|
||||
}
|
||||
},
|
||||
mixHexWithWhite(hex, ratio) {
|
||||
const clean = hex.replace('#', '')
|
||||
const r = parseInt(clean.substring(0, 2), 16)
|
||||
const g = parseInt(clean.substring(2, 4), 16)
|
||||
const b = parseInt(clean.substring(4, 6), 16)
|
||||
const mr = Math.round(r * ratio + 255 * (1 - ratio))
|
||||
const mg = Math.round(g * ratio + 255 * (1 - ratio))
|
||||
const mb = Math.round(b * ratio + 255 * (1 - ratio))
|
||||
return `rgb(${mr}, ${mg}, ${mb})`
|
||||
},
|
||||
isActive(route) {
|
||||
return route.path === this.$route.path
|
||||
},
|
||||
tagActiveStyle(tag) {
|
||||
if (!this.isActive(tag) || this.tagsViewStyle !== 'card') return {}
|
||||
if (!this.isActive(tag)) return {}
|
||||
return {
|
||||
"background-color": this.theme,
|
||||
"border-color": this.theme
|
||||
"background-color": "#00875A",
|
||||
"border-color": "#00875A"
|
||||
}
|
||||
},
|
||||
isAffix(tag) {
|
||||
@@ -209,9 +180,6 @@ export default {
|
||||
return tags
|
||||
},
|
||||
initTags() {
|
||||
if (this.$store.state.settings.tagsViewPersist) {
|
||||
this.$store.dispatch('tagsView/loadPersistedViews')
|
||||
}
|
||||
const affixTags = this.affixTags = this.filterAffixTags(this.routes)
|
||||
for (const tag of affixTags) {
|
||||
if (tag.name) {
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
<template>
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
mode="horizontal"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<template v-for="(item, index) in topMenus">
|
||||
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber">
|
||||
<svg-icon
|
||||
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
|
||||
:icon-class="item.meta.icon"/>
|
||||
{{ item.meta.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<!-- 顶部菜单超出数量折叠 -->
|
||||
<el-submenu :style="{'--theme': theme}" index="more" :key="visibleNumber" v-if="topMenus.length > visibleNumber">
|
||||
<template slot="title">更多菜单</template>
|
||||
<template v-for="(item, index) in topMenus">
|
||||
<el-menu-item
|
||||
:index="item.path"
|
||||
:key="index"
|
||||
v-if="index >= visibleNumber">
|
||||
<svg-icon
|
||||
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
|
||||
:icon-class="item.meta.icon"/>
|
||||
{{ item.meta.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { constantRoutes } from "@/router"
|
||||
import { isHttp } from "@/utils/validate"
|
||||
|
||||
// 隐藏侧边栏路由
|
||||
const hideList = ['/index', '/user/profile']
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 顶部栏初始数
|
||||
visibleNumber: 5,
|
||||
// 当前激活菜单的 index
|
||||
currentIndex: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
theme() {
|
||||
return this.$store.state.settings.theme
|
||||
},
|
||||
// 顶部显示菜单
|
||||
topMenus() {
|
||||
let topMenus = []
|
||||
this.routers.map((menu) => {
|
||||
if (menu.hidden !== true) {
|
||||
// 兼容顶部栏一级菜单内部跳转
|
||||
if (menu.path === '/' && menu.children) {
|
||||
topMenus.push(menu.children[0])
|
||||
} else {
|
||||
topMenus.push(menu)
|
||||
}
|
||||
}
|
||||
})
|
||||
return topMenus
|
||||
},
|
||||
// 所有的路由信息
|
||||
routers() {
|
||||
return this.$store.state.permission.topbarRouters
|
||||
},
|
||||
// 设置子路由
|
||||
childrenMenus() {
|
||||
var childrenMenus = []
|
||||
this.routers.map((router) => {
|
||||
for (var item in router.children) {
|
||||
if (router.children[item].parentPath === undefined) {
|
||||
if (router.path === "/") {
|
||||
router.children[item].path = "/" + router.children[item].path
|
||||
} else {
|
||||
if (!isHttp(router.children[item].path)) {
|
||||
router.children[item].path = router.path + "/" + router.children[item].path
|
||||
}
|
||||
}
|
||||
router.children[item].parentPath = router.path
|
||||
}
|
||||
childrenMenus.push(router.children[item])
|
||||
}
|
||||
})
|
||||
return constantRoutes.concat(childrenMenus)
|
||||
},
|
||||
// 默认激活的菜单
|
||||
activeMenu() {
|
||||
const path = this.$route.path
|
||||
let activePath = path
|
||||
if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
|
||||
const tmpPath = path.substring(1, path.length)
|
||||
if (!this.$route.meta.link) {
|
||||
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"))
|
||||
this.$store.dispatch('app/toggleSideBarHide', false)
|
||||
}
|
||||
} else if (!this.$route.children) {
|
||||
activePath = path
|
||||
this.$store.dispatch('app/toggleSideBarHide', true)
|
||||
}
|
||||
this.activeRoutes(activePath)
|
||||
return activePath
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
window.addEventListener('resize', this.setVisibleNumber)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.setVisibleNumber)
|
||||
},
|
||||
mounted() {
|
||||
this.setVisibleNumber()
|
||||
},
|
||||
methods: {
|
||||
// 根据宽度计算设置显示栏数
|
||||
setVisibleNumber() {
|
||||
const width = document.body.getBoundingClientRect().width / 3
|
||||
this.visibleNumber = parseInt(width / 85)
|
||||
},
|
||||
// 菜单选择事件
|
||||
handleSelect(key, keyPath) {
|
||||
this.currentIndex = key
|
||||
const route = this.routers.find(item => item.path === key)
|
||||
if (isHttp(key)) {
|
||||
// http(s):// 路径新窗口打开
|
||||
window.open(key, "_blank")
|
||||
} else if (!route || !route.children) {
|
||||
// 没有子路由路径内部打开
|
||||
const routeMenu = this.childrenMenus.find(item => item.path === key)
|
||||
if (routeMenu && routeMenu.query) {
|
||||
let query = JSON.parse(routeMenu.query)
|
||||
this.$router.push({ path: key, query: query })
|
||||
} else {
|
||||
this.$router.push({ path: key })
|
||||
}
|
||||
this.$store.dispatch('app/toggleSideBarHide', true)
|
||||
} else {
|
||||
// 显示左侧联动菜单
|
||||
this.activeRoutes(key)
|
||||
this.$store.dispatch('app/toggleSideBarHide', false)
|
||||
}
|
||||
},
|
||||
// 当前激活的路由
|
||||
activeRoutes(key) {
|
||||
var routes = []
|
||||
if (this.childrenMenus && this.childrenMenus.length > 0) {
|
||||
this.childrenMenus.map((item) => {
|
||||
if (key == item.parentPath || (key == "index" && "" == item.path)) {
|
||||
routes.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (routes.length > 0) {
|
||||
this.$store.commit("SET_SIDEBAR_ROUTERS", routes)
|
||||
} else {
|
||||
this.$store.dispatch('app/toggleSideBarHide', true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.topmenu-container.el-menu--horizontal > .el-menu-item {
|
||||
float: left;
|
||||
height: 50px !important;
|
||||
line-height: 50px !important;
|
||||
color: #303133 !important;
|
||||
padding: 0 5px !important;
|
||||
margin: 0 10px !important;
|
||||
}
|
||||
|
||||
.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
|
||||
border-bottom: 2px solid #{'var(--theme)'} !important;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* submenu item */
|
||||
.topmenu-container.el-menu--horizontal > .el-submenu .el-submenu__title {
|
||||
float: left;
|
||||
height: 50px !important;
|
||||
line-height: 50px !important;
|
||||
color: #303133 !important;
|
||||
padding: 0 5px !important;
|
||||
margin: 0 10px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,4 @@
|
||||
export { default as AppMain } from './AppMain'
|
||||
export { default as AppMain } from './AppMain'
|
||||
export { default as Navbar } from './Navbar'
|
||||
export { default as Settings } from './Settings'
|
||||
export { default as Sidebar } from './Sidebar/index.vue'
|
||||
export { default as TagsView } from './TagsView/index.vue'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme, '--current-color-light': theme + '1a', '--current-color-dark-bg': theme + '33'}">
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper" :style="{'--current-color': '#00875A', '--current-color-light': '#00875A1a', '--current-color-dark-bg': '#00875A33'}">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
||||
|
||||
<!-- 顶部全宽 Header -->
|
||||
@@ -12,26 +12,25 @@
|
||||
class="mobile-hamburger"
|
||||
@toggleClick="toggleSideBar"
|
||||
/>
|
||||
<span class="sys-title">教学管理信息系统</span>
|
||||
<span class="sys-title" title="关闭所有已打开的页签" @click="handleCloseAllTabs">教学管理信息系统</span>
|
||||
</div>
|
||||
<semester-bar class="top-header__center" />
|
||||
<navbar class="top-header__right" @setLayout="setLayout" :header-mode="true" />
|
||||
<navbar class="top-header__right" :header-mode="true" />
|
||||
</div>
|
||||
|
||||
<!-- 下方:侧边栏 + 主内容 -->
|
||||
<div class="lower-container" :class="{sidebarHide:sidebar.hide}">
|
||||
<sidebar v-if="!sidebar.hide" class="sidebar-container"/>
|
||||
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
|
||||
<tags-view v-if="needTagsView"/>
|
||||
<div :class="{hasTagsView:true,sidebarHide:sidebar.hide}" class="main-container">
|
||||
<tags-view/>
|
||||
<app-main/>
|
||||
<settings ref="settingRef"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
||||
import { AppMain, Navbar, Sidebar, TagsView } from './components'
|
||||
import SemesterBar from './components/SemesterBar'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
import ResizeMixin from './mixin/ResizeHandler'
|
||||
@@ -43,7 +42,6 @@ export default {
|
||||
components: {
|
||||
AppMain,
|
||||
Navbar,
|
||||
Settings,
|
||||
Sidebar,
|
||||
TagsView,
|
||||
SemesterBar,
|
||||
@@ -52,11 +50,8 @@ export default {
|
||||
mixins: [ResizeMixin],
|
||||
computed: {
|
||||
...mapState({
|
||||
theme: state => state.settings.theme,
|
||||
sideTheme: state => state.settings.sideTheme,
|
||||
sidebar: state => state.app.sidebar,
|
||||
device: state => state.app.device,
|
||||
needTagsView: state => state.settings.tagsView
|
||||
device: state => state.app.device
|
||||
}),
|
||||
classObj() {
|
||||
return {
|
||||
@@ -75,8 +70,15 @@ export default {
|
||||
toggleSideBar() {
|
||||
this.$store.dispatch('app/toggleSideBar')
|
||||
},
|
||||
setLayout() {
|
||||
this.$refs.settingRef.openSetting()
|
||||
handleCloseAllTabs() {
|
||||
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
|
||||
const last = visitedViews[visitedViews.length - 1]
|
||||
if (last) {
|
||||
this.$router.push(last.fullPath).catch(() => {})
|
||||
} else {
|
||||
this.$router.push('/').catch(() => {})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,6 +139,14 @@ export default {
|
||||
white-space: nowrap;
|
||||
letter-spacing: 1.5px;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
padding: 4px 10px;
|
||||
transition: background 0.25s ease;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Vue from 'vue'
|
||||
import Vue from 'vue'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
@@ -13,6 +13,10 @@ import router from './router'
|
||||
import directive from './directive' // directive
|
||||
import plugins from './plugins' // plugins
|
||||
import { download } from '@/utils/request'
|
||||
import { initAdaptive } from '@/utils/adaptive' // 全局视口等比缩放自适应
|
||||
|
||||
// 初始化全局自适应,保障不同大小屏幕下页面布局不崩塌
|
||||
initAdaptive()
|
||||
|
||||
import './assets/icons' // icon
|
||||
import './permission' // permission control
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import router from './router'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import { Message } from 'element-ui'
|
||||
import NProgress from 'nprogress'
|
||||
@@ -18,7 +18,6 @@ const isWhiteList = (path) => {
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start()
|
||||
if (getToken()) {
|
||||
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
|
||||
const isLock = store.getters.isLock
|
||||
/* has token*/
|
||||
if (to.path === '/login') {
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 网页标题
|
||||
*/
|
||||
title: process.env.VUE_APP_TITLE,
|
||||
|
||||
/**
|
||||
* 侧边栏主题 深色主题theme-dark,浅色主题theme-light
|
||||
*/
|
||||
sideTheme: 'theme-dark',
|
||||
|
||||
/**
|
||||
* 系统布局配置
|
||||
*/
|
||||
showSettings: true,
|
||||
|
||||
/**
|
||||
* 菜单导航模式 1、纯左侧 2、混合(左侧+顶部) 3、纯顶部
|
||||
*/
|
||||
navType: 1,
|
||||
|
||||
/**
|
||||
* 是否显示 tagsView
|
||||
*/
|
||||
tagsView: true,
|
||||
|
||||
/**
|
||||
* 持久化标签页
|
||||
*/
|
||||
tagsViewPersist: false,
|
||||
|
||||
/**
|
||||
* 显示页签图标
|
||||
*/
|
||||
tagsIcon: false,
|
||||
|
||||
/**
|
||||
* 标签页样式:card 卡片(默认)、chrome 谷歌浏览器风格
|
||||
*/
|
||||
tagsViewStyle: 'card',
|
||||
|
||||
/**
|
||||
* 是否固定头部
|
||||
*/
|
||||
fixedHeader: true,
|
||||
|
||||
/**
|
||||
* 是否显示logo
|
||||
*/
|
||||
sidebarLogo: true,
|
||||
|
||||
/**
|
||||
* 是否显示动态标题
|
||||
*/
|
||||
dynamicTitle: false,
|
||||
|
||||
/**
|
||||
* 是否显示底部版权
|
||||
*/
|
||||
footerVisible: false,
|
||||
|
||||
/**
|
||||
* 底部版权文本内容
|
||||
*/
|
||||
footerContent: 'Copyright © 2018-2026 roomroot. All Rights Reserved.'
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import Vue from 'vue'
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import app from './modules/app'
|
||||
import lock from './modules/lock'
|
||||
@@ -6,7 +6,6 @@ import dict from './modules/dict'
|
||||
import user from './modules/user'
|
||||
import tagsView from './modules/tagsView'
|
||||
import permission from './modules/permission'
|
||||
import settings from './modules/settings'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
@@ -18,8 +17,7 @@ const store = new Vuex.Store({
|
||||
dict,
|
||||
user,
|
||||
tagsView,
|
||||
permission,
|
||||
settings
|
||||
permission
|
||||
},
|
||||
getters
|
||||
})
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import defaultSettings from '@/settings'
|
||||
import { useDynamicTitle } from '@/utils/dynamicTitle'
|
||||
|
||||
const { sideTheme, showSettings, navType, tagsView, tagsViewPersist, tagsIcon, tagsViewStyle, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings
|
||||
|
||||
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
|
||||
const state = {
|
||||
title: '',
|
||||
theme: storageSetting.theme || '#00875A',
|
||||
sideTheme: storageSetting.sideTheme || sideTheme,
|
||||
showSettings: showSettings,
|
||||
navType: storageSetting.navType === undefined ? navType : storageSetting.navType,
|
||||
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
|
||||
tagsViewPersist: storageSetting.tagsViewPersist === undefined ? tagsViewPersist : storageSetting.tagsViewPersist,
|
||||
tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon,
|
||||
tagsViewStyle: storageSetting.tagsViewStyle === undefined ? tagsViewStyle : storageSetting.tagsViewStyle,
|
||||
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
|
||||
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
|
||||
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle,
|
||||
footerVisible: storageSetting.footerVisible === undefined ? footerVisible : storageSetting.footerVisible,
|
||||
footerContent: footerContent
|
||||
}
|
||||
const mutations = {
|
||||
CHANGE_SETTING: (state, { key, value }) => {
|
||||
if (state.hasOwnProperty(key)) {
|
||||
state[key] = value
|
||||
}
|
||||
},
|
||||
SET_TITLE: (state, title) => {
|
||||
state.title = title
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
// 修改布局设置
|
||||
changeSetting({ commit }, data) {
|
||||
commit('CHANGE_SETTING', data)
|
||||
},
|
||||
// 设置网页标题
|
||||
setTitle({ commit }, title) {
|
||||
commit('SET_TITLE', title)
|
||||
useDynamicTitle()
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import store from '@/store'
|
||||
import cache from '@/plugins/cache'
|
||||
|
||||
const PERSIST_KEY = 'tags-view-visited'
|
||||
|
||||
// 布局已固定,不启用标签页持久化
|
||||
function isPersistEnabled() {
|
||||
return store.state.settings.tagsViewPersist
|
||||
return false
|
||||
}
|
||||
|
||||
function saveVisitedViews(views) {
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* 全局视口等比缩放 —— 让整个系统在不同大小屏幕(桌面 1280~4K)下布局不崩塌。
|
||||
*
|
||||
* 原理:
|
||||
* 以 DESIGN_WIDTH(1920)为设计基准宽度。将视口宽度与设计宽的比值作为缩放倍数,
|
||||
* 作用到文档根节点 <html> 的 zoom 上:
|
||||
* - 视口 < 设计宽(如 1280):zoom < 1,整体等比缩小,避免窄屏布局被撑破;
|
||||
* - 视口 = 设计宽(1920):zoom = 1,原生 1:1 显示;
|
||||
* - 视口 > 设计宽(如 4K 3840):zoom = 2,整体等比放大,大屏不再留白/字小。
|
||||
* 缩放倍数被限制在 MIN_SCALE ~ MAX_SCALE 之间,MAX_SCALE=2 恰好覆盖 4K(3840/1920)。
|
||||
*
|
||||
* 采用 zoom 挂在 documentElement 上,可覆盖包括 Element UI 挂载到 body 的
|
||||
* 弹窗/提示/下拉选择在内的所有内容,保证整套界面一致缩放、不塌陷。
|
||||
*
|
||||
* 兼容性:
|
||||
* - zoom:Chrome/Edge/Safari/Opera 全系、Firefox 126+(2024-05 起)、
|
||||
* 以及国内常见 Chromium 内核浏览器(360/QQ/微信等)均支持;
|
||||
* - 本方案对不支持 zoom 的旧浏览器(如 2024 前的 Firefox)做能力探测,
|
||||
* 自动降级为 transform: scale() 回退,保证不崩塌、可正常使用。
|
||||
*/
|
||||
|
||||
let initialized = false
|
||||
|
||||
export const DEFAULT_DESIGN_WIDTH = 1920
|
||||
// 最小缩放倍数:极窄视口的安全下限,避免文字过小/布局异常
|
||||
export const MIN_SCALE = 0.5
|
||||
// 最大缩放倍数:2 对应 4K(3840/1920=2),更高分辨率也封顶在此,避免过度放大
|
||||
export const MAX_SCALE = 2
|
||||
|
||||
/**
|
||||
* 探测当前浏览器是否支持 CSS zoom 属性。
|
||||
* 现代 Chromium/Safari/Firefox(≥126) 返回 true;旧 Firefox(<126) 返回 false。
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isZoomSupported() {
|
||||
const el = document.createElement('div')
|
||||
el.style.zoom = '0.5'
|
||||
// 能读回 "0.5" 说明浏览器真正支持
|
||||
return el.style.zoom === '0.5'
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化全局自适应。可在任意入口调用,重复调用幂等。
|
||||
* @param {number} [designWidth] 设计基准宽度,默认 1920
|
||||
*/
|
||||
export function initAdaptive(designWidth = DEFAULT_DESIGN_WIDTH) {
|
||||
if (initialized) {
|
||||
return
|
||||
}
|
||||
initialized = true
|
||||
|
||||
const useZoom = isZoomSupported()
|
||||
|
||||
// rAF 帧对齐节流:把同一帧内多次 resize 合并为一次
|
||||
let rafId = null
|
||||
// 真实写入节流 + 尾随兜底:拖拽/设备模拟期间 resize 高频触发,
|
||||
// 若每帧都写 html.zoom 会强制整页重排+重绘导致卡顿,因此限制真实写入频率
|
||||
let lastAppliedScale = -1
|
||||
let lastWriteAt = 0
|
||||
let trailingTimer = null
|
||||
const WRITE_MIN_INTERVAL = 100 // ms
|
||||
|
||||
function computeScale() {
|
||||
const root = document.documentElement
|
||||
const width = window.innerWidth || (root && root.clientWidth) || designWidth
|
||||
const ratio = width / designWidth
|
||||
// 收敛到 [MIN_SCALE, MAX_SCALE],规避极端宽高的异常比例
|
||||
return Math.min(MAX_SCALE, Math.max(MIN_SCALE, ratio))
|
||||
}
|
||||
|
||||
function writeScale(scale) {
|
||||
const root = document.documentElement
|
||||
if (!root) {
|
||||
return
|
||||
}
|
||||
// 值未变化:跳过,避免冗余的样式失效/整页重排
|
||||
if (Math.abs(scale - lastAppliedScale) < 1e-4) {
|
||||
return
|
||||
}
|
||||
lastAppliedScale = scale
|
||||
|
||||
if (scale === 1) {
|
||||
clearScale(root)
|
||||
return
|
||||
}
|
||||
|
||||
if (useZoom) {
|
||||
// 首选:zoom 参与布局计算,视觉与占位一致,最平滑
|
||||
root.style.zoom = String(scale)
|
||||
// 注入缩放与逆缩放变量:逆缩放用于把挂到 body 的 Element 浮层还原为 1:1,
|
||||
// 以抵消 zoom 对 getBoundingClientRect 坐标造成的二次缩放(否则下拉框位置错乱)
|
||||
root.style.setProperty('--adaptive-scale', String(scale))
|
||||
root.style.setProperty('--adaptive-scale-inv', String(1 / scale))
|
||||
} else {
|
||||
// 回退:transform 仅影响视觉;将布局宽度固定为设计宽并从左上角缩放,
|
||||
// 使其铺满视口且不改变内部结构,旧浏览器也能正常使用
|
||||
root.style.transformOrigin = 'top left'
|
||||
root.style.width = `${designWidth}px`
|
||||
root.style.transform = `scale(${scale})`
|
||||
}
|
||||
}
|
||||
|
||||
function clearScale(root) {
|
||||
if (useZoom) {
|
||||
root.style.zoom = ''
|
||||
root.style.removeProperty('--adaptive-scale')
|
||||
root.style.removeProperty('--adaptive-scale-inv')
|
||||
} else {
|
||||
root.style.transform = ''
|
||||
root.style.transformOrigin = ''
|
||||
root.style.width = ''
|
||||
}
|
||||
}
|
||||
|
||||
/** 立即计算并写入一次(带值变化守卫) */
|
||||
function applyNow() {
|
||||
lastWriteAt = Date.now()
|
||||
writeScale(computeScale())
|
||||
}
|
||||
|
||||
function onResize() {
|
||||
if (document.hidden) {
|
||||
return // 后台标签不执行,避免无谓开销
|
||||
}
|
||||
if (rafId) {
|
||||
return // 本帧内已有待执行任务,合并
|
||||
}
|
||||
rafId = window.requestAnimationFrame(() => {
|
||||
rafId = null
|
||||
if (document.hidden) {
|
||||
return
|
||||
}
|
||||
const now = Date.now()
|
||||
if (trailingTimer) {
|
||||
clearTimeout(trailingTimer)
|
||||
}
|
||||
// 距上次真实写入已超过阈值才立即写入,其余情况靠尾随兜底,避免满帧整页重排
|
||||
if (now - lastWriteAt >= WRITE_MIN_INTERVAL) {
|
||||
applyNow()
|
||||
}
|
||||
// 尾随:拖拽/改变尺寸停下后,确保落到最终窗口尺寸
|
||||
trailingTimer = setTimeout(applyNow, WRITE_MIN_INTERVAL)
|
||||
})
|
||||
}
|
||||
|
||||
function onVisibilityChange() {
|
||||
if (!document.hidden) {
|
||||
// 从后台切回时补算一次
|
||||
if (trailingTimer) {
|
||||
clearTimeout(trailingTimer)
|
||||
}
|
||||
applyNow()
|
||||
}
|
||||
}
|
||||
|
||||
// 首次:渲染前同步应用一次,避免首帧闪烁
|
||||
applyNow()
|
||||
window.addEventListener('resize', onResize)
|
||||
// 从后台标签切回来时,若期间窗口尺寸变化(因 hidden 被跳过)需补算一次
|
||||
document.addEventListener('visibilitychange', onVisibilityChange)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import store from '@/store'
|
||||
import defaultSettings from '@/settings'
|
||||
|
||||
/**
|
||||
* 动态修改标题
|
||||
*/
|
||||
export function useDynamicTitle() {
|
||||
if (store.state.settings.dynamicTitle) {
|
||||
document.title = store.state.settings.title + ' - ' + defaultSettings.title
|
||||
} else {
|
||||
document.title = defaultSettings.title
|
||||
}
|
||||
}
|
||||
@@ -1,881 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container assessment-page">
|
||||
<el-tabs v-model="activeTab" type="border-card" class="assessment-tabs">
|
||||
<!-- ==================== Tab1:课程表信息列表 ==================== -->
|
||||
<el-tab-pane label="课程表信息列表" name="schedule">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="scheduleSearchForm" label-width="130px" class="search-form">
|
||||
<!-- 考核日期:独立整行 -->
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.examDateEnabled">考核日期</el-checkbox>
|
||||
</template>
|
||||
<div class="date-block">
|
||||
<div class="date-range">
|
||||
<span>从</span>
|
||||
<el-date-picker
|
||||
v-model="scheduleSearchForm.examDateFrom"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
:disabled="!scheduleSearchForm.examDateEnabled"
|
||||
/>
|
||||
<span>到</span>
|
||||
<el-date-picker
|
||||
v-model="scheduleSearchForm.examDateTo"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
:disabled="!scheduleSearchForm.examDateEnabled"
|
||||
/>
|
||||
</div>
|
||||
<div class="quick-row">
|
||||
<el-select v-model="scheduleSearchForm.semester" class="quick-select">
|
||||
<el-option v-for="item in semesterOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-button size="small" @click="handleQuickDate('semester')">确定</el-button>
|
||||
<el-select v-model="scheduleSearchForm.week" class="quick-select">
|
||||
<el-option v-for="item in weekOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-button size="small" @click="handleQuickDate('week')">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</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="scheduleSearchForm.deptEnabled">教研室</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.dept" class="w-full" :disabled="!scheduleSearchForm.deptEnabled">
|
||||
<el-option v-for="item in deptOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.buildingEnabled">教学楼</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.building" class="w-full" :disabled="!scheduleSearchForm.buildingEnabled">
|
||||
<el-option v-for="item in buildingOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="培训层次">
|
||||
<el-select v-model="scheduleSearchForm.trainLevel" placeholder="请选择" clearable class="w-full">
|
||||
<el-option v-for="item in trainLevelOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.deptSystemEnabled">监考教员所属院部系</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.deptSystem" class="w-full" :disabled="!scheduleSearchForm.deptSystemEnabled">
|
||||
<el-option v-for="item in deptOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.resourceTypeEnabled">保障资源类别</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.resourceType" class="w-full" :disabled="!scheduleSearchForm.resourceTypeEnabled">
|
||||
<el-option v-for="item in resourceTypeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.periodEnabled">节次</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.period" class="w-full" :disabled="!scheduleSearchForm.periodEnabled">
|
||||
<el-option v-for="item in periodOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.combineEnabled">合堂选项</el-checkbox>
|
||||
</template>
|
||||
<el-checkbox v-model="scheduleSearchForm.combineChange" :disabled="!scheduleSearchForm.combineEnabled">合堂变动</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="专业名称">
|
||||
<el-input v-model="scheduleSearchForm.majorName" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="监考教员姓名">
|
||||
<el-input v-model="scheduleSearchForm.invigilatorName" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="考核场地名称">
|
||||
<el-input v-model="scheduleSearchForm.examPlaceName" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.invigilatorEnabled">监考教员</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.invigilator" class="w-full" :disabled="!scheduleSearchForm.invigilatorEnabled">
|
||||
<el-option v-for="item in invigilatorOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.examSubjectEnabled">考核科目</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.examSubject" class="w-full" :disabled="!scheduleSearchForm.examSubjectEnabled">
|
||||
<el-option v-for="item in subjectOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.placeEnabled">教学场地</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.place" class="w-full" :disabled="!scheduleSearchForm.placeEnabled">
|
||||
<el-option v-for="item in placeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.teamEnabled">班次</el-checkbox>
|
||||
</template>
|
||||
<div class="team-field">
|
||||
<el-select v-model="scheduleSearchForm.team" placeholder="请选择" :disabled="!scheduleSearchForm.teamEnabled">
|
||||
<el-option v-for="item in teamOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-checkbox v-model="scheduleSearchForm.showElective" class="elective-check">显示选修课临时班</el-checkbox>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.teamCategoryEnabled">队别</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.teamCategory" class="w-full" :disabled="!scheduleSearchForm.teamCategoryEnabled">
|
||||
<el-option v-for="item in teamCategoryOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.resourceEnabled">保障资源</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.resource" class="w-full" :disabled="!scheduleSearchForm.resourceEnabled">
|
||||
<el-option v-for="item in resourceOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.manageOrgEnabled">管理机构</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="scheduleSearchForm.manageOrg" class="w-full" :disabled="!scheduleSearchForm.manageOrgEnabled">
|
||||
<el-option v-for="item in manageOrgOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="scheduleSearchForm.logOptionEnabled">日志填写选项</el-checkbox>
|
||||
</template>
|
||||
<el-radio-group v-model="scheduleSearchForm.logOption" :disabled="!scheduleSearchForm.logOptionEnabled">
|
||||
<el-radio :label="'已填写'">已填写</el-radio>
|
||||
<el-radio :label="'未填写'">未填写</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="年级">
|
||||
<el-input v-model="scheduleSearchForm.gradeInput" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="队别班次名称">
|
||||
<el-input v-model="scheduleSearchForm.teamClassName" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="科目名称">
|
||||
<el-input v-model="scheduleSearchForm.subjectName" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="search-tip">注意:勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleScheduleQuery">查询</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 操作与列表区域 -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<div class="table-title">课程表信息列表</div>
|
||||
<div class="action-bar">
|
||||
<div class="action-row">
|
||||
<el-button type="primary" size="small" @click="handleScheduleBatch('批量设置备注信息')">批量设置备注信息</el-button>
|
||||
<el-button type="primary" size="small" @click="handleScheduleBatch('批量变更时间')">批量变更时间</el-button>
|
||||
<el-button type="primary" size="small" @click="handleScheduleBatch('批量平移时间')">批量平移时间</el-button>
|
||||
<el-button type="primary" size="small" @click="handleScheduleBatch('批量变更授课教员')">批量变更授课教员</el-button>
|
||||
<el-button type="primary" size="small" @click="handleScheduleBatch('批量变更授课场地')">批量变更授课场地</el-button>
|
||||
<el-button type="primary" size="small" @click="handleExport('班次课程课时汇总')">班次课程课时汇总另存</el-button>
|
||||
<el-button type="primary" size="small" @click="handleExport('教学实施计划概要')">教学实施计划概要另存</el-button>
|
||||
<el-button type="primary" size="small" @click="handleExport('教学实施计划')">教学实施计划另存</el-button>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button type="danger" size="small" @click="handleScheduleBatchDelete">批量删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table v-loading="scheduleLoading" :data="schedulePagedData" border stripe class="main-table" @selection-change="handleScheduleSelectionChange">
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="time" label="上课时间" width="150" align="center" />
|
||||
<el-table-column prop="course" label="课程" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="deptUnit" label="责任单位" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="teamCategory" label="队别" width="90" align="center" />
|
||||
<el-table-column prop="teamClass" label="班次" show-overflow-tooltip />
|
||||
<el-table-column prop="grade" label="年级" width="90" align="center" />
|
||||
<el-table-column prop="major" label="专业" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="teacher" label="教员" width="80" align="center" />
|
||||
<el-table-column prop="countPlace" label="人数/场地" width="110" align="center" />
|
||||
<el-table-column prop="contentMethod" label="教学内容方法" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="keyPoints" label="教学要点" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="guarantee" label="保障明细" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="remark" label="备注" width="90" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<div class="pagination-wrap">
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="scheduleData.length"
|
||||
:page-size="schedulePageSize"
|
||||
:current-page="scheduleCurrentPage"
|
||||
@current-change="handleSchedulePageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- ==================== Tab2:课程检索 ==================== -->
|
||||
<el-tab-pane label="课程检索" name="search">
|
||||
<div v-if="statusTip" class="status-tip">{{ statusTip }}</div>
|
||||
<div class="big-title">2026年秋季学期-课程检索</div>
|
||||
|
||||
<div class="export-bar">
|
||||
<el-button type="primary" @click="handleExport('另存Excel(成绩五级制)')">另存Excel(成绩五级制)</el-button>
|
||||
<el-button type="primary" @click="handleExport('另存Excel(成绩四级制)')">另存Excel(成绩四级制)</el-button>
|
||||
<el-button type="primary" @click="handleExport('课程学员名单')">课程学员名单</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="courseSearchForm" label-width="130px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<!-- 左栏 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.deptEnabled">责任教研室</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.dept" class="w-full" :disabled="!courseSearchForm.deptEnabled">
|
||||
<el-option v-for="item in deptOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.courseTypeEnabled">课类型</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.courseType" class="w-full" :disabled="!courseSearchForm.courseTypeEnabled">
|
||||
<el-option v-for="item in courseTypeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="培训层次">
|
||||
<el-select v-model="courseSearchForm.trainLevel" placeholder="请选择" clearable class="w-full">
|
||||
<el-option v-for="item in trainLevelOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.teamEnabled">队别(班次)</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.team" class="w-full" :disabled="!courseSearchForm.teamEnabled">
|
||||
<el-option v-for="item in teamOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学分">
|
||||
<div class="range-control">
|
||||
<el-input v-model="courseSearchForm.creditMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="courseSearchForm.creditMax" placeholder="0" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="计划学时">
|
||||
<div class="range-control">
|
||||
<el-input v-model="courseSearchForm.planHoursMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="courseSearchForm.planHoursMax" placeholder="0" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.arrangeStatusEnabled">考核安排状态</el-checkbox>
|
||||
</template>
|
||||
<el-radio-group v-model="courseSearchForm.arrangeStatus" :disabled="!courseSearchForm.arrangeStatusEnabled">
|
||||
<el-radio :label="'已安排'">已安排</el-radio>
|
||||
<el-radio :label="'未安排'">未安排</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="教员">
|
||||
<el-input v-model="courseSearchForm.teacher" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="队别班次">
|
||||
<el-input v-model="courseSearchForm.teamClass" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.scoreStatusEnabled">成绩录入状态</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.scoreStatus" class="w-full" :disabled="!courseSearchForm.scoreStatusEnabled">
|
||||
<el-option v-for="item in scoreStatusOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="形成性成绩比例">
|
||||
<div class="range-control">
|
||||
<el-input v-model="courseSearchForm.formaScoreMin" placeholder="0" />
|
||||
<span class="range-suffix">%</span>
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="courseSearchForm.formaScoreMax" placeholder="0" />
|
||||
<span class="range-suffix">%</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.implTeacherEnabled">实施教员</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.implTeacher" class="w-full" :disabled="!courseSearchForm.implTeacherEnabled">
|
||||
<el-option v-for="item in implTeacherOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.courseSubjectEnabled">课程科目</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.courseSubject" class="w-full" :disabled="!courseSearchForm.courseSubjectEnabled">
|
||||
<el-option v-for="item in subjectOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="教学楼">
|
||||
<el-select v-model="courseSearchForm.building" class="w-full">
|
||||
<el-option v-for="item in buildingOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.placeEnabled">教学场地</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.place" class="w-full" :disabled="!courseSearchForm.placeEnabled">
|
||||
<el-option v-for="item in placeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.startDateEnabled">开课日期</el-checkbox>
|
||||
</template>
|
||||
<div class="range-control">
|
||||
<el-date-picker v-model="courseSearchForm.startDateStart" type="date" value-format="yyyy-MM-dd" :disabled="!courseSearchForm.startDateEnabled" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-date-picker v-model="courseSearchForm.startDateEnd" type="date" value-format="yyyy-MM-dd" :disabled="!courseSearchForm.startDateEnabled" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.endDateEnabled">结课日期</el-checkbox>
|
||||
</template>
|
||||
<div class="range-control">
|
||||
<el-date-picker v-model="courseSearchForm.endDateStart" type="date" value-format="yyyy-MM-dd" :disabled="!courseSearchForm.endDateEnabled" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-date-picker v-model="courseSearchForm.endDateEnd" type="date" value-format="yyyy-MM-dd" :disabled="!courseSearchForm.endDateEnabled" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.examDateEnabled">考试日期</el-checkbox>
|
||||
</template>
|
||||
<div class="range-control">
|
||||
<el-date-picker v-model="courseSearchForm.examDateStart" type="date" value-format="yyyy-MM-dd" :disabled="!courseSearchForm.examDateEnabled" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-date-picker v-model="courseSearchForm.examDateEnd" type="date" value-format="yyyy-MM-dd" :disabled="!courseSearchForm.examDateEnabled" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="课程科目">
|
||||
<el-input v-model="courseSearchForm.courseSubjectInput" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="教学场地">
|
||||
<el-input v-model="courseSearchForm.placeInput" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.finalStrategyEnabled">终结性成绩策略</el-checkbox>
|
||||
</template>
|
||||
<el-checkbox v-model="courseSearchForm.finalPassEnabled">终结性成绩定及格</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="courseSearchForm.manageOrgEnabled">管理机构</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="courseSearchForm.manageOrg" class="w-full" :disabled="!courseSearchForm.manageOrgEnabled">
|
||||
<el-option v-for="item in manageOrgOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="search-tip">注意:勾选"选择框"表示启用该项对应的查询条件,输入框非空表示启用查询条件。</div>
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleCourseQuery">查询</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="courseLoading" :data="coursePagedData" border stripe class="main-table">
|
||||
<el-table-column type="index" label="序号" width="50" align="center" />
|
||||
<el-table-column label="课程名称/课时系数" width="150" align="center">
|
||||
<template slot="header">
|
||||
<div class="two-line-header">
|
||||
<span>课程名称</span>
|
||||
<span>课时系数</span>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="{ row }">
|
||||
<div class="two-line-cell">
|
||||
<span>{{ row.courseName }}</span>
|
||||
<span>{{ row.coeff }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="teacherTimes" label="责任教员&课次" width="120" align="center" />
|
||||
<el-table-column prop="teamClass" label="班次" show-overflow-tooltip />
|
||||
<el-table-column prop="grade" label="年级" width="90" align="center" />
|
||||
<el-table-column prop="major" label="专业" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="planHours" label="计划学时" width="90" align="center" />
|
||||
<el-table-column prop="runHours" label="运行学时" width="90" align="center" />
|
||||
<el-table-column prop="examType" label="考核类型方式" width="110" align="center" />
|
||||
<el-table-column prop="implTeacher" label="实施教员" width="90" align="center" />
|
||||
<el-table-column prop="countPlace" label="人数/场地" width="110" align="center" />
|
||||
<el-table-column prop="courseLecture" label="课程讲座" width="90" align="center" />
|
||||
<el-table-column prop="planChange" label="实施计划变" width="90" align="center" />
|
||||
</el-table>
|
||||
<div class="pagination-wrap">
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="courseData.length"
|
||||
:page-size="coursePageSize"
|
||||
:current-page="courseCurrentPage"
|
||||
@current-change="handleCoursePageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AssessmentIndex',
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'schedule',
|
||||
|
||||
// ==================== 下拉选项(两页共用) ====================
|
||||
deptOptions: ['教务处', '政治工作教研室', '军事基础教研室', '装备保障教研室'],
|
||||
trainLevelOptions: ['本科', '研究生', '大专'],
|
||||
buildingOptions: ['校内', '教学楼A', '教学楼B'],
|
||||
placeOptions: ['操场', '教室101', '实验室203'],
|
||||
subjectOptions: ['英语(补课)', '高等数学', '军事理论', '战术基础'],
|
||||
teamOptions: ['2025级炮兵装备运用(线膛炮)专业学员54队5区队', '2024级学员32队', '研究生1队'],
|
||||
manageOrgOptions: ['教务处', '教务科', '教研室'],
|
||||
|
||||
// Tab1 专属选项
|
||||
semesterOptions: ['2026年春季学期', '2026年秋季学期', '2025年秋季学期'],
|
||||
weekOptions: ['第20周2026-07-06', '第19周2026-06-29', '第21周2026-07-13'],
|
||||
resourceTypeOptions: ['弹药', '器材', '场地'],
|
||||
periodOptions: ['1-2', '3-4', '5-6', '7-8'],
|
||||
invigilatorOptions: ['教务处', '张三', '李四', '王五'],
|
||||
teamCategoryOptions: ['学员大队', '学员一队', '学员二队'],
|
||||
resourceOptions: ['92式手榴弹', '模拟器材', '靶场'],
|
||||
|
||||
// Tab2 专属选项
|
||||
courseTypeOptions: ['讲座', '讲授', '研讨', '实操'],
|
||||
scoreStatusOptions: ['未填写', '已填写'],
|
||||
implTeacherOptions: ['教务处', '张三', '李四', '王五', '赵六'],
|
||||
|
||||
// ==================== Tab1 查询条件 ====================
|
||||
scheduleSearchForm: {
|
||||
examDateEnabled: true,
|
||||
examDateFrom: '2026-07-06',
|
||||
examDateTo: '2026-07-12',
|
||||
semester: '2026年春季学期',
|
||||
week: '第20周2026-07-06',
|
||||
deptEnabled: false,
|
||||
dept: '教务处',
|
||||
buildingEnabled: true,
|
||||
building: '校内',
|
||||
trainLevel: '',
|
||||
deptSystemEnabled: false,
|
||||
deptSystem: '教务处',
|
||||
resourceTypeEnabled: false,
|
||||
resourceType: '弹药',
|
||||
periodEnabled: false,
|
||||
period: '1-2',
|
||||
combineEnabled: false,
|
||||
combineChange: false,
|
||||
majorName: '',
|
||||
invigilatorName: '',
|
||||
examPlaceName: '',
|
||||
invigilatorEnabled: false,
|
||||
invigilator: '教务处',
|
||||
examSubjectEnabled: false,
|
||||
examSubject: '英语(补课)',
|
||||
placeEnabled: false,
|
||||
place: '操场',
|
||||
teamEnabled: false,
|
||||
team: '',
|
||||
showElective: true,
|
||||
teamCategoryEnabled: false,
|
||||
teamCategory: '学员大队',
|
||||
resourceEnabled: false,
|
||||
resource: '92式手榴弹',
|
||||
manageOrgEnabled: false,
|
||||
manageOrg: '教务处',
|
||||
logOptionEnabled: false,
|
||||
logOption: '未填写',
|
||||
gradeInput: '',
|
||||
teamClassName: '',
|
||||
subjectName: ''
|
||||
},
|
||||
|
||||
// ==================== Tab2 查询条件 ====================
|
||||
statusTip: '',
|
||||
courseSearchForm: {
|
||||
deptEnabled: false,
|
||||
dept: '教务处',
|
||||
courseTypeEnabled: false,
|
||||
courseType: '讲座',
|
||||
trainLevel: '',
|
||||
teamEnabled: false,
|
||||
team: '2025级炮兵装备运用(线膛炮)专业学员54队5区队',
|
||||
creditMin: '',
|
||||
creditMax: '',
|
||||
planHoursMin: '',
|
||||
planHoursMax: '',
|
||||
arrangeStatusEnabled: true,
|
||||
arrangeStatus: '已安排',
|
||||
teacher: '',
|
||||
teamClass: '',
|
||||
scoreStatusEnabled: false,
|
||||
scoreStatus: '未填写',
|
||||
formaScoreMin: '',
|
||||
formaScoreMax: '',
|
||||
implTeacherEnabled: false,
|
||||
implTeacher: '教务处',
|
||||
courseSubjectEnabled: false,
|
||||
courseSubject: '英语(补课)',
|
||||
building: '校内',
|
||||
placeEnabled: false,
|
||||
place: '操场',
|
||||
startDateEnabled: false,
|
||||
startDateStart: '2026-08-21',
|
||||
startDateEnd: '2027-01-23',
|
||||
endDateEnabled: false,
|
||||
endDateStart: '2026-08-21',
|
||||
endDateEnd: '2027-01-23',
|
||||
examDateEnabled: false,
|
||||
examDateStart: '2026-08-21',
|
||||
examDateEnd: '2027-01-23',
|
||||
courseSubjectInput: '',
|
||||
placeInput: '',
|
||||
finalStrategyEnabled: false,
|
||||
finalPassEnabled: false,
|
||||
manageOrgEnabled: false,
|
||||
manageOrg: '教务处'
|
||||
},
|
||||
|
||||
// ==================== Tab1 表格数据(mock) ====================
|
||||
scheduleLoading: false,
|
||||
scheduleData: [
|
||||
{ id: 1, time: '2026-07-06 08:00-09:40', course: '高等数学', deptUnit: '教务处', teamCategory: '学员大队', teamClass: '2025级本科1班', grade: '2025级', major: '数学', teacher: '张三', countPlace: '45/教室101', contentMethod: '理论讲授', keyPoints: '微积分基础', guarantee: '无', remark: '第1次课' },
|
||||
{ id: 2, time: '2026-07-06 10:00-11:40', course: '军事理论', deptUnit: '政治工作教研室', teamCategory: '学员大队', teamClass: '2024级本科2班', grade: '2024级', major: '军事', teacher: '李四', countPlace: '38/教室203', contentMethod: '案例教学', keyPoints: '战争理论', guarantee: '多媒体', remark: '' },
|
||||
{ id: 3, time: '2026-07-07 14:30-16:10', course: '英语(补课)', deptUnit: '军事基础教研室', teamCategory: '学员一队', teamClass: '研究生1班', grade: '2026级', major: '英语', teacher: '王五', countPlace: '30/教室102', contentMethod: '研讨教学', keyPoints: '口语训练', guarantee: '无', remark: '补课' },
|
||||
{ id: 4, time: '2026-07-07 08:00-09:40', course: '战术基础', deptUnit: '教务处', teamCategory: '学员大队', teamClass: '2023级本科3班', grade: '2023级', major: '战术', teacher: '赵六', countPlace: '50/操场', contentMethod: '实操演练', keyPoints: '战术动作', guarantee: '器材', remark: '' },
|
||||
{ id: 5, time: '2026-07-08 10:00-11:40', course: '装备保障', deptUnit: '装备保障教研室', teamCategory: '学员二队', teamClass: '研究生2班', grade: '2026级', major: '装备', teacher: '孙七', countPlace: '20/实验室203', contentMethod: '实践教学', keyPoints: '装备维护', guarantee: '模拟器材', remark: '分组' },
|
||||
{ id: 6, time: '2026-07-08 14:30-16:10', course: '联合作战指挥', deptUnit: '教务处', teamCategory: '学员大队', teamClass: '2025级本科1班', grade: '2025级', major: '指挥', teacher: '李四', countPlace: '45/教室B301', contentMethod: '案例教学', keyPoints: '联合作战', guarantee: '多媒体', remark: '' },
|
||||
{ id: 7, time: '2026-07-09 08:00-09:40', course: '大学英语', deptUnit: '军事基础教研室', teamCategory: '学员一队', teamClass: '2024级本科2班', grade: '2024级', major: '英语', teacher: '王五', countPlace: '38/教室105', contentMethod: '理论讲授', keyPoints: '语法', guarantee: '无', remark: '' },
|
||||
{ id: 8, time: '2026-07-09 10:00-11:40', course: '政治理论', deptUnit: '政治工作教研室', teamCategory: '学员大队', teamClass: '研究生1班', grade: '2026级', major: '政治', teacher: '张三', countPlace: '30/教室204', contentMethod: '理论讲授', keyPoints: '形势政策', guarantee: '无', remark: '' },
|
||||
{ id: 9, time: '2026-07-10 14:30-16:10', course: '装备操作', deptUnit: '装备保障教研室', teamCategory: '学员二队', teamClass: '2023级本科3班', grade: '2023级', major: '装备', teacher: '赵六', countPlace: '45/实验室101', contentMethod: '实操演练', keyPoints: '操作规范', guarantee: '器材', remark: '安全注意' },
|
||||
{ id: 10, time: '2026-07-10 16:20-18:00', course: '军事地形学', deptUnit: '教务处', teamCategory: '学员大队', teamClass: '2025级本科1班', grade: '2025级', major: '地形', teacher: '孙七', countPlace: '50/操场', contentMethod: '实操演练', keyPoints: '地形判读', guarantee: '地图', remark: '' }
|
||||
],
|
||||
selectedRows: [],
|
||||
scheduleCurrentPage: 1,
|
||||
schedulePageSize: 20,
|
||||
|
||||
// ==================== Tab2 表格数据(mock) ====================
|
||||
courseLoading: false,
|
||||
courseData: [
|
||||
{ id: 1, courseName: '高等数学', coeff: '1.0', teacherTimes: '张三×48', teamClass: '2025级炮兵装备运用(线膛炮)专业学员54队5区队', grade: '2025级', major: '炮兵装备运用', planHours: 96, runHours: 96, examType: '闭卷考试', implTeacher: '张三', countPlace: '45/教室101', courseLecture: '讲座', planChange: '否' },
|
||||
{ id: 2, courseName: '军事理论', coeff: '1.2', teacherTimes: '李四×32', teamClass: '2024级学员32队', grade: '2024级', major: '军事指挥', planHours: 64, runHours: 62, examType: '开卷考试', implTeacher: '李四', countPlace: '38/教室203', courseLecture: '讲授', planChange: '是' },
|
||||
{ id: 3, courseName: '英语(补课)', coeff: '0.8', teacherTimes: '王五×40', teamClass: '研究生1队', grade: '2026级', major: '英语', planHours: 80, runHours: 78, examType: '口语测试', implTeacher: '王五', countPlace: '30/教室102', courseLecture: '讲座', planChange: '否' },
|
||||
{ id: 4, courseName: '战术基础', coeff: '1.0', teacherTimes: '赵六×56', teamClass: '2023级学员51队', grade: '2023级', major: '战术指挥', planHours: 112, runHours: 110, examType: '实操考核', implTeacher: '赵六', countPlace: '50/操场', courseLecture: '实操', planChange: '是' },
|
||||
{ id: 5, courseName: '装备保障', coeff: '1.1', teacherTimes: '张三×24', teamClass: '研究生2队', grade: '2026级', major: '装备保障', planHours: 48, runHours: 48, examType: '闭卷考试', implTeacher: '孙七', countPlace: '20/实验室203', courseLecture: '讲授', planChange: '否' },
|
||||
{ id: 6, courseName: '联合作战指挥', coeff: '1.3', teacherTimes: '李四×60', teamClass: '2025级炮兵装备运用(线膛炮)专业学员54队5区队', grade: '2025级', major: '联合作战', planHours: 120, runHours: 118, examType: '综合考核', implTeacher: '李四', countPlace: '45/教室B301', courseLecture: '讲座', planChange: '是' },
|
||||
{ id: 7, courseName: '大学英语', coeff: '0.8', teacherTimes: '王五×36', teamClass: '2024级学员32队', grade: '2024级', major: '英语', planHours: 72, runHours: 72, examType: '四级制考试', implTeacher: '王五', countPlace: '38/教室105', courseLecture: '讲授', planChange: '否' },
|
||||
{ id: 8, courseName: '军事地形学', coeff: '1.0', teacherTimes: '赵六×40', teamClass: '2023级学员51队', grade: '2023级', major: '军事指挥', planHours: 80, runHours: 76, examType: '实操考核', implTeacher: '赵六', countPlace: '50/操场', courseLecture: '实操', planChange: '是' },
|
||||
{ id: 9, courseName: '政治理论', coeff: '1.0', teacherTimes: '张三×48', teamClass: '研究生1队', grade: '2026级', major: '政治学', planHours: 96, runHours: 96, examType: '开卷考试', implTeacher: '孙七', countPlace: '30/教室204', courseLecture: '讲座', planChange: '否' },
|
||||
{ id: 10, courseName: '装备操作', coeff: '1.2', teacherTimes: '李四×32', teamClass: '2025级炮兵装备运用(线膛炮)专业学员54队5区队', grade: '2025级', major: '炮兵装备运用', planHours: 64, runHours: 62, examType: '实操考核', implTeacher: '李四', countPlace: '45/实验室101', courseLecture: '实操', planChange: '是' }
|
||||
],
|
||||
courseCurrentPage: 1,
|
||||
coursePageSize: 20
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
schedulePagedData() {
|
||||
const start = (this.scheduleCurrentPage - 1) * this.schedulePageSize
|
||||
return this.scheduleData.slice(start, start + this.schedulePageSize)
|
||||
},
|
||||
coursePagedData() {
|
||||
const start = (this.courseCurrentPage - 1) * this.coursePageSize
|
||||
return this.courseData.slice(start, start + this.coursePageSize)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// ==================== Tab1 查询 ====================
|
||||
// TODO: 后端接口未提供,以下操作均为前端模拟;接口就绪后替换为对应接口
|
||||
handleScheduleQuery() {
|
||||
this.$message.success('查询完成(前端模拟)')
|
||||
},
|
||||
|
||||
/** 学期/周次「确定」快速填充日期范围 */
|
||||
handleQuickDate(type) {
|
||||
if (type === 'semester') {
|
||||
this.$message.success(`已按「${this.scheduleSearchForm.semester}」确定考核日期范围(前端模拟)`)
|
||||
} else {
|
||||
this.$message.success(`已按「${this.scheduleSearchForm.week}」确定考核日期范围(前端模拟)`)
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 导出按钮 ====================
|
||||
handleExport(type) {
|
||||
this.$message.success(`已导出 ${type}(前端模拟)`)
|
||||
},
|
||||
|
||||
// ==================== Tab1 多选与批量操作 ====================
|
||||
handleScheduleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
|
||||
handleScheduleBatch(action) {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择记录')
|
||||
return
|
||||
}
|
||||
this.$message.success(`已对所选 ${this.selectedRows.length} 条记录执行「${action}」(前端模拟)`)
|
||||
},
|
||||
|
||||
handleScheduleBatchDelete() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择要删除的记录')
|
||||
return
|
||||
}
|
||||
const ids = this.selectedRows.map((r) => r.id)
|
||||
this.scheduleData = this.scheduleData.filter((r) => ids.indexOf(r.id) === -1)
|
||||
this.$message.success(`已删除所选 ${ids.length} 条记录(前端模拟)`)
|
||||
},
|
||||
|
||||
handleSchedulePageChange(page) {
|
||||
this.scheduleCurrentPage = page
|
||||
},
|
||||
|
||||
// ==================== Tab2 查询 ====================
|
||||
handleCourseQuery() {
|
||||
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')
|
||||
const count = this.courseData.length
|
||||
this.statusTip = `[${hh}:${mm}:${ss}]查询成功! 共检索到${count}条记录。`
|
||||
this.$message.success(`查询成功,共检索到${count}条记录(前端模拟)`)
|
||||
},
|
||||
|
||||
handleCoursePageChange(page) {
|
||||
this.courseCurrentPage = page
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.assessment-page {
|
||||
.assessment-tabs {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
// ==================== 查询条件区域 ====================
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.date-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.quick-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.quick-select {
|
||||
width: 170px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.team-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.el-select {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.elective-check {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.range-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.el-date-editor {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.range-sep,
|
||||
.range-suffix {
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Tab2 顶部提示 / 标题 / 导出 ====================
|
||||
.status-tip {
|
||||
display: inline-block;
|
||||
background: #dc3545;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.big-title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #303133;
|
||||
margin: 8px 0 12px;
|
||||
}
|
||||
|
||||
.export-bar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
// ==================== 数据表格区域 ====================
|
||||
.table-card {
|
||||
.table-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
.action-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-table {
|
||||
::v-deep(.cell) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.two-line-header,
|
||||
.two-line-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.pagination-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,47 +4,35 @@
|
||||
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<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 :model="searchForm" label-width="40px" class="search-form">
|
||||
<el-row :gutter="6">
|
||||
<el-col :span="4">
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="searchForm.mc" placeholder="请输入名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="年度">
|
||||
<el-input v-model="searchForm.nd" placeholder="如 2026" clearable />
|
||||
<el-input v-model="searchForm.mc" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教员编号">
|
||||
<el-input v-model="searchForm.jybh" placeholder="如 JY00128" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="合班类型">
|
||||
<el-select v-model="searchForm.hflx" placeholder="请选择" clearable class="w-full">
|
||||
<el-option v-for="item in hflxOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-col :span="2">
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 文件操作区域 ==================== -->
|
||||
<!-- ==================== 2. 操作区域 ==================== -->
|
||||
<el-card shadow="never" class="upload-card">
|
||||
<div class="upload-row">
|
||||
<div class="upload-left">
|
||||
<el-button type="primary" @click="handleDownloadTemplate">【联教联训数据文件模板】下载</el-button>
|
||||
<el-button type="primary" plain @click="handleChooseFile">选择文件</el-button>
|
||||
<el-button type="primary" @click="handleAdd">新增联教联训</el-button>
|
||||
<el-button type="primary" plain @click="handleExport">导出 Excel</el-button>
|
||||
<el-button @click="handleDownloadTemplate">【联教联训数据文件模板】下载</el-button>
|
||||
<el-button plain @click="handleChooseFile">选择文件</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>
|
||||
<input ref="fileInputRef" type="file" accept=".xls,.xlsx" style="display: none" @change="handleFileChange" />
|
||||
<el-button type="success" :loading="uploading" @click="handleUpload">上传数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-tip">您还没建立 联教联训证明。</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 数据表格 ==================== -->
|
||||
@@ -52,20 +40,25 @@
|
||||
<div class="table-title">联教联训记录列表</div>
|
||||
<el-table v-loading="tableLoading" :data="tableData" border stripe style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="bh" label="任务编号" width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="mc" label="名称" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="jybh" label="教员编号" width="100" align="center" />
|
||||
<el-table-column prop="rwlb" label="任务类别" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="ksl" label="课时量" width="80" align="center" />
|
||||
<el-table-column label="合班类型" width="90" align="center">
|
||||
<template slot-scope="{ row }">{{ formatHflx(row.hflx) }}</template>
|
||||
<el-table-column prop="bh" label="编号" width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="mc" label="名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="xz" label="性质" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="yj" label="依据" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="ksrq" label="开始日期" width="110" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="jsrq" label="结束日期" width="110" align="center" :formatter="fmtDateTime" />
|
||||
<el-table-column prop="ts" label="天数" width="70" align="center" />
|
||||
<el-table-column prop="jbksl" label="基本课时量" width="90" align="center" />
|
||||
<el-table-column prop="kslx" label="课时类型" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xmlx" label="项目类型" width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="sm" label="说明" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="bz" label="备注" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="160" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">修改</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否评优" width="90" align="center">
|
||||
<template slot-scope="{ row }">{{ formatSfpy(row.sfpy) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="nd" label="年度" width="80" align="center" />
|
||||
<el-table-column prop="xq" label="学期" width="110" align="center" />
|
||||
<el-table-column prop="sm" label="说明" min-width="180" show-overflow-tooltip />
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
@@ -80,67 +73,122 @@
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 4. 新增联教联训记录区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<div class="form-title">新增联教联训记录</div>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<!-- ==================== 4. 新增/修改对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="720px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px" class="add-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务编号" prop="bh">
|
||||
<el-input v-model="form.bh" placeholder="如 RW20260810001" clearable />
|
||||
<el-form-item label="编号">
|
||||
<el-input v-model="form.bh" placeholder="留空则自动生成" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="mc">
|
||||
<el-input v-model="form.mc" placeholder="请输入名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="教员编号" prop="jybh">
|
||||
<el-input v-model="form.jybh" placeholder="如 JY00128" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="任务类别" prop="rwlb">
|
||||
<el-input v-model="form.rwlb" placeholder="如 理论授课" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="课时量" prop="ksl">
|
||||
<el-input v-model="form.ksl" placeholder="如 16.5" clearable />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="性质">
|
||||
<el-input v-model="form.xz" placeholder="请输入性质" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="合班类型">
|
||||
<el-radio-group v-model="form.hflx">
|
||||
<el-radio :label="0">未合班</el-radio>
|
||||
<el-radio :label="1">合班</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否评优">
|
||||
<el-radio-group v-model="form.sfpy">
|
||||
<el-radio :label="0">否</el-radio>
|
||||
<el-radio :label="1">是</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-input v-model="form.nd" placeholder="如 2026" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="学期" prop="xq">
|
||||
<el-input v-model="form.xq" placeholder="如 2026-2027-1" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="说明" prop="sm">
|
||||
<el-input v-model="form.sm" type="textarea" :rows="3" placeholder="请输入说明" />
|
||||
<el-form-item label="依据">
|
||||
<el-input v-model="form.yj" placeholder="请输入依据" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" :loading="addLoading" @click="handleAdd">添加</el-button>
|
||||
</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker v-model="form.ksrq" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择开始日期" clearable class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="form.jsrq" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择结束日期" clearable class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="天数">
|
||||
<el-input-number v-model="form.ts" :min="0" :precision="1" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="基本课时量">
|
||||
<el-input-number v-model="form.jbksl" :min="0" :precision="1" :step="0.5" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课时类型">
|
||||
<el-input v-model="form.kslx" placeholder="请输入课时类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目类型">
|
||||
<el-input v-model="form.xmlx" placeholder="请输入项目类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="form.sm" type="textarea" :rows="2" placeholder="请输入说明" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 5. 详情对话框 ==================== -->
|
||||
<el-dialog :visible="detailVisible" title="联教联训详情" width="640px" @update:visible="val => detailVisible = val">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailData.bh }}</el-descriptions-item>
|
||||
<el-descriptions-item label="名称">{{ detailData.mc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性质">{{ fmtEmpty(detailData.xz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="依据">{{ fmtEmpty(detailData.yj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始日期">{{ fmtDateTime(null, null, detailData.ksrq) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束日期">{{ fmtDateTime(null, null, detailData.jsrq) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="天数">{{ fmtValue(detailData.ts) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="基本课时量">{{ fmtValue(detailData.jbksl) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="课时类型">{{ fmtEmpty(detailData.kslx) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="项目类型">{{ fmtEmpty(detailData.xmlx) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="说明" :span="2">{{ fmtEmpty(detailData.sm) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ fmtEmpty(detailData.bz) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div slot="footer">
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 模拟列表数据(后端接口未提供,接口就绪后可删除并改为接口加载)
|
||||
const mockTableData = [
|
||||
{ bh: 'RW20260810001', mc: '某型装备联合训练', jybh: 'JY00128', rwlb: '理论授课', ksl: 16.5, hflx: 1, sfpy: 1, nd: '2026', xq: '2026-2027-1', sm: '' },
|
||||
{ bh: 'RW20260810002', mc: '通信保障联合演练', jybh: 'JY00302', rwlb: '实践教学', ksl: 24, hflx: 0, sfpy: 0, nd: '2026', xq: '2026-2027-1', sm: '跨单位合练' },
|
||||
{ bh: 'RW20260721003', mc: '联合教学研讨', jybh: 'JY00511', rwlb: '教学研究', ksl: 8, hflx: 1, sfpy: 1, nd: '2025', xq: '2025-2026-2', sm: '' }
|
||||
]
|
||||
import { saveAs } from 'file-saver'
|
||||
import {
|
||||
listJointTraining,
|
||||
addJointTraining,
|
||||
updateJointTraining,
|
||||
deleteJointTraining,
|
||||
getJointTraining,
|
||||
importJointTraining,
|
||||
exportJointTraining
|
||||
} from '@/api/classHour/jointTraining'
|
||||
|
||||
export default {
|
||||
name: 'JointTrainingIndex',
|
||||
@@ -148,49 +196,32 @@ export default {
|
||||
return {
|
||||
// ==================== 1. 查询条件 ====================
|
||||
searchForm: {
|
||||
mc: '',
|
||||
jybh: '',
|
||||
nd: '',
|
||||
hflx: ''
|
||||
mc: ''
|
||||
},
|
||||
hflxOptions: [
|
||||
{ label: '未合班', value: '0' },
|
||||
{ label: '合班', value: '1' }
|
||||
],
|
||||
|
||||
// ==================== 2. 文件操作 ====================
|
||||
selectedFile: null,
|
||||
uploading: false,
|
||||
|
||||
// ==================== 3. 表格数据 ====================
|
||||
tableLoading: false,
|
||||
tableData: [],
|
||||
allData: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
|
||||
// ==================== 4. 新增联教联训记录表单 ====================
|
||||
form: {
|
||||
bh: this.genBh(),
|
||||
mc: '',
|
||||
jybh: '',
|
||||
rwlb: '',
|
||||
ksl: '',
|
||||
hflx: 0,
|
||||
sfpy: 0,
|
||||
nd: '2026',
|
||||
xq: '2026-2027-1',
|
||||
sm: ''
|
||||
},
|
||||
// ==================== 4. 新增/修改表单 ====================
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新增联教联训',
|
||||
saving: false,
|
||||
form: this.createEmptyForm(),
|
||||
rules: {
|
||||
bh: [{ required: true, message: '请输入任务编号', trigger: 'blur' }],
|
||||
mc: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||||
jybh: [{ required: true, message: '请输入教员编号', trigger: 'blur' }],
|
||||
rwlb: [{ required: true, message: '请输入任务类别', trigger: 'blur' }],
|
||||
ksl: [{ required: true, message: '请输入课时量', trigger: 'blur' }],
|
||||
nd: [{ required: true, message: '请输入年度', trigger: 'blur' }]
|
||||
mc: [{ required: true, message: '请输入名称', trigger: 'blur' }]
|
||||
},
|
||||
addLoading: false
|
||||
|
||||
// ==================== 5. 详情 ====================
|
||||
detailVisible: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -199,73 +230,177 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handleQuery()
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
/** 生成任务编号(RW+日期+序号) */
|
||||
genBh() {
|
||||
const d = new Date()
|
||||
const ymd = '' + d.getFullYear() + (d.getMonth() + 1 < 10 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1) + (d.getDate() < 10 ? '0' + d.getDate() : d.getDate())
|
||||
const seq = String(Math.floor(Math.random() * 900) + 100)
|
||||
return `RW${ymd}${seq}`
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
mc: '',
|
||||
xz: '',
|
||||
yj: '',
|
||||
ksrq: '',
|
||||
jsrq: '',
|
||||
ts: null,
|
||||
jbksl: null,
|
||||
kslx: '',
|
||||
xmlx: '',
|
||||
sm: '',
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
|
||||
/** 把后端 LocalDateTime(含 T/毫秒)规范为表单可回显的格式 */
|
||||
normalizeDateTime(val) {
|
||||
if (!val) return ''
|
||||
return String(val).replace('T', ' ').replace(/\.\d+$/, '').slice(0, 19)
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getJointTrainingList
|
||||
handleQuery() {
|
||||
fetchList() {
|
||||
this.tableLoading = true
|
||||
setTimeout(() => {
|
||||
let records = mockTableData.slice()
|
||||
if (this.searchForm.mc.trim()) {
|
||||
records = records.filter((item) => (item.mc || '').includes(this.searchForm.mc.trim()))
|
||||
}
|
||||
if (this.searchForm.jybh.trim()) {
|
||||
records = records.filter((item) => (item.jybh || '').includes(this.searchForm.jybh.trim()))
|
||||
}
|
||||
if (this.searchForm.nd.trim()) {
|
||||
records = records.filter((item) => String(item.nd || '').includes(this.searchForm.nd.trim()))
|
||||
}
|
||||
if (this.searchForm.hflx !== '') {
|
||||
records = records.filter((item) => String(item.hflx) === this.searchForm.hflx)
|
||||
}
|
||||
this.allData = records
|
||||
this.total = records.length
|
||||
this.pageNum = 1
|
||||
this.applyPage()
|
||||
this.$message.success(`查询完成,共 ${records.length} 条记录(前端模拟)`)
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
if (this.searchForm.mc && this.searchForm.mc.trim()) params.mc = this.searchForm.mc.trim()
|
||||
listJointTraining(params).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.tableLoading = false
|
||||
}, 200)
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.tableLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
applyPage() {
|
||||
const start = (this.pageNum - 1) * this.pageSize
|
||||
this.tableData = this.allData.slice(start, start + this.pageSize)
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.applyPage()
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.applyPage()
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/** 合班类型显示 */
|
||||
formatHflx(val) {
|
||||
if (val === undefined || val === null || val === '') return '-'
|
||||
return String(val) === '1' ? '合班' : '未合班'
|
||||
/** 日期时间显示(去掉 T、截断到分钟) */
|
||||
fmtDateTime(row, column, cellValue) {
|
||||
if (cellValue === null || cellValue === undefined || cellValue === '') return '-'
|
||||
return String(cellValue).replace('T', ' ').slice(0, 16)
|
||||
},
|
||||
|
||||
/** 是否评优显示 */
|
||||
formatSfpy(val) {
|
||||
if (val === undefined || val === null || val === '') return '-'
|
||||
return String(val) === '1' ? '是' : '否'
|
||||
/** 空值显示为 '-' */
|
||||
fmtEmpty(val) {
|
||||
return val === null || val === undefined || val === '' ? '-' : val
|
||||
},
|
||||
|
||||
// ==================== 2. 文件操作 ====================
|
||||
/** 数值空值显示为 '-'(保留 0) */
|
||||
fmtValue(val) {
|
||||
return val === null || val === undefined ? '-' : val
|
||||
},
|
||||
|
||||
// ==================== 新增 / 修改 ====================
|
||||
handleAdd() {
|
||||
this.form = this.createEmptyForm()
|
||||
this.dialogTitle = '新增联教联训'
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
getJointTraining(row.bh).then(res => {
|
||||
const d = (res && res.data) || {}
|
||||
this.form = {
|
||||
bh: d.bh || '',
|
||||
mc: d.mc || '',
|
||||
xz: d.xz || '',
|
||||
yj: d.yj || '',
|
||||
ksrq: this.normalizeDateTime(d.ksrq),
|
||||
jsrq: this.normalizeDateTime(d.jsrq),
|
||||
ts: d.ts === null || d.ts === undefined ? null : d.ts,
|
||||
jbksl: d.jbksl === null || d.jbksl === undefined ? null : d.jbksl,
|
||||
kslx: d.kslx || '',
|
||||
xmlx: d.xmlx || '',
|
||||
sm: d.sm || '',
|
||||
bz: d.bz || ''
|
||||
}
|
||||
this.dialogTitle = '修改联教联训'
|
||||
this.dialogVisible = true
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
const payload = this.buildPayload()
|
||||
this.saving = true
|
||||
const req = payload.bh ? updateJointTraining(payload) : addJointTraining(payload)
|
||||
req.then(() => {
|
||||
this.$message.success(this.dialogTitle === '修改联教联训' ? '修改成功' : '新增成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/** 构建请求体,仅含实体非空字段(创建/修改时间为后端自动维护,不传) */
|
||||
buildPayload() {
|
||||
const f = this.form
|
||||
const payload = {}
|
||||
if (f.bh && f.bh.trim()) payload.bh = f.bh.trim()
|
||||
if (f.mc && f.mc.trim()) payload.mc = f.mc.trim()
|
||||
if (f.xz && f.xz.trim()) payload.xz = f.xz.trim()
|
||||
if (f.yj && f.yj.trim()) payload.yj = f.yj.trim()
|
||||
if (f.ksrq) payload.ksrq = f.ksrq
|
||||
if (f.jsrq) payload.jsrq = f.jsrq
|
||||
if (f.ts !== null && f.ts !== undefined) payload.ts = f.ts
|
||||
if (f.jbksl !== null && f.jbksl !== undefined) payload.jbksl = f.jbksl
|
||||
if (f.kslx && f.kslx.trim()) payload.kslx = f.kslx.trim()
|
||||
if (f.xmlx && f.xmlx.trim()) payload.xmlx = f.xmlx.trim()
|
||||
if (f.sm && f.sm.trim()) payload.sm = f.sm.trim()
|
||||
if (f.bz && f.bz.trim()) payload.bz = f.bz.trim()
|
||||
return payload
|
||||
},
|
||||
|
||||
// ==================== 删除 ====================
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除「${row.mc || row.bh || '该记录'}」吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => deleteJointTraining(row.bh)).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 详情 ====================
|
||||
handleDetail(row) {
|
||||
getJointTraining(row.bh).then(res => {
|
||||
this.detailData = (res && res.data) || {}
|
||||
this.detailVisible = true
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 导出 ====================
|
||||
handleExport() {
|
||||
exportJointTraining().then(blob => {
|
||||
saveAs(blob, '联教联训管理.xlsx')
|
||||
this.$message.success('导出成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 文件选择与导入 ====================
|
||||
handleChooseFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
@@ -275,48 +410,31 @@ export default {
|
||||
this.selectedFile = (input.files && input.files[0]) || null
|
||||
},
|
||||
|
||||
/** 下载模板(生成 CSV 模板文件,字段对齐后端接口) */
|
||||
handleDownloadTemplate() {
|
||||
const csvContent = '\uFEFF' + '任务编号,名称,教员编号,任务类别,课时量,合班类型,是否评优,年度,学期,说明\n'
|
||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = '联教联训数据文件模板.csv'
|
||||
link.click()
|
||||
URL.revokeObjectURL(link.href)
|
||||
this.$message.success('已下载联教联训数据文件模板')
|
||||
},
|
||||
|
||||
// TODO: 后端接口未提供,上传为前端模拟;接口就绪后替换为 /log/joint-training/import-excel
|
||||
handleUpload() {
|
||||
if (!this.selectedFile) {
|
||||
this.$message.warning('请先选择文件')
|
||||
return
|
||||
}
|
||||
this.$message.success(`文件「${this.selectedFile.name}」上传成功(前端模拟)`)
|
||||
this.selectedFile = null
|
||||
this.handleQuery()
|
||||
this.uploading = true
|
||||
importJointTraining(this.selectedFile).then(res => {
|
||||
const count = res && res.data
|
||||
if (count !== null && count !== undefined) {
|
||||
this.$message.success(`导入成功,共 ${count} 条记录`)
|
||||
} else {
|
||||
this.$message.success((res && res.msg) || '导入成功')
|
||||
}
|
||||
this.selectedFile = null
|
||||
this.$refs.fileInputRef && (this.$refs.fileInputRef.value = '')
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.uploading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 4. 添加 ====================
|
||||
// TODO: 后端接口未提供,提交为前端模拟;接口就绪后替换为 addJointTraining
|
||||
handleAdd() {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
this.addLoading = true
|
||||
setTimeout(() => {
|
||||
this.$message.success('添加成功(前端模拟)')
|
||||
Object.assign(this.form, {
|
||||
bh: this.genBh(), mc: '', jybh: '', rwlb: '', ksl: '',
|
||||
hflx: 0, sfpy: 0, nd: '2026', xq: '2026-2027-1', sm: ''
|
||||
})
|
||||
this.handleQuery()
|
||||
this.addLoading = false
|
||||
}, 300)
|
||||
})
|
||||
handleDownloadTemplate() {
|
||||
// 后端暂未提供模板下载接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,30 +465,19 @@ export default {
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 文件操作区域 ====================
|
||||
// ==================== 2. 操作区域 ====================
|
||||
.upload-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.upload-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
@@ -390,12 +497,6 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 3. 数据表格 ====================
|
||||
@@ -414,6 +515,17 @@ export default {
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 4. 新增/修改表单 ====================
|
||||
.add-form {
|
||||
max-height: 62vh;
|
||||
overflow-y: auto;
|
||||
padding-right: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,15 +1,679 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<placeholder-page title="方案管理" icon="documentation"
|
||||
description="用于维护课时的各类方案信息,如教学方案的配置、启用与调整,支持查询与维护。" />
|
||||
<div class="app-container plan-page">
|
||||
|
||||
<!-- ==================== Tab 切换 ==================== -->
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="课时费方案" name="fee" />
|
||||
<el-tab-pane label="课时方案" name="coeff" />
|
||||
</el-tabs>
|
||||
|
||||
<!-- ==================== 1. 查询与新增 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :inline="true" class="search-form" @submit.native.prevent>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="currentForm.mc" placeholder="请输入名称" clearable style="width: 220px" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button type="primary" plain @click="handleAdd">新增{{ currentTitle }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 数据表格 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<!-- 课时费方案 -->
|
||||
<el-table v-if="activeTab === 'fee'" v-loading="feeState.loading" :data="feeState.list" border stripe style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="bh" label="编号" width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="mc" label="名称" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="mrbzksl" label="默认标准课时量" width="120" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.mrbzksl) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mrksfbz" label="默认课时费标准" width="120" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.mrksfbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mrclksfbz" label="默认超量课时费标准" width="150" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.mrclksfbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="xgjxbzksfbz" label="相关教学补助课时费标准" width="180" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.xgjxbzksfbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jxyxbz" label="绩效优秀补助" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.jxyxbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jxlhbz" label="绩效良好补助" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.jxlhbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jxzdbz" label="绩效中等补助" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.jxzdbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jxjgbz" label="绩效及格补助" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.jxjgbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jxbjgbz" label="绩效不及格补助" width="120" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.jxbjgbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sm" label="说明" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="160" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">修改</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 课时方案 -->
|
||||
<el-table v-else v-loading="coeffState.loading" :data="coeffState.list" border stripe style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="bh" label="编号" width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="mc" label="名称" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="zjksxs" label="主讲课时系数" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.zjksxs) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fjksxs" label="辅讲课时系数" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.fjksxs) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mbxyrs" label="满班学员人数" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.mbxyrs) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dz10xybjxs" label="递增10学员班级系数" width="150" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.dz10xybjxs) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bjxssx" label="班级系数上限" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.bjxssx) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="d78jksl" label="第78节课时量" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.d78jksl) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="yjksl" label="夜间课时量" width="100" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.yjksl) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mrktjxffxs" label="默认课堂教法系数" width="130" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.mrktjxffxs) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="hbxszl" label="合班系数增量" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.hbxszl) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="hbxssx" label="合班系数上限" width="110" align="right">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.hbxssx) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sm" label="说明" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">修改</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
:current-page="currentState.pageNum"
|
||||
:page-size="currentState.pageSize"
|
||||
:total="currentState.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
class="pagination"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 新增/修改对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="760px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<!-- 课时费方案表单 -->
|
||||
<el-form v-if="activeTab === 'fee'" ref="feeFormRef" :model="feeForm" :rules="feeRules" label-width="160px" class="add-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="编号">
|
||||
<el-input v-model="feeForm.bh" placeholder="留空则自动生成" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="mc">
|
||||
<el-input v-model="feeForm.mc" placeholder="请输入名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认标准课时量" prop="mrbzksl">
|
||||
<el-input-number v-model="feeForm.mrbzksl" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认课时费标准" prop="mrksfbz">
|
||||
<el-input-number v-model="feeForm.mrksfbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认超量课时费标准" prop="mrclksfbz">
|
||||
<el-input-number v-model="feeForm.mrclksfbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="相关教学补助课时费标准" prop="xgjxbzksfbz">
|
||||
<el-input-number v-model="feeForm.xgjxbzksfbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绩效优秀补助" prop="jxyxbz">
|
||||
<el-input-number v-model="feeForm.jxyxbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绩效良好补助" prop="jxlhbz">
|
||||
<el-input-number v-model="feeForm.jxlhbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绩效中等补助" prop="jxzdbz">
|
||||
<el-input-number v-model="feeForm.jxzdbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绩效及格补助" prop="jxjgbz">
|
||||
<el-input-number v-model="feeForm.jxjgbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绩效不及格补助" prop="jxbjgbz">
|
||||
<el-input-number v-model="feeForm.jxbjgbz" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="feeForm.sm" type="textarea" :rows="2" placeholder="请输入说明" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="feeForm.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 课时方案表单 -->
|
||||
<el-form v-else ref="coeffFormRef" :model="coeffForm" :rules="coeffRules" label-width="160px" class="add-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="编号">
|
||||
<el-input v-model="coeffForm.bh" placeholder="留空则自动生成" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="mc">
|
||||
<el-input v-model="coeffForm.mc" placeholder="请输入名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主讲课时系数">
|
||||
<el-input-number v-model="coeffForm.zjksxs" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="辅讲课时系数">
|
||||
<el-input-number v-model="coeffForm.fjksxs" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="满班学员人数">
|
||||
<el-input-number v-model="coeffForm.mbxyrs" :min="0" :precision="0" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="递增10学员班级系数">
|
||||
<el-input-number v-model="coeffForm.dz10xybjxs" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="班级系数上限">
|
||||
<el-input-number v-model="coeffForm.bjxssx" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="第78节课时量">
|
||||
<el-input-number v-model="coeffForm.d78jksl" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="夜间课时量">
|
||||
<el-input-number v-model="coeffForm.yjksl" :min="0" :precision="2" :step="1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认课堂教学方法系数">
|
||||
<el-input-number v-model="coeffForm.mrktjxffxs" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="合班系数增量">
|
||||
<el-input-number v-model="coeffForm.hbxszl" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="合班系数上限">
|
||||
<el-input-number v-model="coeffForm.hbxssx" :min="0" :precision="2" :step="0.1" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="coeffForm.sm" type="textarea" :rows="2" placeholder="请输入说明" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="coeffForm.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 4. 详情对话框 ==================== -->
|
||||
<el-dialog :visible="detailVisible" :title="`${currentTitle}详情`" width="680px" @update:visible="val => detailVisible = val">
|
||||
<el-descriptions v-if="activeTab === 'fee'" :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailData.bh }}</el-descriptions-item>
|
||||
<el-descriptions-item label="名称">{{ detailData.mc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="默认标准课时量">{{ fmtValue(detailData.mrbzksl) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="默认课时费标准">{{ fmtValue(detailData.mrksfbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="默认超量课时费标准">{{ fmtValue(detailData.mrclksfbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="相关教学补助课时费标准">{{ fmtValue(detailData.xgjxbzksfbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="绩效优秀补助">{{ fmtValue(detailData.jxyxbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="绩效良好补助">{{ fmtValue(detailData.jxlhbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="绩效中等补助">{{ fmtValue(detailData.jxzdbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="绩效及格补助">{{ fmtValue(detailData.jxjgbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="绩效不及格补助">{{ fmtValue(detailData.jxbjgbz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ fmtEmpty(detailData.cjsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="说明" :span="2">{{ fmtEmpty(detailData.sm) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ fmtEmpty(detailData.bz) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-descriptions v-else :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailData.bh }}</el-descriptions-item>
|
||||
<el-descriptions-item label="名称">{{ detailData.mc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="主讲课时系数">{{ fmtValue(detailData.zjksxs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="辅讲课时系数">{{ fmtValue(detailData.fjksxs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="满班学员人数">{{ fmtValue(detailData.mbxyrs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="递增10学员班级系数">{{ fmtValue(detailData.dz10xybjxs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="班级系数上限">{{ fmtValue(detailData.bjxssx) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="第78节课时量">{{ fmtValue(detailData.d78jksl) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="夜间课时量">{{ fmtValue(detailData.yjksl) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="默认课堂教学方法系数">{{ fmtValue(detailData.mrktjxffxs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="合班系数增量">{{ fmtValue(detailData.hbxszl) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="合班系数上限">{{ fmtValue(detailData.hbxssx) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ fmtEmpty(detailData.cjsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="说明" :span="2">{{ fmtEmpty(detailData.sm) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ fmtEmpty(detailData.bz) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div slot="footer">
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlaceholderPage from "@/components/PlaceholderPage"
|
||||
import {
|
||||
listFeeStandard,
|
||||
getFeeStandard,
|
||||
addFeeStandard,
|
||||
updateFeeStandard,
|
||||
deleteFeeStandard,
|
||||
listCoefficientPlan,
|
||||
getCoefficientPlan,
|
||||
addCoefficientPlan,
|
||||
updateCoefficientPlan
|
||||
} from '@/api/classHour/plan'
|
||||
|
||||
export default {
|
||||
name: "ClassHourPlan",
|
||||
components: { PlaceholderPage }
|
||||
name: 'ClassHourPlan',
|
||||
data() {
|
||||
return {
|
||||
// ==================== Tab ====================
|
||||
activeTab: 'fee',
|
||||
|
||||
// ==================== 查询条件 ====================
|
||||
feeSearch: { mc: '' },
|
||||
coeffSearch: { mc: '' },
|
||||
|
||||
// ==================== 列表状态 ====================
|
||||
feeState: this.createEmptyState(),
|
||||
coeffState: this.createEmptyState(),
|
||||
|
||||
// ==================== 新增/修改 ====================
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
saving: false,
|
||||
feeForm: this.createEmptyFeeForm(),
|
||||
coeffForm: this.createEmptyCoeffForm(),
|
||||
feeRules: {
|
||||
mc: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||||
mrbzksl: [{ required: true, message: '请输入默认标准课时量', trigger: 'blur' }],
|
||||
mrksfbz: [{ required: true, message: '请输入默认课时费标准', trigger: 'blur' }],
|
||||
mrclksfbz: [{ required: true, message: '请输入默认超量课时费标准', trigger: 'blur' }],
|
||||
xgjxbzksfbz: [{ required: true, message: '请输入相关教学补助课时费标准', trigger: 'blur' }],
|
||||
jxyxbz: [{ required: true, message: '请输入绩效优秀补助', trigger: 'blur' }],
|
||||
jxlhbz: [{ required: true, message: '请输入绩效良好补助', trigger: 'blur' }],
|
||||
jxzdbz: [{ required: true, message: '请输入绩效中等补助', trigger: 'blur' }],
|
||||
jxjgbz: [{ required: true, message: '请输入绩效及格补助', trigger: 'blur' }],
|
||||
jxbjgbz: [{ required: true, message: '请输入绩效不及格补助', trigger: 'blur' }]
|
||||
},
|
||||
coeffRules: {
|
||||
mc: [{ required: true, message: '请输入名称', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// ==================== 详情 ====================
|
||||
detailVisible: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentForm() {
|
||||
return this.activeTab === 'fee' ? this.feeSearch : this.coeffSearch
|
||||
},
|
||||
currentState() {
|
||||
return this.activeTab === 'fee' ? this.feeState : this.coeffState
|
||||
},
|
||||
currentTitle() {
|
||||
return this.activeTab === 'fee' ? '课时费方案' : '课时方案'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
createEmptyState() {
|
||||
return { list: [], loading: false, pageNum: 1, pageSize: 10, total: 0 }
|
||||
},
|
||||
|
||||
createEmptyFeeForm() {
|
||||
return {
|
||||
bh: '',
|
||||
mc: '',
|
||||
mrbzksl: null,
|
||||
mrksfbz: null,
|
||||
mrclksfbz: null,
|
||||
xgjxbzksfbz: null,
|
||||
jxyxbz: null,
|
||||
jxlhbz: null,
|
||||
jxzdbz: null,
|
||||
jxjgbz: null,
|
||||
jxbjgbz: null,
|
||||
sm: '',
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
|
||||
createEmptyCoeffForm() {
|
||||
return {
|
||||
bh: '',
|
||||
mc: '',
|
||||
zjksxs: null,
|
||||
fjksxs: null,
|
||||
mbxyrs: null,
|
||||
dz10xybjxs: null,
|
||||
bjxssx: null,
|
||||
d78jksl: null,
|
||||
yjksl: null,
|
||||
mrktjxffxs: null,
|
||||
hbxszl: null,
|
||||
hbxssx: null,
|
||||
sm: '',
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
fetchList() {
|
||||
const state = this.currentState
|
||||
const params = { pageNum: state.pageNum, pageSize: state.pageSize }
|
||||
if (this.currentForm.mc && this.currentForm.mc.trim()) params.mc = this.currentForm.mc.trim()
|
||||
state.loading = true
|
||||
const req = this.activeTab === 'fee' ? listFeeStandard(params) : listCoefficientPlan(params)
|
||||
req.then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
state.list = data.records || []
|
||||
state.total = data.total || 0
|
||||
}).catch(() => {
|
||||
state.list = []
|
||||
state.total = 0
|
||||
}).finally(() => {
|
||||
state.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleTabClick() {
|
||||
this.currentState.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.currentState.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(page) {
|
||||
this.currentState.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.currentState.pageSize = size
|
||||
this.currentState.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// ==================== 新增 / 修改 ====================
|
||||
handleAdd() {
|
||||
this.feeForm = this.createEmptyFeeForm()
|
||||
this.coeffForm = this.createEmptyCoeffForm()
|
||||
this.dialogTitle = `新增${this.currentTitle}`
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
const req = this.activeTab === 'fee' ? getFeeStandard(row.bh) : getCoefficientPlan(row.bh)
|
||||
req.then(res => {
|
||||
const d = (res && res.data) || {}
|
||||
if (this.activeTab === 'fee') {
|
||||
this.feeForm = {
|
||||
bh: d.bh || '',
|
||||
mc: d.mc || '',
|
||||
mrbzksl: this.toNull(d.mrbzksl),
|
||||
mrksfbz: this.toNull(d.mrksfbz),
|
||||
mrclksfbz: this.toNull(d.mrclksfbz),
|
||||
xgjxbzksfbz: this.toNull(d.xgjxbzksfbz),
|
||||
jxyxbz: this.toNull(d.jxyxbz),
|
||||
jxlhbz: this.toNull(d.jxlhbz),
|
||||
jxzdbz: this.toNull(d.jxzdbz),
|
||||
jxjgbz: this.toNull(d.jxjgbz),
|
||||
jxbjgbz: this.toNull(d.jxbjgbz),
|
||||
sm: d.sm || '',
|
||||
bz: d.bz || ''
|
||||
}
|
||||
} else {
|
||||
this.coeffForm = {
|
||||
bh: d.bh || '',
|
||||
mc: d.mc || '',
|
||||
zjksxs: this.toNull(d.zjksxs),
|
||||
fjksxs: this.toNull(d.fjksxs),
|
||||
mbxyrs: this.toNull(d.mbxyrs),
|
||||
dz10xybjxs: this.toNull(d.dz10xybjxs),
|
||||
bjxssx: this.toNull(d.bjxssx),
|
||||
d78jksl: this.toNull(d.d78jksl),
|
||||
yjksl: this.toNull(d.yjksl),
|
||||
mrktjxffxs: this.toNull(d.mrktjxffxs),
|
||||
hbxszl: this.toNull(d.hbxszl),
|
||||
hbxssx: this.toNull(d.hbxssx),
|
||||
sm: d.sm || '',
|
||||
bz: d.bz || ''
|
||||
}
|
||||
}
|
||||
this.dialogTitle = `修改${this.currentTitle}`
|
||||
this.dialogVisible = true
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
handleSubmit() {
|
||||
const isFee = this.activeTab === 'fee'
|
||||
const formRef = isFee ? this.$refs.feeFormRef : this.$refs.coeffFormRef
|
||||
formRef.validate(valid => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
const payload = isFee ? this.buildFeePayload() : this.buildCoeffPayload()
|
||||
this.saving = true
|
||||
const req = payload.bh
|
||||
? (isFee ? updateFeeStandard(payload) : updateCoefficientPlan(payload))
|
||||
: (isFee ? addFeeStandard(payload) : addCoefficientPlan(payload))
|
||||
req.then(() => {
|
||||
this.$message.success(this.dialogTitle.indexOf('修改') === 0 ? '修改成功' : '新增成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.saving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
toNull(val) {
|
||||
return val === null || val === undefined ? null : val
|
||||
},
|
||||
|
||||
/** 课时费方案请求体:仅含实体非空字段(创建/修改时间后端自动维护) */
|
||||
buildFeePayload() {
|
||||
const f = this.feeForm
|
||||
const p = {}
|
||||
if (f.bh && f.bh.trim()) p.bh = f.bh.trim()
|
||||
if (f.mc && f.mc.trim()) p.mc = f.mc.trim()
|
||||
;['mrbzksl', 'mrksfbz', 'mrclksfbz', 'xgjxbzksfbz', 'jxyxbz', 'jxlhbz', 'jxzdbz', 'jxjgbz', 'jxbjgbz'].forEach(k => {
|
||||
if (f[k] !== null && f[k] !== undefined) p[k] = f[k]
|
||||
})
|
||||
if (f.sm && f.sm.trim()) p.sm = f.sm.trim()
|
||||
if (f.bz && f.bz.trim()) p.bz = f.bz.trim()
|
||||
return p
|
||||
},
|
||||
|
||||
/** 课时方案请求体:仅含实体非空字段 */
|
||||
buildCoeffPayload() {
|
||||
const f = this.coeffForm
|
||||
const p = {}
|
||||
if (f.bh && f.bh.trim()) p.bh = f.bh.trim()
|
||||
if (f.mc && f.mc.trim()) p.mc = f.mc.trim()
|
||||
;['zjksxs', 'fjksxs', 'mbxyrs', 'dz10xybjxs', 'bjxssx', 'd78jksl', 'yjksl', 'mrktjxffxs', 'hbxszl', 'hbxssx'].forEach(k => {
|
||||
if (f[k] !== null && f[k] !== undefined) p[k] = f[k]
|
||||
})
|
||||
if (f.sm && f.sm.trim()) p.sm = f.sm.trim()
|
||||
if (f.bz && f.bz.trim()) p.bz = f.bz.trim()
|
||||
return p
|
||||
},
|
||||
|
||||
// ==================== 删除(仅课时费方案有删除接口) ====================
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除「${row.mc || row.bh || '该方案'}」吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => deleteFeeStandard(row.bh)).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 详情 ====================
|
||||
handleDetail(row) {
|
||||
const req = this.activeTab === 'fee' ? getFeeStandard(row.bh) : getCoefficientPlan(row.bh)
|
||||
req.then(res => {
|
||||
this.detailData = (res && res.data) || {}
|
||||
this.detailVisible = true
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/** 数值空值显示为 '-'(保留 0) */
|
||||
fmtValue(val) {
|
||||
return val === null || val === undefined ? '-' : val
|
||||
},
|
||||
|
||||
/** 空值显示为 '-' */
|
||||
fmtEmpty(val) {
|
||||
return val === null || val === undefined || val === '' ? '-' : val
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.plan-page {
|
||||
.list-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
// ==================== 1. 查询区域 ====================
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 数据表格 ====================
|
||||
.table-card {
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 3. 新增/修改表单 ====================
|
||||
.add-form {
|
||||
max-height: 62vh;
|
||||
overflow-y: auto;
|
||||
padding-right: 4px;
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,223 +1,250 @@
|
||||
<template>
|
||||
<div class="app-container subsidy-page">
|
||||
<div class="list-title">课时补助核算</div>
|
||||
<div class="top-tip">{{ tipText }}</div>
|
||||
|
||||
<!-- ==================== 1. 新增核算区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<div class="form-title">新增</div>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<!-- 左栏 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期名称" prop="semesterName">
|
||||
<el-input v-model="form.semesterName" placeholder="请输入学期名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期" prop="startDate">
|
||||
<el-input v-model="form.startDate" placeholder="如:2016-03-01" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="课时补助标准">
|
||||
<el-select v-model="form.subsidyStandard" placeholder="请选择" class="w-full">
|
||||
<el-option v-for="item in subsidyStandardOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<!-- ==================== Tab 切换 ==================== -->
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="课时统计" name="hour" />
|
||||
<el-tab-pane label="课时费统计" name="fee" />
|
||||
</el-tabs>
|
||||
|
||||
<!-- ==================== 1. 查询条件 ==================== -->
|
||||
<!-- 课时统计 -->
|
||||
<el-card v-if="activeTab === 'hour'" shadow="never" class="search-card">
|
||||
<el-form :model="hourForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="学期年度">
|
||||
<el-input v-model="hourForm.nd" placeholder="如 2026" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务类别">
|
||||
<el-radio-group v-model="form.taskCategory">
|
||||
<el-radio v-for="item in taskCategoryOptions" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="学期序号">
|
||||
<el-input v-model="hourForm.xq" placeholder="如 1" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期" prop="endDate">
|
||||
<el-input v-model="form.endDate" placeholder="如:2016-08-31" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="课时核算标准">
|
||||
<el-select v-model="form.accountStandard" placeholder="请选择" class="w-full">
|
||||
<el-option v-for="item in accountStandardOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="教员姓名">
|
||||
<el-input v-model="hourForm.jyxm" placeholder="请输入教员姓名" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="6" class="search-actions-col">
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button type="primary" plain @click="handleExport">导出 Excel</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 课时费统计 -->
|
||||
<el-card v-else shadow="never" class="search-card">
|
||||
<el-form :model="feeForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="学期年度">
|
||||
<el-input v-model="feeForm.nd" placeholder="如 2026" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="学期序号">
|
||||
<el-input v-model="feeForm.xq" placeholder="如 1" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="教员姓名">
|
||||
<el-input v-model="feeForm.jyxm" placeholder="请输入教员姓名" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<el-form-item label="标准编号">
|
||||
<el-input v-model="feeForm.ksfbzbh" placeholder="课时费标准编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="search-actions-col">
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button type="primary" plain @click="handleExport">导出 Excel</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" :loading="addLoading" @click="handleAdd">添加</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 数据表格 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="queryLoading" :data="tableData" border stripe style="width: 100%">
|
||||
<el-table-column label="详细" width="80" fixed align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" @click="handleDetail(row)">详细</el-button>
|
||||
</template>
|
||||
<div class="table-title">{{ activeTab === 'hour' ? '课时统计列表' : '课时费统计列表' }}</div>
|
||||
<el-table v-loading="currentState.loading" :data="currentState.list" border stripe style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="jysdh" label="教研室代号" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jysmc" label="教研室名称" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="jybh" label="教员编号" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jyxm" label="教员姓名" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="zc" label="职称" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nf" label="年份" width="70" align="center" />
|
||||
<el-table-column prop="sbn" label="上半年" width="90" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.sbn) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="semesterName" label="学期名称" width="120" />
|
||||
<el-table-column prop="taskCategory" label="任务类别" width="180" />
|
||||
<el-table-column prop="startDate" label="核算开始日期" width="120" />
|
||||
<el-table-column prop="endDate" label="核算结束日期" width="120" />
|
||||
<el-table-column prop="totalHours" label="总课时量" width="100" align="right" />
|
||||
<el-table-column prop="qualityHours" label="优质课时量" width="100" align="right" />
|
||||
<el-table-column prop="qualityRatio" label="优质课时量比例" width="120" align="right" />
|
||||
<el-table-column prop="totalSubsidy" label="总补助金额" width="120" align="right" />
|
||||
<el-table-column prop="accountStandard" label="课时核算标准" show-overflow-tooltip />
|
||||
<el-table-column prop="subsidyStandard" label="课时补助标准" width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<span :class="row.status === '已核算' ? 'status-done' : 'status-doing'">
|
||||
{{ row.status }}
|
||||
</span>
|
||||
</template>
|
||||
<el-table-column prop="xbn" label="下半年" width="90" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.xbn) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zj" label="总计" width="90" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.zj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bzksl" label="标准课时量" width="100" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.bzksl) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="cks" label="超课时" width="90" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.cks) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jsgs" label="计算过程" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="jg" label="结果" width="90" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.jg) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ksfbzmc" label="课时费标准" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="ksfbz" label="课时费单价" width="100" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.ksfbz) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="clksfbz" label="超量课时费单价" width="110" align="right" header-align="center">
|
||||
<template slot-scope="{ row }">{{ fmtValue(row.clksfbz) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="table-footer">
|
||||
<span>总记录数:{{ tableData.length }} 条</span>
|
||||
<span>总课时量:{{ totalHours }}</span>
|
||||
<span>优质课时量:{{ totalQualityHours }}</span>
|
||||
<span>总补助金额:{{ totalSubsidy }} 元</span>
|
||||
</div>
|
||||
<el-pagination
|
||||
:current-page="currentState.pageNum"
|
||||
:page-size="currentState.pageSize"
|
||||
:total="currentState.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
class="pagination"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 详情对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="detailVisible"
|
||||
title="课时补助核算详情"
|
||||
width="560px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => detailVisible = val"
|
||||
>
|
||||
<el-descriptions v-if="detailRow" :column="1" border>
|
||||
<el-descriptions-item label="学期名称">{{ detailRow.semesterName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务类别">{{ detailRow.taskCategory }}</el-descriptions-item>
|
||||
<el-descriptions-item label="核算开始日期">{{ detailRow.startDate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="核算结束日期">{{ detailRow.endDate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="总课时量">{{ detailRow.totalHours }}</el-descriptions-item>
|
||||
<el-descriptions-item label="优质课时量">{{ detailRow.qualityHours }}</el-descriptions-item>
|
||||
<el-descriptions-item label="优质课时量比例">{{ detailRow.qualityRatio }}</el-descriptions-item>
|
||||
<el-descriptions-item label="总补助金额">{{ detailRow.totalSubsidy }} 元</el-descriptions-item>
|
||||
<el-descriptions-item label="课时核算标准">{{ detailRow.accountStandard }}</el-descriptions-item>
|
||||
<el-descriptions-item label="课时补助标准">{{ detailRow.subsidyStandard }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{ detailRow.status }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div slot="footer">
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 模拟核算列表数据(后端接口未提供,接口就绪后可删除并改为接口加载)
|
||||
const mockSummaryData = [
|
||||
{ bh: 'H001', mc: '2022年秋季学期课时补助核算', rwlb: '全军院校训练规划内任务', hsksrq: '2022-09-01T00:00:00', hsjsrq: '2023-01-15T00:00:00', zksl: 1200, yzksl: 800, yzkslbl: 0.6667, zbzje: 24000, zt: '已核算' },
|
||||
{ bh: 'H002', mc: '2022年春季学期课时补助核算', rwlb: '其他任务(含研究生导师指导)', hsksrq: '2022-03-01T00:00:00', hsjsrq: '2022-08-31T00:00:00', zksl: 900, yzksl: 540, yzkslbl: 0.6, zbzje: 18000, zt: '核算中' },
|
||||
{ bh: 'H003', mc: '2021年秋季学期课时补助核算', rwlb: '全军院校训练规划内任务', hsksrq: '2021-09-01T00:00:00', hsjsrq: '2022-01-15T00:00:00', zksl: 1100, yzksl: 770, yzkslbl: 0.7, zbzje: 22000, zt: '已核算' }
|
||||
]
|
||||
import { saveAs } from 'file-saver'
|
||||
import {
|
||||
listHourStatistics,
|
||||
exportHourStatistics,
|
||||
listFeeStatistics,
|
||||
exportFeeStatistics
|
||||
} from '@/api/classHour/hourStat'
|
||||
|
||||
export default {
|
||||
name: 'SubsidyIndex',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 顶部提示条 ====================
|
||||
tipText: '提示:"课时核算"和"补助核算"要花费稍微长一点时间,操作后请耐心等待系统"操作成功"的提示!',
|
||||
// ==================== Tab ====================
|
||||
activeTab: 'hour',
|
||||
|
||||
// ==================== 下拉选项 ====================
|
||||
subsidyStandardOptions: ['2022年秋季学期', '2022年春季学期', '2021年秋季学期', '2021年春季学期'],
|
||||
accountStandardOptions: ['2022年秋季学期课时补助核算', '2022年春季学期课时补助核算', '2021年秋季学期课时补助核算', '2021年春季学期课时补助核算'],
|
||||
taskCategoryOptions: [
|
||||
{ label: '全军院校训练规划内任务', value: '全军院校训练规划内任务' },
|
||||
{ label: '其他任务(含研究生导师指导)', value: '其他任务(含研究生导师指导)' }
|
||||
],
|
||||
|
||||
// ==================== 新增表单 ====================
|
||||
form: {
|
||||
semesterName: '',
|
||||
taskCategory: '全军院校训练规划内任务',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
subsidyStandard: '2022年秋季学期',
|
||||
accountStandard: '2022年秋季学期课时补助核算'
|
||||
// ==================== 课时统计查询条件 ====================
|
||||
hourForm: {
|
||||
nd: '',
|
||||
xq: '',
|
||||
jyxm: ''
|
||||
},
|
||||
rules: {
|
||||
semesterName: [{ required: true, message: '请输入学期名称', trigger: 'blur' }],
|
||||
startDate: [{ required: true, message: '请输入开始日期', trigger: 'blur' }],
|
||||
endDate: [{ required: true, message: '请输入结束日期', trigger: 'blur' }]
|
||||
|
||||
// ==================== 课时费统计查询条件 ====================
|
||||
feeForm: {
|
||||
nd: '',
|
||||
xq: '',
|
||||
jyxm: '',
|
||||
ksfbzbh: ''
|
||||
},
|
||||
addLoading: false,
|
||||
|
||||
// ==================== 表格数据 ====================
|
||||
tableData: [],
|
||||
queryLoading: false,
|
||||
|
||||
// ==================== 详情对话框 ====================
|
||||
detailVisible: false,
|
||||
detailRow: null
|
||||
// ==================== 各 Tab 列表状态 ====================
|
||||
hourState: this.createEmptyState(),
|
||||
feeState: this.createEmptyState()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
totalHours() {
|
||||
return this.tableData.reduce((sum, r) => sum + Number(r.totalHours || 0), 0)
|
||||
currentForm() {
|
||||
return this.activeTab === 'hour' ? this.hourForm : this.feeForm
|
||||
},
|
||||
totalQualityHours() {
|
||||
return this.tableData.reduce((sum, r) => sum + Number(r.qualityHours || 0), 0)
|
||||
},
|
||||
totalSubsidy() {
|
||||
return this.tableData.reduce((sum, r) => sum + Number(r.totalSubsidy || 0), 0)
|
||||
currentState() {
|
||||
return this.activeTab === 'hour' ? this.hourState : this.feeState
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handleQuery()
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// ==================== 查询核算列表 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 /log/summary/list
|
||||
handleQuery() {
|
||||
this.queryLoading = true
|
||||
setTimeout(() => {
|
||||
this.tableData = mockSummaryData.map((item, idx) => ({
|
||||
id: idx + 1,
|
||||
_bh: item.bh || '',
|
||||
semesterName: item.mc || '-',
|
||||
taskCategory: item.rwlb || '-',
|
||||
startDate: (item.hsksrq || '').substring(0, 10) || '-',
|
||||
endDate: (item.hsjsrq || '').substring(0, 10) || '-',
|
||||
totalHours: item.zksl || 0,
|
||||
qualityHours: item.yzksl || 0,
|
||||
qualityRatio: item.zksl > 0 ? ((item.yzkslbl || 0) * 100).toFixed(2) + '%' : '0.00%',
|
||||
totalSubsidy: item.zbzje || 0,
|
||||
accountStandard: item.mc || '-',
|
||||
subsidyStandard: '-',
|
||||
status: item.zt || '-'
|
||||
}))
|
||||
this.$message.success(`查询完成,共 ${this.tableData.length} 条记录(前端模拟)`)
|
||||
this.queryLoading = false
|
||||
}, 200)
|
||||
createEmptyState() {
|
||||
return { list: [], loading: false, pageNum: 1, pageSize: 20, total: 0 }
|
||||
},
|
||||
|
||||
// ==================== 添加 ====================
|
||||
// TODO: 后端接口未提供,提交为前端模拟;接口就绪后替换为 /log/subsidy-project/add
|
||||
handleAdd() {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
this.addLoading = true
|
||||
setTimeout(() => {
|
||||
this.$message.success('核算提交成功(前端模拟)')
|
||||
this.handleQuery()
|
||||
this.addLoading = false
|
||||
}, 300)
|
||||
/** 构建查询参数,仅传非空字段(与后端 Query 字段一致) */
|
||||
buildParams(form) {
|
||||
const params = {}
|
||||
if (form.nd && form.nd.trim()) params.nd = form.nd.trim()
|
||||
if (form.xq && form.xq.trim()) params.xq = form.xq.trim()
|
||||
if (form.jyxm && form.jyxm.trim()) params.jyxm = form.jyxm.trim()
|
||||
if (form.ksfbzbh && form.ksfbzbh.trim()) params.ksfbzbh = form.ksfbzbh.trim()
|
||||
return params
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
fetchList() {
|
||||
const state = this.currentState
|
||||
const form = this.currentForm
|
||||
const params = Object.assign(
|
||||
{ pageNum: state.pageNum, pageSize: state.pageSize },
|
||||
this.buildParams(form)
|
||||
)
|
||||
state.loading = true
|
||||
const req = this.activeTab === 'hour' ? listHourStatistics(params) : listFeeStatistics(params)
|
||||
req.then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
state.list = data.records || []
|
||||
state.total = data.total || 0
|
||||
}).catch(() => {
|
||||
state.list = []
|
||||
state.total = 0
|
||||
}).finally(() => {
|
||||
state.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 详情对话框 ====================
|
||||
handleDetail(row) {
|
||||
this.detailRow = row
|
||||
this.detailVisible = true
|
||||
handleTabClick() {
|
||||
this.currentState.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.currentState.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(page) {
|
||||
this.currentState.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.currentState.pageSize = size
|
||||
this.currentState.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// ==================== 导出 ====================
|
||||
handleExport() {
|
||||
const clean = this.buildParams(this.currentForm)
|
||||
const isHour = this.activeTab === 'hour'
|
||||
const req = isHour ? exportHourStatistics(clean) : exportFeeStatistics(clean)
|
||||
const fileName = isHour ? '课时统计.xlsx' : '课时费统计.xlsx'
|
||||
req.then(blob => {
|
||||
saveAs(blob, fileName)
|
||||
this.$message.success('导出成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/** 数值空值显示为 '-'(保留 0) */
|
||||
fmtValue(val) {
|
||||
return val === null || val === undefined ? '-' : val
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,63 +263,37 @@ export default {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.top-tip {
|
||||
color: #f56c6c;
|
||||
font-size: 13px;
|
||||
margin-bottom: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
// ==================== 1. 查询条件区域 ====================
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.form-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
.search-actions-col {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 数据表格 ====================
|
||||
.table-card {
|
||||
.el-table {
|
||||
width: 100%;
|
||||
.table-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.table-footer {
|
||||
.pagination {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24px;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
|
||||
.status-done {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.status-doing {
|
||||
color: #e6a23c;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,89 +1,8 @@
|
||||
<template>
|
||||
<div class="app-container home">
|
||||
<!-- 第一行:信息/日志/公告 -->
|
||||
<!-- 通知公告 -->
|
||||
<el-row :gutter="20" class="bottom-row">
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="8">
|
||||
<el-card class="module-card info-card" shadow="hover">
|
||||
<div slot="header" class="card-header">
|
||||
<span><i class="el-icon-phone-outline card-icon"></i> 联系信息</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="contact-item">
|
||||
<div class="contact-icon"><i class="el-icon-s-promotion"></i></div>
|
||||
<div class="contact-text">
|
||||
<div class="label">官网</div>
|
||||
<el-link href="http://www.roomroot.vip" target="_blank">http://www.roomroot.vip</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-item">
|
||||
<div class="contact-icon"><i class="el-icon-user-solid"></i></div>
|
||||
<div class="contact-text">
|
||||
<div class="label">QQ群</div>
|
||||
<a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632" target="_blank">127358632</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-item">
|
||||
<div class="contact-icon"><i class="el-icon-chat-dot-round"></i></div>
|
||||
<div class="contact-text">
|
||||
<div class="label">微信</div>
|
||||
<span>风影随行</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-item">
|
||||
<div class="contact-icon"><i class="el-icon-money"></i></div>
|
||||
<div class="contact-text">
|
||||
<div class="label">支付宝</div>
|
||||
<span>风影随行</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="8">
|
||||
<el-card class="module-card log-card" shadow="hover">
|
||||
<div slot="header" class="card-header">
|
||||
<span><i class="el-icon-time card-icon"></i> 登录日志</span>
|
||||
</div>
|
||||
<div class="card-body" v-loading="loginLogLoading">
|
||||
<table v-if="loginLogList.length > 0" class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>登录人</th>
|
||||
<th>登录时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in loginLogList" :key="item.infoId">
|
||||
<td>
|
||||
<i class="el-icon-user table-icon"></i>
|
||||
{{ item.userName }}
|
||||
</td>
|
||||
<td>{{ parseTime(item.loginTime) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-else class="empty-state">
|
||||
<i class="el-icon-folder-opened empty-icon"></i>
|
||||
<p>暂无记录</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<el-pagination
|
||||
@size-change="handleLoginLogSizeChange"
|
||||
@current-change="handleLoginLogCurrentChange"
|
||||
:current-page="loginLogPage.currentPage"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="loginLogPage.pageSize"
|
||||
:total="loginLogPage.total"
|
||||
layout="total, prev, pager, next"
|
||||
small
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="8">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24">
|
||||
<el-card class="module-card notice-card" shadow="hover">
|
||||
<div slot="header" class="card-header">
|
||||
<span><i class="el-icon-bell card-icon"></i> 通知公告</span>
|
||||
@@ -131,7 +50,6 @@
|
||||
|
||||
<script>
|
||||
import { listNotice } from "@/api/system/notice"
|
||||
import { homeList } from "@/api/monitor/logininfor"
|
||||
import NoticeDetailView from "@/layout/components/HeaderNotice/DetailView"
|
||||
|
||||
export default {
|
||||
@@ -142,13 +60,6 @@ export default {
|
||||
version: "3.9.2",
|
||||
noticeList: [],
|
||||
noticeLoading: false,
|
||||
loginLogList: [],
|
||||
loginLogLoading: false,
|
||||
loginLogPage: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
},
|
||||
noticePage: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
@@ -158,7 +69,6 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.loadNoticeList()
|
||||
this.loadLoginLogList()
|
||||
},
|
||||
methods: {
|
||||
goTarget(href) {
|
||||
@@ -208,28 +118,6 @@ export default {
|
||||
handleViewNotice(item) {
|
||||
this.$refs.noticeViewRef.open(item)
|
||||
},
|
||||
loadLoginLogList() {
|
||||
this.loginLogLoading = true
|
||||
homeList({
|
||||
pageNum: this.loginLogPage.currentPage,
|
||||
pageSize: this.loginLogPage.pageSize
|
||||
}).then(response => {
|
||||
this.loginLogList = response.rows || []
|
||||
this.loginLogPage.total = response.total || 0
|
||||
this.loginLogLoading = false
|
||||
}).catch(() => {
|
||||
this.loginLogLoading = false
|
||||
})
|
||||
},
|
||||
handleLoginLogSizeChange(val) {
|
||||
this.loginLogPage.pageSize = val
|
||||
this.loginLogPage.currentPage = 1
|
||||
this.loadLoginLogList()
|
||||
},
|
||||
handleLoginLogCurrentChange(val) {
|
||||
this.loginLogPage.currentPage = val
|
||||
this.loadLoginLogList()
|
||||
},
|
||||
handleNoticeSizeChange(val) {
|
||||
this.noticePage.pageSize = val
|
||||
this.noticePage.currentPage = 1
|
||||
@@ -371,102 +259,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.contact-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--edu-green-dark) 0%, var(--edu-green-primary) 100%);
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 2px 8px rgba(15, 25, 86, 0.2);
|
||||
}
|
||||
|
||||
.contact-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.label {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
a, .el-link {
|
||||
font-size: 13px;
|
||||
color: var(--edu-green-primary);
|
||||
}
|
||||
|
||||
a:hover, .el-link:hover {
|
||||
color: var(--edu-green-dark);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 13px;
|
||||
|
||||
thead {
|
||||
tr {
|
||||
background: linear-gradient(135deg, rgba(0, 135, 90, 0.06) 0%, rgba(0, 135, 90, 0.04) 100%);
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 10px 20px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--edu-green-dark);
|
||||
border-bottom: 1px solid rgba(0, 135, 90, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
transition: background 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 135, 90, 0.04);
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px 20px;
|
||||
color: #4a4f6b;
|
||||
border-bottom: 1px solid #f0f1f7;
|
||||
|
||||
.table-icon {
|
||||
color: var(--edu-green-light);
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-list {
|
||||
.notice-item {
|
||||
padding: 14px 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="login">
|
||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
|
||||
<h3 class="title">{{title}}</h3>
|
||||
@@ -50,14 +50,13 @@
|
||||
<script>
|
||||
import Cookies from "js-cookie"
|
||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
||||
import defaultSettings from '@/settings'
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
data() {
|
||||
return {
|
||||
title: process.env.VUE_APP_TITLE,
|
||||
footerContent: defaultSettings.footerContent,
|
||||
footerContent: "Copyright © 2018-2026 roomroot. All Rights Reserved.",
|
||||
loginForm: {
|
||||
username: "admin",
|
||||
password: "admin123",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="register">
|
||||
<el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
|
||||
<h3 class="title">{{title}}</h3>
|
||||
@@ -55,14 +55,13 @@
|
||||
<script>
|
||||
import { register } from "@/api/login"
|
||||
import passwordRule from "@/utils/passwordRule"
|
||||
import defaultSettings from '@/settings'
|
||||
|
||||
export default {
|
||||
mixins: [passwordRule],
|
||||
data() {
|
||||
return {
|
||||
title: process.env.VUE_APP_TITLE,
|
||||
footerContent: defaultSettings.footerContent,
|
||||
footerContent: "Copyright © 2018-2026 roomroot. All Rights Reserved.",
|
||||
registerForm: {
|
||||
username: "",
|
||||
password: "",
|
||||
|
||||
@@ -69,12 +69,6 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<div class="form-tip">注意:勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24" class="search-actions">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
@@ -101,9 +95,9 @@
|
||||
</div>
|
||||
|
||||
<div class="bar-right">
|
||||
<el-button type="primary" @click="handleImportToSystem" :loading="importing">缓存数据导入到系统</el-button>
|
||||
<el-button type="primary" @click="handleUploadToCache">上传数据至缓存</el-button>
|
||||
<el-button type="primary" @click="handleCheckCache">检查缓存数据</el-button>
|
||||
<el-button type="primary" @click="handleImportToSystem">缓存数据导入到系统</el-button>
|
||||
<el-button type="danger" @click="handleDeleteCache">删除缓存数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -112,10 +106,10 @@
|
||||
<!-- ==================== 3. 数据表格 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row class="import-table">
|
||||
<el-table-column prop="xq" label="学期" width="53" align="center" />
|
||||
<el-table-column prop="nd" label="年度" width="60" align="center" />
|
||||
<el-table-column prop="xh" label="序号" width="53" align="center" />
|
||||
<el-table-column prop="yxh" label="原序号" width="67" align="center" />
|
||||
<el-table-column prop="rq" label="日期" width="53" align="center" :formatter="formatDate" />
|
||||
<el-table-column prop="rq" label="日期" width="120" align="center" :formatter="formatDate" />
|
||||
<el-table-column prop="yjc" label="原节次" width="67" align="center" />
|
||||
<el-table-column prop="jc" label="节次" width="53" align="center" />
|
||||
<el-table-column prop="kcmc" label="课程名称" width="85" show-overflow-tooltip />
|
||||
@@ -125,7 +119,6 @@
|
||||
<el-table-column prop="jxcd" label="教学场地" width="81" align="center" />
|
||||
<el-table-column prop="jxnr" label="教学内容" width="81" show-overflow-tooltip />
|
||||
<el-table-column prop="jxff" label="教学方法" width="81" align="center" />
|
||||
<el-table-column prop="jxyd" label="教学要点" width="81" show-overflow-tooltip />
|
||||
<el-table-column prop="jybz" label="教员备注" width="81" show-overflow-tooltip />
|
||||
<el-table-column prop="jwbz" label="教务备注" width="81" show-overflow-tooltip />
|
||||
<el-table-column prop="jcjg" label="检查结果" width="81" align="center" />
|
||||
@@ -134,9 +127,9 @@
|
||||
<span>{{ row.ytgjc ? '是' : '否' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ybhhl" label="已被忽略" width="81" align="center">
|
||||
<el-table-column prop="ybhl" label="已被忽略" width="81" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<span>{{ row.ybhhl ? '是' : '否' }}</span>
|
||||
<span>{{ row.ybhl ? '是' : '否' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ybcl" label="已被处理" width="81" align="center">
|
||||
@@ -166,12 +159,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 模拟导入记录数据(后端接口未提供,接口就绪后可删除并改为接口加载)
|
||||
const mockTableData = [
|
||||
{ xq: '2026-2027-1', xh: 1, yxh: 1, rq: '2026-09-01 08:00:00', yjc: '1-2', jc: '1', kcmc: '高等数学', bc: '2026级1队', zrdw: '基础部', skjy: '王教员', jxcd: '教学楼101', jxnr: '第一章 函数与极限', jxff: '讲授', jxyd: '理解极限定义', jybz: '', jwbz: '', jcjg: '通过', ytgjc: true, ybhhl: false, ybcl: true, ybdr: false },
|
||||
{ xq: '2026-2027-1', xh: 2, yxh: 2, rq: '2026-09-01 10:00:00', yjc: '3-4', jc: '2', kcmc: '大学英语', bc: '2026级2队', zrdw: '外语系', skjy: '李教员', jxcd: '教学楼102', jxnr: 'Unit 1 课文讲解', jxff: '讲授', jxyd: '掌握重点词汇', jybz: '', jwbz: '', jcjg: '通过', ytgjc: true, ybhhl: false, ybcl: true, ybdr: false },
|
||||
{ xq: '2026-2027-1', xh: 3, yxh: 3, rq: '2026-09-02 08:00:00', yjc: '1-2', jc: '1', kcmc: '军事理论', bc: '2026级1队', zrdw: '军事教研室', skjy: '张教员', jxcd: '学术报告厅', jxnr: '国防概论', jxff: '讲授', jxyd: '了解国防常识', jybz: '', jwbz: '', jcjg: '待检', ytgjc: false, ybhhl: false, ybcl: false, ybdr: false }
|
||||
]
|
||||
import { listTeachingPlan, importTeachingPlan, downloadTeachingPlanTemplate } from '@/api/schedule/teachingPlan'
|
||||
|
||||
export default {
|
||||
name: 'PlanImportIndex',
|
||||
@@ -193,50 +181,68 @@ export default {
|
||||
kmmc: ''
|
||||
},
|
||||
|
||||
// ==================== 文件上传与缓存操作 ====================
|
||||
// ==================== 文件上传与导入 ====================
|
||||
selectedFileName: '未选择任何文件',
|
||||
selectedFile: null,
|
||||
importing: false,
|
||||
|
||||
// ==================== 表格数据 ====================
|
||||
tableData: [],
|
||||
loading: false,
|
||||
allData: [],
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handleSearch()
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// ==================== 查询 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为接口加载
|
||||
handleSearch() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
this.allData = mockTableData.slice()
|
||||
this.total = this.allData.length
|
||||
this.pageNum = 1
|
||||
this.applyPage()
|
||||
this.$message.success(`查询完成,共 ${this.allData.length} 条记录(前端模拟)`)
|
||||
this.loading = false
|
||||
}, 200)
|
||||
// 仅传后端 Mapper 支持的字段:skjy(授课教员) bc(班次) kcmc(课程名称) ytgjc(已通过检查)
|
||||
// 课程时间、忽略状态、教学场地名称后端列表查询不支持,不传
|
||||
buildSearchParams() {
|
||||
const f = this.searchForm
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
if (f.jyxm && f.jyxm.trim()) params.skjy = f.jyxm.trim()
|
||||
if (f.bcmc && f.bcmc.trim()) params.bc = f.bcmc.trim()
|
||||
if (f.kmmc && f.kmmc.trim()) params.kcmc = f.kmmc.trim()
|
||||
// 检查状态:仅勾选「已通过」或「未通过」其中之一时才按该条件过滤
|
||||
if (f.jcztEnabled) {
|
||||
if (f.jcztYtg && !f.jcztWtg) params.ytgjc = true
|
||||
else if (!f.jcztYtg && f.jcztWtg) params.ytgjc = false
|
||||
}
|
||||
return params
|
||||
},
|
||||
|
||||
applyPage() {
|
||||
const start = (this.pageNum - 1) * this.pageSize
|
||||
this.tableData = this.allData.slice(start, start + this.pageSize)
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
listTeachingPlan(this.buildSearchParams()).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(current) {
|
||||
this.pageNum = current
|
||||
this.applyPage()
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.applyPage()
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/** 日期格式化 */
|
||||
@@ -244,7 +250,7 @@ export default {
|
||||
return cellValue ? String(cellValue).substring(0, 10) : ''
|
||||
},
|
||||
|
||||
// ==================== 文件上传与缓存操作 ====================
|
||||
// ==================== 文件选择 ====================
|
||||
handleChooseFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
@@ -253,36 +259,68 @@ export default {
|
||||
const target = event.target
|
||||
const file = target.files && target.files[0]
|
||||
if (file) {
|
||||
this.selectedFile = file
|
||||
this.selectedFileName = file.name
|
||||
this.$message.success(`已选择文件:${file.name}`)
|
||||
} else {
|
||||
this.selectedFile = null
|
||||
this.selectedFileName = '未选择任何文件'
|
||||
}
|
||||
},
|
||||
|
||||
// TODO: 后端接口未提供,以下操作均为前端模拟;接口就绪后替换为对应接口
|
||||
// ==================== 下载模板 ====================
|
||||
handleDownloadTemplate() {
|
||||
this.$message.success('下载课程表数据文件模板(前端模拟)')
|
||||
downloadTeachingPlanTemplate().then(blob => {
|
||||
this.downloadBlob(blob, '教学实施计划导入模板.xlsx')
|
||||
this.$message.success('模板下载成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
handleUploadToCache() {
|
||||
if (this.selectedFileName === '未选择任何文件') {
|
||||
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)
|
||||
},
|
||||
|
||||
// ==================== 导入到系统 ====================
|
||||
handleImportToSystem() {
|
||||
if (!this.selectedFile) {
|
||||
this.$message.warning('请先选择文件')
|
||||
return
|
||||
}
|
||||
this.$message.success('上传数据至缓存(前端模拟)')
|
||||
this.importing = true
|
||||
importTeachingPlan(this.selectedFile).then(res => {
|
||||
const count = res && res.data
|
||||
if (count !== null && count !== undefined) {
|
||||
this.$message.success(`导入成功,共 ${count} 条记录`)
|
||||
} else {
|
||||
this.$message.success((res && res.msg) || '导入成功')
|
||||
}
|
||||
this.selectedFile = null
|
||||
this.selectedFileName = '未选择任何文件'
|
||||
this.$refs.fileInputRef && (this.$refs.fileInputRef.value = '')
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.importing = false
|
||||
})
|
||||
},
|
||||
|
||||
handleDeleteCache() {
|
||||
this.$message.success('删除缓存数据(前端模拟)')
|
||||
// ==================== 缓存操作(后端暂未提供) ====================
|
||||
handleUploadToCache() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleCheckCache() {
|
||||
this.$message.success('检查缓存数据(前端模拟)')
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleImportToSystem() {
|
||||
this.$message.success('缓存数据导入到系统(前端模拟)')
|
||||
handleDeleteCache() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,38 +25,38 @@
|
||||
<el-tabs v-model="activeTab">
|
||||
<!-- 课程成绩 -->
|
||||
<el-tab-pane label="课程成绩" name="grades">
|
||||
<el-table v-loading="loading" :data="gradesData" stripe border>
|
||||
<el-table v-loading="loading" :data="gradesData" stripe border style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="xybh" label="学员编号" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="kmbh" label="科目编号" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="klx" label="课类型" width="90" align="center" />
|
||||
<el-table-column prop="kscj" label="考试成绩" width="90" align="center" />
|
||||
<el-table-column prop="pscj" label="平时成绩" width="90" align="center" />
|
||||
<el-table-column prop="zzcj" label="最终成绩" width="90" align="center" />
|
||||
<el-table-column prop="bkcj" label="补考成绩" width="90" align="center" />
|
||||
<el-table-column prop="bkcs" label="补考次数" width="90" align="center" />
|
||||
<el-table-column prop="ksqk" label="考试情况" width="90" align="center" />
|
||||
<el-table-column prop="qwxf" label="期望学分" width="90" align="center" />
|
||||
<el-table-column prop="ytg" label="已通过" width="80" align="center" />
|
||||
<el-table-column prop="nd" label="年度" width="80" align="center" />
|
||||
<el-table-column prop="xybh" label="学员编号" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="kmbh" label="科目编号" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="klx" label="课类型" min-width="90" align="center" />
|
||||
<el-table-column prop="kscj" label="考试成绩" min-width="90" align="center" />
|
||||
<el-table-column prop="pscj" label="平时成绩" min-width="90" align="center" />
|
||||
<el-table-column prop="zzcj" label="最终成绩" min-width="90" align="center" />
|
||||
<el-table-column prop="bkcj" label="补考成绩" min-width="90" align="center" />
|
||||
<el-table-column prop="bkcs" label="补考次数" min-width="90" align="center" />
|
||||
<el-table-column prop="ksqk" label="考试情况" min-width="90" align="center" />
|
||||
<el-table-column prop="qwxf" label="期望学分" min-width="90" align="center" />
|
||||
<el-table-column prop="ytg" label="已通过" min-width="80" align="center" />
|
||||
<el-table-column prop="nd" label="年度" min-width="80" align="center" />
|
||||
</el-table>
|
||||
<el-empty v-if="!loading && gradesData.length === 0" description="暂无课程成绩数据" :image-size="60" />
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 课程过程成绩 -->
|
||||
<el-tab-pane label="课程过程成绩" name="process">
|
||||
<el-table v-loading="loading" :data="processGradesData" stripe border>
|
||||
<el-table v-loading="loading" :data="processGradesData" stripe border style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="xybh" label="学员编号" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="kmbh" label="科目编号" width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="klx" label="课类型" width="90" align="center" />
|
||||
<el-table-column prop="yscj" label="原始成绩" width="90" align="center" />
|
||||
<el-table-column prop="zzcj" label="最终成绩" width="90" align="center" />
|
||||
<el-table-column prop="bkcj1" label="补考1" width="80" align="center" />
|
||||
<el-table-column prop="bkcj2" label="补考2" width="80" align="center" />
|
||||
<el-table-column prop="bkcj3" label="补考3" width="80" align="center" />
|
||||
<el-table-column prop="ksqk" label="考试情况" width="90" align="center" />
|
||||
<el-table-column prop="nd" label="年度" width="80" align="center" />
|
||||
<el-table-column prop="xybh" label="学员编号" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="kmbh" label="科目编号" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column prop="klx" label="课类型" min-width="90" align="center" />
|
||||
<el-table-column prop="yscj" label="原始成绩" min-width="90" align="center" />
|
||||
<el-table-column prop="zzcj" label="最终成绩" min-width="90" align="center" />
|
||||
<el-table-column prop="bkcj1" label="补考1" min-width="80" align="center" />
|
||||
<el-table-column prop="bkcj2" label="补考2" min-width="80" align="center" />
|
||||
<el-table-column prop="bkcj3" label="补考3" min-width="80" align="center" />
|
||||
<el-table-column prop="ksqk" label="考试情况" min-width="90" align="center" />
|
||||
<el-table-column prop="nd" label="年度" min-width="80" align="center" />
|
||||
</el-table>
|
||||
<el-empty v-if="!loading && processGradesData.length === 0" description="暂无课程过程成绩数据" :image-size="60" />
|
||||
</el-tab-pane>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,178 +1,426 @@
|
||||
<template>
|
||||
<div class="app-container status-change-page">
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<!-- ==================== 1. 查询条件 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="140px" class="search-form">
|
||||
<el-form ref="searchFormRef" :model="searchForm" label-width="90px" class="search-form">
|
||||
<el-row :gutter="24">
|
||||
<!-- 左栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="年级">
|
||||
<el-input v-model="searchForm.nj" placeholder="请输入年级" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="专业">
|
||||
<el-input v-model="searchForm.zy" placeholder="请输入专业" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxlxChecked">培训类型</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxlx" class="w-full" :disabled="!searchForm.pxlxChecked">
|
||||
<el-option v-for="item in pxlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxccChecked">培训层次</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxcc" class="w-full" :disabled="!searchForm.pxccChecked">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学号">
|
||||
<el-input v-model="searchForm.xh" placeholder="请输入学号" clearable />
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="编号">
|
||||
<el-input v-model="searchForm.bh" placeholder="请输入编号" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="队别">
|
||||
<el-input v-model="searchForm.db" placeholder="请输入队别" clearable />
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="学员编号">
|
||||
<el-input v-model="searchForm.xybh" placeholder="请输入学员编号" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
<el-form-item label="班次">
|
||||
<el-input v-model="searchForm.bc" placeholder="请输入班次" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.sqlbChecked">学籍异动申请类别</el-checkbox></template>
|
||||
<el-select v-model="searchForm.sqlb" class="w-full" :disabled="!searchForm.sqlbChecked">
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="申请类型">
|
||||
<el-select v-model="searchForm.sqlx" placeholder="请选择申请类型" clearable class="w-full">
|
||||
<el-option v-for="item in applyTypeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.sqztChecked">学籍异动申请状态</el-checkbox></template>
|
||||
<el-select v-model="searchForm.sqzt" class="w-full" :disabled="!searchForm.sqztChecked">
|
||||
<el-option v-for="item in applyStatusOptions" :key="item" :label="item" :value="item" />
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="searchForm.zt" placeholder="请选择状态" clearable class="w-full">
|
||||
<el-option v-for="(item, key) in statusMap" :key="key" :label="item.label" :value="Number(key)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="searchForm.xm" placeholder="请输入姓名" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="search-tip">注意:勾选"选择框"表示启用该项对应的查询条件;文本输入框非空白表示启用对应的查询条件。</div>
|
||||
<div class="search-actions">
|
||||
<el-button class="gray-btn" @click="handleSearch">查询</el-button>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="24" class="search-actions">
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 审核意见区域 ==================== -->
|
||||
<el-card shadow="never" class="opinion-card">
|
||||
<div class="opinion-row">
|
||||
<span class="opinion-label">审核意见:</span>
|
||||
<el-input v-model="auditOpinion" placeholder="请输入审核意见" clearable class="opinion-input" />
|
||||
<el-button type="primary" @click="handleBatchAudit">提交审核意见</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 列表标题 ==================== -->
|
||||
<div class="list-title">学籍异动申请审核列表</div>
|
||||
|
||||
<!-- ==================== 4. 数据表格区域 ==================== -->
|
||||
<!-- ==================== 2. 列表 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table :data="tableData" stripe border @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column prop="xhName" label="学号姓名" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="bcxx" label="班次信息" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="applyType" label="申请类型" width="90" align="center" />
|
||||
<el-table-column prop="reason" label="事由" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="time" label="时间" width="110" align="center" />
|
||||
<el-table-column prop="auditOpinion" label="审核意见" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="90" align="center" />
|
||||
<el-table-column prop="change" label="学籍异动" width="90" align="center" />
|
||||
<el-table-column label="操作" width="130" align="center" fixed="right">
|
||||
<div class="table-header">
|
||||
<span class="table-title">学籍异动申请列表:</span>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增学籍异动申请</el-button>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="bh" label="编号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="xybh" label="学员编号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sqlx" label="申请类型" width="100" align="center" />
|
||||
<el-table-column prop="sy" label="事由" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="bz" label="备注" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" class="text-primary" @click="handleAudit(row)">审核</el-button>
|
||||
<el-button type="text" size="small" class="text-primary" @click="handleView(row)">查看</el-button>
|
||||
<el-tag :type="statusTagType(row.zt)" size="mini" effect="light">{{ statusLabel(row.zt) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提交时间" width="160" align="center">
|
||||
<template slot-scope="{ row }">{{ row.tjsj ? fmtDateTime(row.tjsj) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="160" align="center">
|
||||
<template slot-scope="{ row }">{{ row.cjsj ? fmtDateTime(row.cjsj) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改时间" width="160" align="center">
|
||||
<template slot-scope="{ row }">{{ row.xgsj ? fmtDateTime(row.xgsj) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="230" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button v-if="!row.tjsj" type="text" size="small" icon="el-icon-upload2" @click="handleSubmit(row)">提交</el-button>
|
||||
<el-button v-else type="text" size="small" icon="el-icon-check" disabled>已提交</el-button>
|
||||
<el-button type="text" size="small" icon="el-icon-view" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" icon="el-icon-edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!loading && tableData.length === 0" description="暂无学籍异动申请数据" :image-size="60" />
|
||||
|
||||
<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>
|
||||
|
||||
<!-- ==================== 3. 新增/编辑对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="formDialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => formDialogVisible = val"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="formRules" label-width="110px" class="add-form">
|
||||
<el-form-item label="编号" prop="bh">
|
||||
<el-input v-model="form.bh" placeholder="请输入编号" :disabled="!isAdd" />
|
||||
</el-form-item>
|
||||
<el-form-item label="学员编号" prop="xybh">
|
||||
<el-input v-model="form.xybh" placeholder="请输入学员编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="申请类型" prop="sqlx">
|
||||
<el-select v-model="form.sqlx" placeholder="请选择申请类型" class="w-full">
|
||||
<el-option v-for="item in applyTypeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="事由" prop="sy">
|
||||
<el-input v-model="form.sy" type="textarea" :rows="3" placeholder="请输入事由" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="zt">
|
||||
<el-select v-model="form.zt" placeholder="请选择状态" class="w-full">
|
||||
<el-option v-for="(item, key) in statusMap" :key="key" :label="item.label" :value="Number(key)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="formDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="formSaving" @click="handleFormSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 4. 详情对话框 ==================== -->
|
||||
<el-dialog title="学籍异动申请详情" :visible="detailDialogVisible" width="760px" :close-on-click-modal="false"
|
||||
@update:visible="val => detailDialogVisible = val">
|
||||
<div v-loading="detailLoading" class="detail-body">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailForm.bh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员编号">{{ detailForm.xybh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请类型">{{ detailForm.sqlx || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="statusTagType(detailForm.zt)" size="mini">{{ statusLabel(detailForm.zt) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="事由" :span="2">{{ detailForm.sy || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ detailForm.bz || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ detailForm.cjsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="修改时间">{{ detailForm.xgsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提交时间">{{ detailForm.tjsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员队审核意见">{{ detailForm.xydshyj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员队干部编号">{{ detailForm.xydgbbh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员队干部审核时间">{{ detailForm.xydshsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="管理员账户编号">{{ detailForm.glyzhbh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="管理员审核意见">{{ detailForm.glyshyj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="管理员审核时间">{{ detailForm.glyshsj || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 模拟列表数据(后端接口未提供,接口就绪后可删除并改为接口加载)
|
||||
const mockTableData = [
|
||||
{ id: 1, xhName: '2025010101 张三', bcxx: '2025级炮兵装备运用54队5区队', applyType: '退学', reason: '身体原因', time: '2026-08-20', auditOpinion: '待审核', status: '拟制', change: '退学' },
|
||||
{ id: 2, xhName: '2025010102 李四', bcxx: '2025级通信工程32队1区队', applyType: '休学', reason: '家庭原因', time: '2026-08-21', auditOpinion: '同意', status: '待审核', change: '休学' },
|
||||
{ id: 3, xhName: '2024010101 王五', bcxx: '2024级军事指挥51队2区队', applyType: '留级', reason: '成绩不达标', time: '2026-08-22', auditOpinion: '', status: '拟制', change: '留级' }
|
||||
]
|
||||
import {
|
||||
listApplication,
|
||||
getApplication,
|
||||
addApplication,
|
||||
updateApplication,
|
||||
delApplication
|
||||
} from '@/api/studentRecords/application'
|
||||
|
||||
export default {
|
||||
name: 'StatusChangeIndex',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 下拉选项(字典数据,接口就绪后可由后端字典加载) ====================
|
||||
pxlxOptions: ['军官基础教育', '士兵职业教育', '研究生教育', '其他'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
applyTypeOptions: ['退学', '休学', '留级', '复学', '转专业'],
|
||||
applyStatusOptions: ['拟制', '待审核', '已通过', '已驳回'],
|
||||
// ==================== 申请类型选项(学籍异动) ====================
|
||||
applyTypeOptions: ['休学', '复学', '退学', '转学', '留级', '转专业'],
|
||||
|
||||
// ==================== 状态映射:0-待审核 1-已审核 2-驳回等 ====================
|
||||
statusMap: {
|
||||
0: { label: '待审核', type: 'warning' },
|
||||
1: { label: '已审核', type: 'success' },
|
||||
2: { label: '驳回', type: 'danger' }
|
||||
},
|
||||
|
||||
// ==================== 查询条件 ====================
|
||||
searchForm: {
|
||||
nj: '', zy: '', pxlxChecked: false, pxlx: '军官基础教育', pxccChecked: false, pxcc: '无', xh: '',
|
||||
db: '', bc: '', sqlbChecked: false, sqlb: '退学', sqztChecked: false, sqzt: '拟制', xm: ''
|
||||
bh: '',
|
||||
xybh: '',
|
||||
sqlx: '',
|
||||
zt: undefined
|
||||
},
|
||||
|
||||
// ==================== 审核意见 ====================
|
||||
auditOpinion: '',
|
||||
|
||||
// ==================== 数据表格 ====================
|
||||
// ==================== 列表数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
selectedRows: []
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
|
||||
// ==================== 新增/编辑 ====================
|
||||
formDialogVisible: false,
|
||||
dialogTitle: '新增学籍异动申请',
|
||||
isAdd: true,
|
||||
formSaving: false,
|
||||
form: this.createEmptyForm(),
|
||||
formRules: {
|
||||
bh: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||
xybh: [{ required: true, message: '请输入学员编号', trigger: 'blur' }],
|
||||
sqlx: [{ required: true, message: '请选择申请类型', trigger: 'change' }],
|
||||
sy: [{ required: true, message: '请输入事由', trigger: 'blur' }],
|
||||
zt: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
||||
},
|
||||
|
||||
// ==================== 详情 ====================
|
||||
detailDialogVisible: false,
|
||||
detailLoading: false,
|
||||
detailForm: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadData()
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// ==================== 列表加载 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getStatusChangeList
|
||||
loadData() {
|
||||
this.tableData = mockTableData.slice()
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
xybh: '',
|
||||
sqlx: '',
|
||||
sy: '',
|
||||
bz: '',
|
||||
zt: 0
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 状态展示 ====================
|
||||
// 统一格式化后端 LocalDateTime(去除 T、截断到秒)
|
||||
fmtDateTime(val) {
|
||||
if (val === null || val === undefined || val === '') return ''
|
||||
return String(val).replace('T', ' ').slice(0, 19)
|
||||
},
|
||||
statusLabel(zt) {
|
||||
const item = this.statusMap[zt]
|
||||
return item ? item.label : (zt !== null && zt !== undefined ? String(zt) : '-')
|
||||
},
|
||||
statusTagType(zt) {
|
||||
const item = this.statusMap[zt]
|
||||
return item ? item.type : 'info'
|
||||
},
|
||||
|
||||
// ==================== 查询列表 ====================
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = {
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}
|
||||
// 等值筛选,留空不传
|
||||
;['bh', 'xybh', 'sqlx'].forEach(key => {
|
||||
const value = this.searchForm[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
params[key] = String(value).trim()
|
||||
}
|
||||
})
|
||||
if (this.searchForm.zt !== undefined && this.searchForm.zt !== '' && this.searchForm.zt !== null) {
|
||||
params.zt = this.searchForm.zt
|
||||
}
|
||||
listApplication(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
// TODO: 后端接口未提供,查询为前端模拟;接口就绪后替换为后端查询
|
||||
handleSearch() {
|
||||
this.loadData()
|
||||
this.$message.success('查询完成(前端模拟)')
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
handleReset() {
|
||||
this.$refs.searchFormRef.resetFields()
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// TODO: 后端接口未提供,审核为前端模拟;接口就绪后替换为 auditStatusChange
|
||||
handleAudit(row) {
|
||||
this.$message.info(`审核「${row.xhName}」的申请(前端模拟)`)
|
||||
handlePageChange(current) {
|
||||
this.pageNum = current
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// TODO: 后端接口未提供,查看为前端模拟;接口就绪后替换为 getStatusChangeDetail
|
||||
handleView(row) {
|
||||
this.$message.info(`查看「${row.xhName}」的申请详情(前端模拟)`)
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/** 批量审核所选 */
|
||||
// TODO: 后端接口未提供,批量审核为前端模拟;接口就绪后替换为 batchAuditStatusChange
|
||||
handleBatchAudit() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择申请记录')
|
||||
return
|
||||
// ==================== 新增/编辑 ====================
|
||||
handleAdd() {
|
||||
this.isAdd = true
|
||||
this.dialogTitle = '新增学籍异动申请'
|
||||
this.form = this.createEmptyForm()
|
||||
this.formDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
this.isAdd = false
|
||||
this.dialogTitle = '编辑学籍异动申请'
|
||||
this.form = this.createEmptyForm()
|
||||
this.formDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
getApplication(row.bh).then(response => {
|
||||
const data = response.data || {}
|
||||
this.form = {
|
||||
bh: data.bh || '',
|
||||
xybh: data.xybh || '',
|
||||
sqlx: data.sqlx || '',
|
||||
sy: data.sy || '',
|
||||
bz: data.bz || '',
|
||||
zt: data.zt !== null && data.zt !== undefined ? Number(data.zt) : 0
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
buildPayload() {
|
||||
const f = this.form
|
||||
const payload = {
|
||||
bh: f.bh,
|
||||
xybh: f.xybh,
|
||||
sqlx: f.sqlx,
|
||||
sy: f.sy,
|
||||
zt: Number(f.zt)
|
||||
}
|
||||
if (!this.auditOpinion.trim()) {
|
||||
this.$message.warning('请输入审核意见')
|
||||
return
|
||||
// 备注留空则移除
|
||||
if (f.bz !== '' && f.bz !== null && f.bz !== undefined) {
|
||||
payload.bz = f.bz
|
||||
}
|
||||
const names = this.selectedRows.map((r) => r.xhName).join('、')
|
||||
this.$message.success(`已对「${names}」提交审核意见(前端模拟)`)
|
||||
return payload
|
||||
},
|
||||
|
||||
handleFormSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) return
|
||||
this.formSaving = true
|
||||
const payload = this.buildPayload()
|
||||
const request = this.isAdd ? addApplication(payload) : updateApplication(payload)
|
||||
request.then(() => {
|
||||
this.$message.success(this.isAdd ? '新增成功' : '修改成功')
|
||||
this.formDialogVisible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.formSaving = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 提交 ====================
|
||||
// 无独立提交接口,通过编辑接口写入提交时间 tjsj(zt 保持原值不变)
|
||||
formatNow() {
|
||||
const d = new Date()
|
||||
const pad = n => String(n).padStart(2, '0')
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||
},
|
||||
|
||||
handleSubmit(row) {
|
||||
this.$confirm(`确定要提交编号为「${row.bh}」的学籍异动申请吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const payload = {
|
||||
bh: row.bh,
|
||||
xybh: row.xybh,
|
||||
sqlx: row.sqlx,
|
||||
sy: row.sy,
|
||||
zt: row.zt !== null && row.zt !== undefined ? Number(row.zt) : 0,
|
||||
tjsj: this.formatNow()
|
||||
}
|
||||
if (row.bz) {
|
||||
payload.bz = row.bz
|
||||
}
|
||||
return updateApplication(payload)
|
||||
}).then(() => {
|
||||
this.$message.success('提交成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 删除 ====================
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除编号为「${row.bh}」的学籍异动申请吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return delApplication(row.bh)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 详情 ====================
|
||||
handleDetail(row) {
|
||||
this.detailDialogVisible = true
|
||||
this.detailLoading = true
|
||||
this.detailForm = {}
|
||||
getApplication(row.bh).then(response => {
|
||||
this.detailForm = response.data || {}
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,87 +434,61 @@ export default {
|
||||
.status-change-page {
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 8px;
|
||||
|
||||
.search-tip {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
.search-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.opinion-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.opinion-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.opinion-label {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.opinion-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-title {
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
.el-table {
|
||||
width: 100%;
|
||||
.table-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
::v-deep(.cell) {
|
||||
font-size: 12px;
|
||||
.table-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: #409eff;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.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;
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.add-form {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,67 +6,11 @@
|
||||
<el-row :gutter="24">
|
||||
<!-- 左栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="年级">
|
||||
<el-input v-model="searchForm.nj" placeholder="请输入年级" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="专业">
|
||||
<el-input v-model="searchForm.zy" placeholder="请输入专业" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxlxChecked">培训类型</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxlx" class="w-full" :disabled="!searchForm.pxlxChecked">
|
||||
<el-option v-for="item in pxlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxccChecked">培训层次</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxcc" class="w-full" :disabled="!searchForm.pxccChecked">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学号">
|
||||
<el-input v-model="searchForm.xh" placeholder="请输入学号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="证件号码">
|
||||
<el-input v-model="searchForm.zjhm" placeholder="请输入证件号码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="政治面貌">
|
||||
<el-input v-model="searchForm.zzmm" placeholder="请输入政治面貌" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="籍贯">
|
||||
<el-input v-model="searchForm.jg" placeholder="请输入籍贯" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="学位">
|
||||
<el-input v-model="searchForm.xw" placeholder="请输入学位" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="原部职别">
|
||||
<el-input v-model="searchForm.ybzb" placeholder="请输入原部职别" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="标签">
|
||||
<el-input v-model="searchForm.bq" placeholder="请输入标签" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.xjydEnabled">学籍异动状态</el-checkbox></template>
|
||||
<el-radio-group v-model="searchForm.xjyd" :disabled="!searchForm.xjydEnabled">
|
||||
<el-radio :label="'无异动'">无异动</el-radio>
|
||||
<el-radio :label="'异动'">异动</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.ksqkEnabled">考试情况</el-checkbox></template>
|
||||
<el-radio-group v-model="searchForm.ksqk" :disabled="!searchForm.ksqkEnabled">
|
||||
<el-radio :label="'正常'">正常</el-radio>
|
||||
<el-radio :label="'异动'">异动</el-radio>
|
||||
<el-radio :label="'旷考'">旷考</el-radio>
|
||||
<el-radio :label="'作弊'">作弊</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="不及格门数">
|
||||
<div class="range-control">
|
||||
<el-input v-model="searchForm.bjgmMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="searchForm.bjgmMax" placeholder="0" />
|
||||
</div>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="searchForm.xm" placeholder="请输入姓名" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.xbEnabled">性别</el-checkbox></template>
|
||||
@@ -75,84 +19,49 @@
|
||||
<el-radio :label="'女'">女</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.zcztEnabled">注册状态</el-checkbox></template>
|
||||
<el-radio-group v-model="searchForm.zczt" :disabled="!searchForm.zcztEnabled">
|
||||
<el-radio :label="'已注册'">已注册</el-radio>
|
||||
<el-radio :label="'未注册'">未注册</el-radio>
|
||||
</el-radio-group>
|
||||
<el-form-item label="证件号码">
|
||||
<el-input v-model="searchForm.zjhm" placeholder="请输入证件号码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="政治面貌">
|
||||
<el-input v-model="searchForm.zzmm" placeholder="请输入政治面貌" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="民族">
|
||||
<el-input v-model="searchForm.mz" placeholder="请输入民族" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="籍贯">
|
||||
<el-input v-model="searchForm.jg" placeholder="请输入籍贯" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="学位">
|
||||
<el-input v-model="searchForm.xw" placeholder="请输入学位" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="队别">
|
||||
<el-input v-model="searchForm.db" placeholder="请输入队别" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="班次">
|
||||
<el-input v-model="searchForm.bc" placeholder="请输入班次" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxlx2Checked">培训类型2</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxlx2" class="w-full" :disabled="!searchForm.pxlx2Checked">
|
||||
<el-option v-for="item in pxlx2Options" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义分类">
|
||||
<el-input v-model="searchForm.zdyfl" placeholder="请输入自定义分类" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="searchForm.xm" placeholder="请输入姓名" clearable />
|
||||
<el-form-item label="原部职别">
|
||||
<el-input v-model="searchForm.ybzb" placeholder="请输入原部职别" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证号">
|
||||
<el-input v-model="searchForm.sfzh" placeholder="请输入身份证号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="民族">
|
||||
<el-input v-model="searchForm.mz" placeholder="请输入民族" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="文化程度">
|
||||
<el-input v-model="searchForm.whcd" placeholder="请输入文化程度" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="本科毕业院校">
|
||||
<el-input v-model="searchForm.bkbyyx" placeholder="请输入本科毕业院校" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属战区">
|
||||
<el-input v-model="searchForm.sszq" placeholder="请输入所属战区" clearable />
|
||||
<el-form-item label="标签">
|
||||
<el-input v-model="searchForm.bq" placeholder="请输入标签" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="奖惩情况">
|
||||
<el-input v-model="searchForm.jcqk" placeholder="请输入奖惩情况" clearable />
|
||||
<el-form-item label="联系电话">
|
||||
<el-input v-model="searchForm.lxdh" placeholder="请输入联系电话" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.txEnabled">退学状态</el-checkbox></template>
|
||||
<el-radio-group v-model="searchForm.tx" :disabled="!searchForm.txEnabled">
|
||||
<el-radio :label="'未退学'">未退学</el-radio>
|
||||
<el-radio :label="'退学'">退学</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="曾不及格门数">
|
||||
<div class="range-control">
|
||||
<el-input v-model="searchForm.lbjgmMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="searchForm.lbjgmMax" placeholder="0" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="补考不及格门数">
|
||||
<div class="range-control">
|
||||
<el-input v-model="searchForm.bkcljgmMin" placeholder="0" />
|
||||
<span class="range-sep">至</span>
|
||||
<el-input v-model="searchForm.bkcljgmMax" placeholder="0" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.gljgChecked">管理机构</el-checkbox></template>
|
||||
<el-select v-model="searchForm.gljg" class="w-full" :disabled="!searchForm.gljgChecked">
|
||||
<el-option v-for="item in gljgOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-form-item label="通信地址">
|
||||
<el-input v-model="searchForm.txdz" placeholder="请输入通信地址" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="search-tip">注意:勾选"选择框"表示启用该项对应的查询条件;文本输入框非空白表示启用对应的查询条件。</div>
|
||||
<div class="search-actions">
|
||||
<el-button class="gray-btn" @click="handleSearch">查询</el-button>
|
||||
</div>
|
||||
@@ -312,21 +221,11 @@ export default {
|
||||
name: 'StudentInfoIndex',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 下拉选项(字典数据,接口就绪后可由后端字典加载) ====================
|
||||
pxlxOptions: ['军官基础教育', '士兵职业教育', '研究生教育', '其他'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
pxlx2Options: ['其他', '军官基础教育', '任职培训', '研究生教育'],
|
||||
gljgOptions: ['教务处', '教研室1', '教研室2'],
|
||||
|
||||
// ==================== 查询条件 ====================
|
||||
// 仅保留后端 XYXX 实体支持的字段:/student-records/list 会按实体字段动态构建查询条件
|
||||
searchForm: {
|
||||
nj: '', zy: '', pxlxChecked: false, pxlx: '军官基础教育', pxccChecked: false, pxcc: '无', xh: '', zjhm: '', zzmm: '',
|
||||
jg: '', xw: '', ybzb: '', bq: '', xjydEnabled: false, xjyd: '无异动', ksqkEnabled: false, ksqk: '正常',
|
||||
bjgmMin: '', bjgmMax: '', xbEnabled: false, xb: '男', zcztEnabled: false, zczt: '已注册',
|
||||
db: '', bc: '', pxlx2Checked: false, pxlx2: '其他', zdyfl: '', xm: '', sfzh: '', mz: '', whcd: '',
|
||||
bkbyyx: '', sszq: '', jcqk: '', txEnabled: false, tx: '未退学', lbjgmMin: '', lbjgmMax: '',
|
||||
bkcljgmMin: '', bkcljgmMax: '', gljgChecked: false, gljg: '教务处',
|
||||
xylb: ''
|
||||
xh: '', xm: '', xbEnabled: false, xb: '男', zjhm: '', zzmm: '', mz: '', jg: '', xw: '',
|
||||
ybzb: '', sfzh: '', whcd: '', bkbyyx: '', bq: '', lxdh: '', txdz: ''
|
||||
},
|
||||
|
||||
// ==================== 数据表格 ====================
|
||||
@@ -406,33 +305,14 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
/** 组装查询参数:文本非空才传,勾选启用的字段才传,门数范围二者其一非空才传 */
|
||||
/** 组装查询参数:仅传后端 XYXX 实体支持的字符串字段,空值忽略 */
|
||||
buildQueryParams(params) {
|
||||
const textFields = ['xh', 'xm', 'sfzh', 'zjhm', 'zzmm', 'mz', 'jg', 'xw', 'ybzb', 'bq', 'whcd', 'bkbyyx', 'xylb', 'zdyfl', 'nj', 'zy', 'db', 'bc', 'sszq', 'jcqk']
|
||||
const textFields = ['xh', 'xm', 'zjhm', 'zzmm', 'mz', 'jg', 'xw', 'ybzb', 'sfzh', 'whcd', 'bkbyyx', 'bq', 'lxdh', 'txdz']
|
||||
textFields.forEach(key => {
|
||||
const v = this.searchForm[key]
|
||||
if (v !== '' && v !== null && v !== undefined) params[key] = v.trim()
|
||||
})
|
||||
if (this.searchForm.pxlxChecked) params.pxlx = this.searchForm.pxlx
|
||||
if (this.searchForm.pxccChecked) params.pxcc = this.searchForm.pxcc
|
||||
if (this.searchForm.pxlx2Checked) params.pxlx2 = this.searchForm.pxlx2
|
||||
if (this.searchForm.xjydEnabled) params.xjyd = this.searchForm.xjyd
|
||||
if (this.searchForm.ksqkEnabled) params.ksqk = this.searchForm.ksqk
|
||||
if (this.searchForm.xbEnabled) params.xb = this.searchForm.xb
|
||||
if (this.searchForm.zcztEnabled) params.zczt = this.searchForm.zczt
|
||||
if (this.searchForm.txEnabled) params.txzt = this.searchForm.tx
|
||||
if (this.searchForm.gljgChecked) params.gljg = this.searchForm.gljg
|
||||
const ranges = [
|
||||
['bjgmMin', 'bjgmMax'],
|
||||
['lbjgmMin', 'lbjgmMax'],
|
||||
['bkcljgmMin', 'bkcljgmMax']
|
||||
]
|
||||
ranges.forEach(([minKey, maxKey]) => {
|
||||
if (this.searchForm[minKey] !== '' || this.searchForm[maxKey] !== '') {
|
||||
params[minKey] = this.searchForm[minKey]
|
||||
params[maxKey] = this.searchForm[maxKey]
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 查询/分页 ====================
|
||||
|
||||
@@ -1,15 +1,256 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<placeholder-page title="学员学籍预警结果" icon="checkbox"
|
||||
description="用于查看学员学籍预警的触发结果列表,支持按条件筛选、导出与处理。" />
|
||||
<div class="app-container warning-result-page">
|
||||
<!-- ==================== 1. 查询条件 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form ref="searchFormRef" :model="searchForm" label-width="110px" class="search-form">
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||
<el-form-item label="年度">
|
||||
<el-input v-model="searchForm.nd" placeholder="请输入年度" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||
<el-form-item label="预警条件编号">
|
||||
<el-input v-model="searchForm.yjtjbh" placeholder="请输入预警条件编号" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||
<el-form-item label="学员编号">
|
||||
<el-input v-model="searchForm.xybh" placeholder="请输入学员编号" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||
<el-form-item label="发布">
|
||||
<el-select v-model="searchForm.fb" placeholder="请选择发布状态" clearable class="w-full">
|
||||
<el-option label="未发布" :value="0" />
|
||||
<el-option label="已发布" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="search-actions-row">
|
||||
<el-col :span="24" class="search-actions">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 列表 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<div class="table-header">
|
||||
<span class="table-title">预警结果列表:</span>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||||
<el-table-column prop="bh" label="编号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="nd" label="年度" width="90" align="center" />
|
||||
<el-table-column prop="yjtjbh" label="预警条件编号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="xybh" label="学员编号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="cjsj" label="创建时间" width="160" show-overflow-tooltip />
|
||||
<el-table-column label="发布" width="90" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-tag :type="Number(row.fb) === 1 ? 'success' : 'info'" size="mini">
|
||||
{{ Number(row.fb) === 1 ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fbsj" label="发布时间" width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" icon="el-icon-view" @click="handleDetail(row)">详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</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>
|
||||
|
||||
<!-- ==================== 3. 详情对话框 ==================== -->
|
||||
<el-dialog title="预警结果详情" :visible="detailDialogVisible" width="560px" :close-on-click-modal="false"
|
||||
@update:visible="val => detailDialogVisible = val">
|
||||
<div v-loading="detailLoading" class="detail-body">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="编号">{{ detailForm.bh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年度">{{ detailForm.nd || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="预警条件编号">{{ detailForm.yjtjbh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员编号">{{ detailForm.xybh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ detailForm.cjsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="发布时间">{{ detailForm.fbsj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="发布">
|
||||
<el-tag :type="Number(detailForm.fb) === 1 ? 'success' : 'info'" size="mini">
|
||||
{{ Number(detailForm.fb) === 1 ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlaceholderPage from "@/components/PlaceholderPage"
|
||||
import {
|
||||
listWarningResult,
|
||||
getWarningResult
|
||||
} from '@/api/studentRecords/warningResult'
|
||||
|
||||
export default {
|
||||
name: "WarningResult",
|
||||
components: { PlaceholderPage }
|
||||
name: 'WarningResult',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 查询条件 ====================
|
||||
searchForm: {
|
||||
nd: '',
|
||||
yjtjbh: '',
|
||||
xybh: '',
|
||||
fb: undefined
|
||||
},
|
||||
|
||||
// ==================== 列表数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
|
||||
// ==================== 详情 ====================
|
||||
detailDialogVisible: false,
|
||||
detailLoading: false,
|
||||
detailForm: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// ==================== 查询列表 ====================
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = {
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}
|
||||
// 文本条件非空时才传
|
||||
;['nd', 'yjtjbh', 'xybh'].forEach(key => {
|
||||
const value = this.searchForm[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
params[key] = String(value).trim()
|
||||
}
|
||||
})
|
||||
// 发布:等值筛选(选中时才传)
|
||||
if (this.searchForm.fb !== undefined && this.searchForm.fb !== '' && this.searchForm.fb !== null) {
|
||||
params.fb = this.searchForm.fb
|
||||
}
|
||||
listWarningResult(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleReset() {
|
||||
this.$refs.searchFormRef.resetFields()
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(current) {
|
||||
this.pageNum = current
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// ==================== 详情 ====================
|
||||
handleDetail(row) {
|
||||
this.detailDialogVisible = true
|
||||
this.detailLoading = true
|
||||
this.detailForm = {}
|
||||
getWarningResult(row.bh).then(response => {
|
||||
this.detailForm = response.data || {}
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.warning-result-page {
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-actions-row {
|
||||
margin-top: 2px;
|
||||
border-top: 1px dashed #ebeef5;
|
||||
padding-top: 14px;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.table-card {
|
||||
.table-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.table-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,22 +6,22 @@
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="专业名称">
|
||||
<el-input v-model="searchForm.zymc" placeholder="请输入专业名称" clearable />
|
||||
<el-input v-model="searchForm.zymc" placeholder="请输入专业名称" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="专业代码">
|
||||
<el-input v-model="searchForm.zydm" placeholder="请输入专业代码" clearable />
|
||||
<el-input v-model="searchForm.zydm" placeholder="请输入专业代码" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="专业方向">
|
||||
<el-input v-model="searchForm.zyfx" placeholder="请输入专业方向" clearable />
|
||||
<el-input v-model="searchForm.zyfx" placeholder="请输入专业方向" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="学年制">
|
||||
<el-input v-model="searchForm.xnz" placeholder="请输入学年制" clearable />
|
||||
<el-input v-model="searchForm.xnz" placeholder="请输入学年制" clearable @keyup.enter.native="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
@@ -41,7 +41,6 @@
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24" class="search-actions">
|
||||
<div class="search-tip">注意:"勾选框" 表示启用该项对应的查询条件。</div>
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
@@ -55,23 +54,25 @@
|
||||
<el-card shadow="never" class="table-card">
|
||||
<div class="table-header">
|
||||
<span class="table-title">学科专业列表:</span>
|
||||
<el-button type="primary" @click="handleAdd">新建学科专业</el-button>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新建学科专业</el-button>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="jxgljgbh" label="教学管理机构" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="xh" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="zydm" label="专业代码" width="85" />
|
||||
<el-table-column prop="zymc" label="专业名称" show-overflow-tooltip />
|
||||
<el-table-column prop="rcpyfaCount" label="在用人才培养方案数" width="180" align="center" />
|
||||
<el-table-column prop="zypyfa" label="在用人才培养方案" width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="zdyfl" label="分类" width="100" align="center" />
|
||||
<el-table-column prop="xylb" label="学员类别" width="100" align="center" />
|
||||
<el-table-column prop="xnz" label="学年制" width="90" align="center" />
|
||||
<el-table-column prop="xqs" label="学期数" width="90" align="center" />
|
||||
<el-table-column prop="zgzy" label="主干专业" width="100" align="center" />
|
||||
<el-table-column label="操作" width="160" align="center" fixed="right">
|
||||
<el-table-column label="序号" width="60" align="center">
|
||||
<template slot-scope="scope">{{ fmtXh(scope.$index) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jxgljgbh" label="教学管理机构" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="zydm" label="专业代码" width="200" />
|
||||
<el-table-column prop="zymc" label="专业名称" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="zdyfl" label="分类" width="150" align="center" />
|
||||
<el-table-column prop="xylb" label="学员类别" width="150" align="center" />
|
||||
<el-table-column prop="xnz" label="学年制" width="120" align="center" />
|
||||
<el-table-column prop="xqs" label="学期数" width="120" align="center" />
|
||||
<el-table-column prop="zgzy" label="主干专业" align="center" />
|
||||
<el-table-column label="操作" width="230" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="small" icon="el-icon-view" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" icon="el-icon-edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button v-if="row.ty === 1" type="text" size="small" class="text-success" @click="handleEnable(row)">
|
||||
启用
|
||||
</el-button>
|
||||
@@ -94,125 +95,160 @@
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 新增学科专业对话框 ==================== -->
|
||||
<!-- ==================== 3. 新增/编辑学科专业对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="addDialogVisible"
|
||||
title="新增学科专业"
|
||||
:visible="formDialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="750px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => addDialogVisible = val"
|
||||
@update:visible="val => formDialogVisible = val"
|
||||
>
|
||||
<el-form :model="addForm" label-width="130px" class="add-form">
|
||||
<el-form ref="formRef" :model="form" label-width="130px" class="add-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="规范名称">
|
||||
<el-input v-model="addForm.gfmc" placeholder="请输入规范名称" />
|
||||
<el-input v-model="form.gfmc" placeholder="请输入规范名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="序号">
|
||||
<el-input v-model="addForm.xh" placeholder="请输入序号" />
|
||||
<el-input-number v-model="form.xh" :min="0" controls-position="right" style="width: 100%" placeholder="请输入序号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业代码">
|
||||
<el-input v-model="addForm.zydm" placeholder="请输入专业代码" />
|
||||
<el-input v-model="form.zydm" placeholder="请输入专业代码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业名称">
|
||||
<el-input v-model="addForm.zymc" placeholder="请输入专业名称" />
|
||||
<el-input v-model="form.zymc" placeholder="请输入专业名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业方向">
|
||||
<el-input v-model="addForm.zyfx" placeholder="请输入专业方向" />
|
||||
<el-input v-model="form.zyfx" placeholder="请输入专业方向" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学年制">
|
||||
<el-input v-model="addForm.xnz" placeholder="请输入学年制" />
|
||||
<el-input v-model="form.xnz" placeholder="请输入学年制" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期数">
|
||||
<el-input v-model="addForm.xqs" placeholder="请输入学期数" />
|
||||
<el-input-number v-model="form.xqs" :min="0" controls-position="right" style="width: 100%" placeholder="请输入学期数" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训层次">
|
||||
<el-input v-model="addForm.pxcc" placeholder="请输入培训层次" />
|
||||
<el-input v-model="form.pxcc" placeholder="请输入培训层次" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训类型">
|
||||
<el-input v-model="addForm.pxlx" placeholder="请输入培训类型" />
|
||||
<el-input v-model="form.pxlx" placeholder="请输入培训类型" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训类型2">
|
||||
<el-input v-model="addForm.pxlx2" placeholder="请输入培训类型2" />
|
||||
<el-input v-model="form.pxlx2" placeholder="请输入培训类型2" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学管理机构编号">
|
||||
<el-input v-model="addForm.jxgljgbh" placeholder="请输入教学管理机构编号" />
|
||||
<el-input v-model="form.jxgljgbh" placeholder="请输入教学管理机构编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学员类别">
|
||||
<el-input v-model="addForm.xylb" placeholder="请输入学员类别" />
|
||||
<el-input v-model="form.xylb" placeholder="请输入学员类别" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="指导分类">
|
||||
<el-input v-model="addForm.zdyfl" placeholder="请输入指导分类" />
|
||||
<el-form-item label="自定义分类">
|
||||
<el-input v-model="form.zdyfl" placeholder="请输入自定义分类" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主干专业">
|
||||
<el-input v-model="addForm.zgzy" placeholder="请输入主干专业" />
|
||||
<el-input v-model="form.zgzy" placeholder="请输入主干专业" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="JSON字段">
|
||||
<el-input v-model="addForm.jsonzd" placeholder="请输入JSON字段" />
|
||||
<el-input v-model="form.jsonzd" placeholder="请输入JSON字段" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="addForm.bz" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="addDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="addSaving" @click="handleAddConfirm">确定</el-button>
|
||||
<el-button @click="formDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="formSaving" @click="handleFormSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 4. 详情对话框 ==================== -->
|
||||
<el-dialog title="学科专业详情" :visible="detailDialogVisible" width="700px" :close-on-click-modal="false"
|
||||
@update:visible="val => detailDialogVisible = val">
|
||||
<div v-loading="detailLoading" class="detail-body">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="规范名称">{{ detailForm.gfmc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="序号">{{ fmtValue(detailForm.xh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业代码">{{ detailForm.zydm || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业名称">{{ detailForm.zymc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业方向">{{ detailForm.zyfx || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学年制">{{ detailForm.xnz || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学期数">{{ fmtValue(detailForm.xqs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训层次">{{ detailForm.pxcc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训类型">{{ detailForm.pxlx || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训类型2">{{ detailForm.pxlx2 || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学管理机构编号">{{ detailForm.jxgljgbh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员类别">{{ detailForm.xylb || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="自定义分类">{{ detailForm.zdyfl || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="主干专业">{{ detailForm.zgzy || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="停用">
|
||||
<el-tag :type="detailForm.ty === 1 ? 'danger' : 'success'" size="mini">
|
||||
{{ detailForm.ty === 1 ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="停用时间">{{ detailForm.tysj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="JSON字段" :span="2">{{ detailForm.jsonzd || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ detailForm.bz || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 模拟学科专业列表数据(后端接口未提供,接口就绪后可删除并改为接口加载)
|
||||
const mockTableData = [
|
||||
{ bsh: 'Z001', jxgljgbh: 'JG001', xh: 1, zydm: '110101', zymc: '军事指挥', rcpyfaCount: 2, zypyfa: '2026版军事指挥人才培养方案', zdyfl: '指挥类', xylb: '生长干部', xnz: '4', xqs: '8', zgzy: '是', ty: 0 },
|
||||
{ bsh: 'Z002', jxgljgbh: 'JG002', xh: 2, zydm: '110102', zymc: '通信工程', rcpyfaCount: 1, zypyfa: '2025版通信工程人才培养方案', zdyfl: '技术类', xylb: '现职干部', xnz: '3', xqs: '6', zgzy: '是', ty: 1 },
|
||||
{ bsh: 'Z003', jxgljgbh: 'JG003', xh: 3, zydm: '110103', zymc: '装备维修', rcpyfaCount: 0, zypyfa: '-', zdyfl: '勤务类', xylb: '士官', xnz: '2', xqs: '4', zgzy: '否', ty: 0 }
|
||||
]
|
||||
import {
|
||||
listDiscipline,
|
||||
getDiscipline,
|
||||
addDiscipline,
|
||||
updateDiscipline,
|
||||
disableDiscipline
|
||||
} from '@/api/subjectMajor/discipline'
|
||||
|
||||
export default {
|
||||
name: 'DisciplineIndex',
|
||||
@@ -231,79 +267,87 @@ export default {
|
||||
// ==================== 列表数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
allData: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
|
||||
// ==================== 新增学科专业 ====================
|
||||
addDialogVisible: false,
|
||||
addSaving: false,
|
||||
addForm: this.createEmptyAddForm()
|
||||
// ==================== 新增/编辑 ====================
|
||||
formDialogVisible: false,
|
||||
dialogTitle: '新增学科专业',
|
||||
isAdd: true,
|
||||
formSaving: false,
|
||||
form: this.createEmptyForm(),
|
||||
|
||||
// ==================== 详情 ====================
|
||||
detailDialogVisible: false,
|
||||
detailLoading: false,
|
||||
detailForm: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
createEmptyAddForm() {
|
||||
/** 序号:按当前页数据索引生成跨页连续的序号 */
|
||||
fmtXh(index) {
|
||||
return (this.pageNum - 1) * this.pageSize + index + 1
|
||||
},
|
||||
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bsh: '',
|
||||
gfmc: '',
|
||||
xh: '',
|
||||
xh: undefined,
|
||||
zydm: '',
|
||||
zymc: '',
|
||||
zyfx: '',
|
||||
xnz: '',
|
||||
xqs: '',
|
||||
xqs: undefined,
|
||||
pxcc: '',
|
||||
pxlx: '',
|
||||
jxgljgbh: '',
|
||||
bz: '',
|
||||
pxlx2: '',
|
||||
jxgljgbh: '',
|
||||
xylb: '',
|
||||
zdyfl: '',
|
||||
jsonzd: '',
|
||||
zgzy: ''
|
||||
zgzy: '',
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 查询列表 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getDisciplineList
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
let records = mockTableData.slice()
|
||||
if (this.searchForm.zymc.trim()) {
|
||||
records = records.filter((item) => (item.zymc || '').includes(this.searchForm.zymc.trim()))
|
||||
const params = {
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}
|
||||
// 状态:勾选「停用」时仅查已停用(ty=1),未勾选则查询全部
|
||||
if (this.searchForm.ty) {
|
||||
params.ty = 1
|
||||
}
|
||||
// 其余文本条件非空时才传
|
||||
;['zymc', 'zydm', 'zyfx', 'xnz', 'pxlx2'].forEach(key => {
|
||||
const value = this.searchForm[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
params[key] = String(value).trim()
|
||||
}
|
||||
if (this.searchForm.zydm.trim()) {
|
||||
records = records.filter((item) => (item.zydm || '').includes(this.searchForm.zydm.trim()))
|
||||
}
|
||||
if (this.searchForm.zyfx.trim()) {
|
||||
records = records.filter((item) => (item.zyfx || '').includes(this.searchForm.zyfx.trim()))
|
||||
}
|
||||
if (this.searchForm.xnz.trim()) {
|
||||
records = records.filter((item) => String(item.xnz || '').includes(this.searchForm.xnz.trim()))
|
||||
}
|
||||
if (this.searchForm.ty) {
|
||||
records = records.filter((item) => item.ty === 1)
|
||||
}
|
||||
this.allData = records
|
||||
this.total = records.length
|
||||
this.applyPage()
|
||||
})
|
||||
listDiscipline(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}, 200)
|
||||
},
|
||||
|
||||
applyPage() {
|
||||
const start = (this.pageNum - 1) * this.pageSize
|
||||
this.tableData = this.allData.slice(start, start + this.pageSize)
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
this.$message.success('查询完成(前端模拟)')
|
||||
},
|
||||
|
||||
handleReset() {
|
||||
@@ -323,47 +367,127 @@ export default {
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// ==================== 新增/编辑 ====================
|
||||
handleAdd() {
|
||||
this.isAdd = true
|
||||
this.dialogTitle = '新增学科专业'
|
||||
this.form = this.createEmptyForm()
|
||||
this.formDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
handleEdit(row) {
|
||||
this.isAdd = false
|
||||
this.dialogTitle = '编辑学科专业'
|
||||
this.form = this.createEmptyForm()
|
||||
this.formDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
getDiscipline(row.bsh).then(response => {
|
||||
const data = response.data || {}
|
||||
this.form = {
|
||||
bsh: data.bsh || '',
|
||||
gfmc: data.gfmc || '',
|
||||
xh: data.xh !== null && data.xh !== undefined ? data.xh : undefined,
|
||||
zydm: data.zydm || '',
|
||||
zymc: data.zymc || '',
|
||||
zyfx: data.zyfx || '',
|
||||
xnz: data.xnz || '',
|
||||
xqs: data.xqs !== null && data.xqs !== undefined ? data.xqs : undefined,
|
||||
pxcc: data.pxcc || '',
|
||||
pxlx: data.pxlx || '',
|
||||
pxlx2: data.pxlx2 || '',
|
||||
jxgljgbh: data.jxgljgbh || '',
|
||||
xylb: data.xylb || '',
|
||||
zdyfl: data.zdyfl || '',
|
||||
jsonzd: data.jsonzd || '',
|
||||
zgzy: data.zgzy || '',
|
||||
bz: data.bz || ''
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
buildPayload() {
|
||||
const f = this.form
|
||||
const payload = {
|
||||
bsh: f.bsh || undefined,
|
||||
gfmc: f.gfmc,
|
||||
zydm: f.zydm,
|
||||
zymc: f.zymc,
|
||||
zyfx: f.zyfx,
|
||||
xnz: f.xnz,
|
||||
pxcc: f.pxcc,
|
||||
pxlx: f.pxlx,
|
||||
pxlx2: f.pxlx2,
|
||||
jxgljgbh: f.jxgljgbh,
|
||||
xylb: f.xylb,
|
||||
zdyfl: f.zdyfl,
|
||||
zgzy: f.zgzy,
|
||||
jsonzd: f.jsonzd,
|
||||
bz: f.bz
|
||||
}
|
||||
// 序号、学期数为数值字段,转为数字后再提交
|
||||
if (f.xh !== '' && f.xh !== null && f.xh !== undefined) {
|
||||
payload.xh = Number(f.xh)
|
||||
}
|
||||
if (f.xqs !== '' && f.xqs !== null && f.xqs !== undefined) {
|
||||
payload.xqs = Number(f.xqs)
|
||||
}
|
||||
return payload
|
||||
},
|
||||
|
||||
handleFormSubmit() {
|
||||
this.formSaving = true
|
||||
const payload = this.buildPayload()
|
||||
const request = this.isAdd ? addDiscipline(payload) : updateDiscipline(payload)
|
||||
request.then(() => {
|
||||
this.$message.success(this.isAdd ? '新增成功' : '修改成功')
|
||||
this.formDialogVisible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.formSaving = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 停用/启用 ====================
|
||||
// TODO: 后端接口未提供,停用/启用为前端模拟;接口就绪后替换为 toggleDiscipline
|
||||
handleDisable(row) {
|
||||
this.$confirm(`确定要停用「${row.zymc || row.zydm || '该专业'}」吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
row.ty = 1
|
||||
this.$message.success('停用成功(前端模拟)')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
handleEnable(row) {
|
||||
this.$confirm(`确定要启用「${row.zymc || row.zydm || '该专业'}」吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
return disableDiscipline(row.bsh)
|
||||
}).then(() => {
|
||||
row.ty = 0
|
||||
this.$message.success('启用成功(前端模拟)')
|
||||
this.$message.success('停用成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 新增学科专业 ====================
|
||||
handleAdd() {
|
||||
this.addForm = this.createEmptyAddForm()
|
||||
this.addDialogVisible = true
|
||||
// 后端暂未提供启用接口,仅作提示
|
||||
handleEnable(row) {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
// TODO: 后端接口未提供,新增为前端模拟;接口就绪后替换为 addDiscipline
|
||||
handleAddConfirm() {
|
||||
this.addSaving = true
|
||||
setTimeout(() => {
|
||||
this.$message.success('新增学科专业成功(前端模拟)')
|
||||
this.addDialogVisible = false
|
||||
this.fetchList()
|
||||
this.addSaving = false
|
||||
}, 300)
|
||||
// ==================== 详情 ====================
|
||||
// 数值字段空值显示为 '-'(保留 0)
|
||||
fmtValue(val) {
|
||||
return val === null || val === undefined || val === '' ? '-' : val
|
||||
},
|
||||
|
||||
handleDetail(row) {
|
||||
this.detailDialogVisible = true
|
||||
this.detailLoading = true
|
||||
this.detailForm = {}
|
||||
getDiscipline(row.bsh).then(response => {
|
||||
this.detailForm = response.data || {}
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="app-container major-page">
|
||||
<!-- ==================== 1. 查询条件 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form ref="searchFormRef" :model="searchForm" label-width="90px" class="search-form">
|
||||
<el-form ref="searchFormRef" :model="searchForm" label-width="140px" class="search-form">
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||
<el-form-item label="专业名称">
|
||||
@@ -72,7 +72,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="序号" width="60" align="center">
|
||||
<template slot-scope="scope">{{ fmtXh(scope.$index) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zydh" label="专业代号" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="zymc" label="专业名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="zyfx" label="专业方向" min-width="120" show-overflow-tooltip />
|
||||
|
||||
@@ -115,8 +115,8 @@ export default {
|
||||
totalWeeks: 0,
|
||||
dateRangeText: '',
|
||||
weeks: [],
|
||||
// 显示控制:默认勾选显示日期;节次全部展示
|
||||
showDate: true,
|
||||
// 显示控制:默认不勾选显示日期;节次全部展示
|
||||
showDate: false,
|
||||
// 事件存储:key = cellKey -> event
|
||||
events: {},
|
||||
loading: false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="app-container teach-semester">
|
||||
<!-- 工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-row :gutter="10" class="semester-toolbar">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新添</el-button>
|
||||
</el-col>
|
||||
@@ -17,62 +17,75 @@
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="semesterList"
|
||||
border
|
||||
:height="tableHeight"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" align="center" width="50" />
|
||||
<el-table-column label="学期名称" align="center" min-width="190">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getSemesterName(scope.row.nd) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前" align="center" width="70">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.dqxq" type="success" size="mini">当前</el-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开学日期" align="center" prop="kxrq" min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatDate(scope.row.kxrq) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束日期" align="center" prop="jsrq" min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatDate(scope.row.jsrq) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="周数" align="center" prop="sdzs" width="70" />
|
||||
<el-table-column label="调课不审批" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.tkbsp ? 'primary' : 'info'" size="mini">{{ scope.row.tkbsp ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="禁止调课" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.jztk ? 'danger' : 'info'" size="mini">{{ scope.row.jztk ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="终结成绩定及格" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.zjcjdjg ? 'primary' : 'info'" size="mini">{{ scope.row.zjcjdjg ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="课时系数方案" align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getCoefficientLabel(scope.row.ksxsfabh) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="锁定时长" align="center" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.sdjldw || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="semester-table-wrap">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="semesterList"
|
||||
border
|
||||
stripe
|
||||
:height="tableHeight"
|
||||
:row-class-name="tableRowClassName"
|
||||
:header-cell-style="{ background: '#F4F8F5', color: '#303133', fontWeight: 600 }"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" align="center" width="50" />
|
||||
<el-table-column label="学期名称" align="center" min-width="190">
|
||||
<template slot-scope="scope">
|
||||
<span class="semester-name">
|
||||
<i v-if="scope.row.dqxq" class="semester-name-icon el-icon-star-on"></i>
|
||||
<span>{{ getSemesterName(scope.row.nd) }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前" align="center" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.dqxq" type="success" effect="dark" size="mini">当前学期</el-tag>
|
||||
<span v-else class="text-muted">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开学日期" align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<span class="date-cell"><i class="el-icon-date"></i>{{ formatDate(scope.row.kxrq) || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束日期" align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<span class="date-cell"><i class="el-icon-date"></i>{{ formatDate(scope.row.jsrq) || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="周数" align="center" prop="sdzs" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.sdzs !== undefined && scope.row.sdzs !== null" type="info" effect="plain" size="mini">{{ scope.row.sdzs }} 周</el-tag>
|
||||
<span v-else class="text-muted">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="调课不审批" align="center" width="116">
|
||||
<template slot-scope="scope">
|
||||
<span :class="boolCellClass(scope.row.tkbsp)">{{ scope.row.tkbsp ? '是' : '否' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="禁止调课" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span :class="boolCellClass(scope.row.jztk)">{{ scope.row.jztk ? '是' : '否' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="终结成绩定及格" align="center" width="132">
|
||||
<template slot-scope="scope">
|
||||
<span :class="boolCellClass(scope.row.zjcjdjg)">{{ scope.row.zjcjdjg ? '是' : '否' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="课时系数方案" align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getCoefficientLabel(scope.row.ksxsfabh) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="锁定时长" align="center" min-width="96">
|
||||
<template slot-scope="scope">
|
||||
<span class="lock-cell">{{ scope.row.sdjldw || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
@@ -335,6 +348,14 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 当前学期行高亮类名 */
|
||||
tableRowClassName({ row }) {
|
||||
return row.dqxq ? 'current-semester-row' : ''
|
||||
},
|
||||
/** 布尔开关单元格样式:是=实心绿点,否=灰色横线标记 */
|
||||
boolCellClass(val) {
|
||||
return val ? 'bool-cell is-true' : 'bool-cell is-false'
|
||||
},
|
||||
/** 多选变化 */
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.nd)
|
||||
@@ -491,8 +512,146 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.teach-semester {
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
/* 页面标题区 */
|
||||
.semester-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding-bottom: 14px;
|
||||
margin-bottom: 14px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.semester-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.title-dot {
|
||||
width: 5px;
|
||||
height: 18px;
|
||||
border-radius: 3px;
|
||||
background: var(--color, #00875A);
|
||||
}
|
||||
|
||||
.semester-subtitle {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
line-height: 1.5;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
/* 工具栏 */
|
||||
.semester-toolbar {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
/* 表格卡片容器 */
|
||||
.semester-table-wrap {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
/* 表头由 header-cell-style 设置底色,这里兜底 */
|
||||
::v-deep .el-table__header th {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 当前学期行高亮:浅绿底 + 左侧加深强调 */
|
||||
::v-deep .el-table .current-semester-row td {
|
||||
background: #F2FAF5;
|
||||
}
|
||||
|
||||
::v-deep .el-table .current-semester-row:hover > td {
|
||||
background: #EAF6EF;
|
||||
}
|
||||
|
||||
::v-deep .el-table .current-semester-row td:first-child {
|
||||
box-shadow: inset 3px 0 0 #00875A;
|
||||
}
|
||||
|
||||
/* 学期名称 + 当前星标 */
|
||||
.semester-name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.semester-name-icon {
|
||||
color: #00875A;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 日期单元格 */
|
||||
.date-cell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: #606266;
|
||||
font-variant-numeric: tabular-nums;
|
||||
|
||||
i {
|
||||
color: #a0a6ad;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 锁定时长 */
|
||||
.lock-cell {
|
||||
background: #F4F6F8;
|
||||
border: 1px solid #EBEEF5;
|
||||
border-radius: 4px;
|
||||
padding: 1px 8px;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 布尔开关:实心圆点 + 是/否 */
|
||||
.bool-cell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.is-true {
|
||||
color: #00875A;
|
||||
font-weight: 600;
|
||||
|
||||
&::before {
|
||||
background: #00875A;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-false {
|
||||
color: #C0C4CC;
|
||||
|
||||
&::before {
|
||||
border: 1px solid #CDD1D6;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #C0C4CC;
|
||||
}
|
||||
|
||||
/* 弹窗内表单:防止 label 文字换行、字段拥挤换行 */
|
||||
|
||||
@@ -2,64 +2,28 @@
|
||||
<div class="app-container syllabus-page">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="120px" class="search-form">
|
||||
<el-form :model="searchForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||
<el-row :gutter="32">
|
||||
<!-- 左栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="专业名称">
|
||||
<el-input v-model="searchForm.zymc" placeholder="请输入专业名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="专业方向">
|
||||
<el-input v-model="searchForm.zyfx" placeholder="请输入专业方向" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxlxEnabled">培训类型</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxlx" placeholder="请选择培训类型" clearable class="w-full" :disabled="!searchForm.pxlxEnabled">
|
||||
<el-option v-for="item in pxlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.pxccEnabled">培训层次</el-checkbox></template>
|
||||
<el-select v-model="searchForm.pxcc" placeholder="请选择培训层次" clearable class="w-full" :disabled="!searchForm.pxccEnabled">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义分类">
|
||||
<el-input v-model="searchForm.zdyfl" placeholder="请输入自定义分类" clearable />
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="专业代号">
|
||||
<el-input v-model="searchForm.zydh" placeholder="请输入专业代号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="专业代码">
|
||||
<el-input v-model="searchForm.zydm" placeholder="请输入专业代码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="学年制">
|
||||
<el-input v-model="searchForm.xnz" placeholder="请输入学年制" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="培训类型2">
|
||||
<el-select v-model="searchForm.pxlx2" placeholder="请选择培训类型2" clearable class="w-full">
|
||||
<el-option v-for="item in pxlx2Options" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态">
|
||||
<el-checkbox v-model="searchForm.ty">停用</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="大纲版本">
|
||||
<el-input v-model="searchForm.dgbb" placeholder="请输入大纲版本" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label"><el-checkbox v-model="searchForm.gljgEnabled">管理机构</el-checkbox></template>
|
||||
<el-select v-model="searchForm.gljg" placeholder="请选择管理机构" clearable class="w-full" :disabled="!searchForm.gljgEnabled">
|
||||
<el-option v-for="item in gljgOptions" :key="item" :label="item" :value="item" />
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="停用标识">
|
||||
<el-select v-model="searchForm.ty" placeholder="全部" clearable class="w-full">
|
||||
<el-option :value="0" label="正常" />
|
||||
<el-option :value="1" label="停用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="search-footer">
|
||||
<div class="notice">注意:勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
@@ -67,79 +31,393 @@
|
||||
<el-card shadow="never" class="table-card">
|
||||
<div class="list-header">
|
||||
<div class="list-title">教学大纲列表</div>
|
||||
<el-button type="primary" @click="handleDownload">下载</el-button>
|
||||
<div class="list-actions">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" icon="el-icon-delete" :disabled="!selection.length" @click="handleBatchDelete">删除所选</el-button>
|
||||
<el-button icon="el-icon-download" @click="handleDownload">下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="tableData" border stripe style="width: 100%">
|
||||
<el-table-column prop="jxgljg" label="教学管理机构" min-width="140" />
|
||||
<el-table-column prop="xkzyxx" label="学科专业信息" min-width="140" />
|
||||
<el-table-column prop="jxdgxx" label="教学大纲信息" min-width="200" />
|
||||
<el-table-column prop="fl" label="分类" width="100" align="center" />
|
||||
<el-table-column prop="xylb" label="学员类别" width="100" align="center" />
|
||||
<el-table-column prop="xnz" label="学年制" width="80" align="center" />
|
||||
<el-table-column prop="xsfb" label="学时分布" min-width="140" align="center" />
|
||||
<el-table-column prop="zy" label="停用" width="80" align="center" />
|
||||
<el-table v-loading="loading" :data="pagedData" border stripe highlight-current-row
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column prop="bh" label="编号" width="170" show-overflow-tooltip align="center" />
|
||||
<el-table-column prop="zydh" label="专业代号" width="150" align="center" />
|
||||
<el-table-column prop="kbh" label="课编号" width="110" show-overflow-tooltip align="center" />
|
||||
<el-table-column prop="jc" label="简称" width="100" show-overflow-tooltip align="center" />
|
||||
<el-table-column prop="klx" label="课类型" width="80" align="center" />
|
||||
<el-table-column prop="xqdc" label="学期第次" width="80" align="center" />
|
||||
<el-table-column prop="xs" label="学时" width="70" align="center" />
|
||||
<el-table-column prop="xf" label="学分" width="70" align="center" />
|
||||
<el-table-column prop="llxs" label="理论学时" width="80" align="center" />
|
||||
<el-table-column prop="sjxs" label="实践学时" width="80" align="center" />
|
||||
<el-table-column prop="zks" label="周课时" width="70" align="center" />
|
||||
<el-table-column prop="ksks" label="考试课时" width="80" align="center" />
|
||||
<el-table-column label="大纲课程" width="90" align="center">
|
||||
<template slot-scope="scope">{{ fmtYesNo(scope.row.dgkc) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="停用" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="Number(scope.row.ty) === 1 ? 'danger' : 'success'" size="mini">
|
||||
{{ Number(scope.row.ty) === 1 ? '停用' : '正常' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="启用时间" width="150" align="center">
|
||||
<template slot-scope="scope">{{ fmtDateTime(scope.row.qysj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="停用时间" width="150" align="center">
|
||||
<template slot-scope="scope">{{ fmtDateTime(scope.row.tysj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" icon="el-icon-delete" class="danger-text-btn" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
background
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:current-page="pageNum"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog :title="dialog.title" :visible.sync="dialog.visible" width="720px" append-to-body
|
||||
:close-on-click-modal="false">
|
||||
<el-form ref="syllabusForm" :model="dialog.form" :rules="rules" label-width="130px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业代号" prop="zydh">
|
||||
<el-input v-model="dialog.form.zydh" placeholder="请输入专业代号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课编号" prop="kbh">
|
||||
<el-input v-model="dialog.form.kbh" placeholder="请输入课编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期第次" prop="xqdc">
|
||||
<el-input-number v-model="dialog.form.xqdc" :min="1" :max="20" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课类型" prop="klx">
|
||||
<el-input v-model="dialog.form.klx" placeholder="请输入课类型" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学时" prop="xs">
|
||||
<el-input-number v-model="dialog.form.xs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="停用" prop="ty">
|
||||
<el-select v-model="dialog.form.ty" class="w-full">
|
||||
<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="dialog.form.jc" placeholder="请输入课程简称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学分">
|
||||
<el-input-number v-model="dialog.form.xf" :min="0" :step="0.5" :precision="1" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课程定位">
|
||||
<el-input v-model="dialog.form.kcdw" placeholder="请输入课程定位" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="模块">
|
||||
<el-input v-model="dialog.form.mk" placeholder="请输入模块" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="成绩分制">
|
||||
<el-input v-model="dialog.form.cjfz" placeholder="请输入成绩分制" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教研室代号">
|
||||
<el-input v-model="dialog.form.jysdh" placeholder="请输入教研室代号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试课时">
|
||||
<el-input-number v-model="dialog.form.ksks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="理论学时">
|
||||
<el-input-number v-model="dialog.form.llxs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="实践学时">
|
||||
<el-input-number v-model="dialog.form.sjxs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周课时">
|
||||
<el-input-number v-model="dialog.form.zks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="不计入平均分">
|
||||
<el-radio-group v-model="dialog.form.bjrxypjf">
|
||||
<el-radio :label="0">否</el-radio>
|
||||
<el-radio :label="1">是</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试课时不显示">
|
||||
<el-radio-group v-model="dialog.form.ksksbxs">
|
||||
<el-radio :label="0">否</el-radio>
|
||||
<el-radio :label="1">是</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="大纲课程">
|
||||
<el-radio-group v-model="dialog.form.dgkc">
|
||||
<el-radio :label="0">否</el-radio>
|
||||
<el-radio :label="1">是</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" :loading="dialog.submitting" @click="submitDialog">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 模拟列表数据(后端接口未提供,接口就绪后可删除并改为接口加载)
|
||||
const mockTableData = [
|
||||
{ jxgljg: '教务处', xkzyxx: '通信工程', jxdgxx: '通信工程导论教学大纲', fl: '专业基础', xylb: '军官', xnz: '4', xsfb: '理论48/实践16', zy: '教学' },
|
||||
{ jxgljg: '教务处', xkzyxx: '信息工程', jxdgxx: '信息工程基础教学大纲', fl: '专业基础', xylb: '军官', xnz: '4', xsfb: '理论64/实践32', zy: '教学' }
|
||||
]
|
||||
import {
|
||||
addSyllabus,
|
||||
deleteSyllabus,
|
||||
batchDeleteSyllabus,
|
||||
updateSyllabus,
|
||||
listSyllabus,
|
||||
listSyllabusByZydhAndTy
|
||||
} from '@/api/teachBusiness/syllabus'
|
||||
|
||||
export default {
|
||||
name: 'SyllabusIndex',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 查询表单 ====================
|
||||
loading: false,
|
||||
searchForm: {
|
||||
zymc: '',
|
||||
zydm: '',
|
||||
zyfx: '',
|
||||
xnz: '',
|
||||
pxlx: '军官基础教育', pxlxEnabled: false,
|
||||
pxlx2: '其他',
|
||||
pxcc: '无', pxccEnabled: false,
|
||||
ty: false,
|
||||
zdyfl: '',
|
||||
dgbb: '',
|
||||
gljg: '教务处', gljgEnabled: false
|
||||
zydh: '',
|
||||
ty: ''
|
||||
},
|
||||
|
||||
// ==================== 下拉选项(字典数据,接口就绪后可由后端字典加载) ====================
|
||||
pxlxOptions: ['军官基础教育', '士兵职业教育', '研究生教育', '其他'],
|
||||
pxlx2Options: ['军官基础教育', '其他', '任职培训', '研究生教育'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
gljgOptions: ['教务处', '教研室1', '教研室2', '学员队'],
|
||||
|
||||
// ==================== 表格数据 ====================
|
||||
tableData: []
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
selection: [],
|
||||
dialog: {
|
||||
visible: false,
|
||||
title: '',
|
||||
submitting: false,
|
||||
form: this.createEmptyForm()
|
||||
},
|
||||
rules: {
|
||||
zydh: [{ required: true, message: '请输入专业代号', trigger: 'blur' }],
|
||||
kbh: [{ required: true, message: '请输入课编号', trigger: 'blur' }],
|
||||
xqdc: [{ required: true, message: '请输入学期第次', trigger: 'blur' }],
|
||||
klx: [{ required: true, message: '请输入课类型', trigger: 'blur' }],
|
||||
xs: [{ required: true, message: '请输入学时', trigger: 'blur' }],
|
||||
ty: [{ required: true, message: '请选择停用标识', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
computed: {
|
||||
pagedData() {
|
||||
const start = (this.pageNum - 1) * this.pageSize
|
||||
return this.tableData.slice(start, start + this.pageSize)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// ==================== 列表加载 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getSyllabusList
|
||||
/* ---------- 列表加载 ---------- */
|
||||
fetchList() {
|
||||
this.tableData = mockTableData.slice()
|
||||
this.loading = true
|
||||
const { zydh, ty } = this.searchForm
|
||||
// 专业代号与停用标识同时给出时走后端 /listByZydhAndTy;否则查全部后本地过滤
|
||||
const useApiQuery = zydh && ty !== '' && ty !== null && ty !== undefined
|
||||
const req = useApiQuery
|
||||
? listSyllabusByZydhAndTy(zydh, ty)
|
||||
: listSyllabus()
|
||||
req.then(response => {
|
||||
let list = response.data || []
|
||||
if (!useApiQuery) {
|
||||
if (zydh) list = list.filter(i => i.zydh && i.zydh.indexOf(zydh) !== -1)
|
||||
if (ty !== '' && ty !== null && ty !== undefined) {
|
||||
list = list.filter(i => Number(i.ty) === Number(ty))
|
||||
}
|
||||
}
|
||||
this.tableData = list
|
||||
this.total = list.length
|
||||
this.pageNum = 1
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
// TODO: 后端接口未提供,查询为前端模拟;接口就绪后替换为后端查询
|
||||
handleQuery() {
|
||||
this.fetchList()
|
||||
this.$message.success('查询教学大纲(前端模拟)')
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm = { zydh: '', ty: '' }
|
||||
this.fetchList()
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.selection = val
|
||||
},
|
||||
|
||||
// ==================== 下载 ====================
|
||||
// TODO: 后端接口未提供,下载为前端模拟;接口就绪后替换为 downloadSyllabusList
|
||||
/* ---------- 新增 / 编辑 ---------- */
|
||||
handleAdd() {
|
||||
this.dialog.title = '新增教学大纲'
|
||||
this.dialog.form = this.createEmptyForm()
|
||||
this.dialog.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.syllabusForm) this.$refs.syllabusForm.clearValidate()
|
||||
})
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.dialog.title = '编辑教学大纲'
|
||||
this.dialog.form = Object.assign({}, this.createEmptyForm(), row)
|
||||
this.dialog.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.syllabusForm) this.$refs.syllabusForm.clearValidate()
|
||||
})
|
||||
},
|
||||
submitDialog() {
|
||||
this.$refs.syllabusForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.dialog.submitting = true
|
||||
const payload = this.cleanPayload(this.dialog.form)
|
||||
const isEdit = !!payload.bh
|
||||
const req = isEdit ? updateSyllabus(payload) : addSyllabus(payload)
|
||||
req.then(() => {
|
||||
this.$message.success(isEdit ? '修改成功' : '新增成功')
|
||||
this.dialog.visible = false
|
||||
this.fetchList()
|
||||
}).finally(() => {
|
||||
this.dialog.submitting = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 删除 / 批量删除 ---------- */
|
||||
handleDelete(row) {
|
||||
this.$confirm('删除后该条记录将置为「停用」,是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return deleteSyllabus(row.bh)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
handleBatchDelete() {
|
||||
if (!this.selection.length) {
|
||||
this.$message.warning('请先勾选要删除的记录')
|
||||
return
|
||||
}
|
||||
const bhList = this.selection.map(row => row.bh)
|
||||
this.$confirm('确定删除所选 ' + bhList.length + ' 条记录吗?(将置为「停用」)', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return batchDeleteSyllabus(bhList)
|
||||
}).then(() => {
|
||||
this.$message.success('批量删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 下载(无后端接口) ---------- */
|
||||
handleDownload() {
|
||||
this.$message.success('下载教学大纲列表(前端模拟)')
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
/* ---------- 分页 ---------- */
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
},
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
},
|
||||
|
||||
/* ---------- 工具 ---------- */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
zydh: '',
|
||||
kbh: '',
|
||||
xqdc: 1,
|
||||
klx: '',
|
||||
xs: 0,
|
||||
ty: 0,
|
||||
jc: '',
|
||||
xf: null,
|
||||
kcdw: '',
|
||||
ksks: 0,
|
||||
mk: '',
|
||||
cjfz: '',
|
||||
bjrxypjf: 0,
|
||||
llxs: 0,
|
||||
sjxs: 0,
|
||||
zks: 0,
|
||||
ksksbxs: 0,
|
||||
dgkc: 0,
|
||||
jysdh: ''
|
||||
}
|
||||
},
|
||||
/** 移除空值(''/null/undefined),保留 0 等有效值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
fmtYesNo(val) {
|
||||
return Number(val) === 1 ? '是' : '否'
|
||||
},
|
||||
fmtDateTime(val) {
|
||||
return (val || '').substring(0, 16) || '-'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,23 +437,8 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-form-item__label {
|
||||
text-align: left;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.search-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 8px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
.notice {
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
}
|
||||
.search-actions {
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,6 +456,19 @@ export default {
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.danger-text-btn {
|
||||
color: #f56c6c;
|
||||
|
||||
&:hover {
|
||||
color: #f78989;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,282 +1,246 @@
|
||||
<template>
|
||||
<div class="app-container teaching-task-page">
|
||||
<!-- 页面标题 -->
|
||||
<div class="page-title">{{ pageTitle }}</div>
|
||||
<!-- ==================== 页面标题 ==================== -->
|
||||
<div class="page-title">教学任务列表</div>
|
||||
|
||||
<!-- 查询条件 -->
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="110px" class="search-form">
|
||||
<el-row :gutter="32">
|
||||
<!-- 左栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="授课教员">
|
||||
<el-input v-model="searchForm.skjy" placeholder="请输入授课教员" clearable />
|
||||
<el-form :model="searchForm" label-width="80px" class="search-form">
|
||||
<el-row :gutter="24">
|
||||
<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-form-item>
|
||||
<el-form-item label="可选班次年级">
|
||||
<el-input v-model="searchForm.kxbcnj" placeholder="请输入可选班次年级" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.fzkztEnabled">分组课状态</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.fzkzt" placeholder="请选择分组课状态" class="w-full"
|
||||
:disabled="!searchForm.fzkztEnabled">
|
||||
<el-option v-for="item in groupStatusOptions" :key="item" :label="item" :value="item" />
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="年度">
|
||||
<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="12">
|
||||
<el-form-item label="课程科目名称">
|
||||
<el-input v-model="searchForm.kckmmc" placeholder="请输入课程科目名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="分组班名称">
|
||||
<el-input v-model="searchForm.fzbmc" placeholder="请输入分组班名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.pxccEnabled">培训层次</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.pxcc" placeholder="请选择培训层次" class="w-full"
|
||||
:disabled="!searchForm.pxccEnabled">
|
||||
<el-option v-for="item in trainLevelOptions" :key="item" :label="item" :value="item" />
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="状态">
|
||||
<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>
|
||||
|
||||
<div class="search-tip">
|
||||
注意:勾选"选择框"表示启用该项对应的查询条件;文本输入框非空白表示启用对应的查询条件。
|
||||
</div>
|
||||
<div class="search-actions">
|
||||
<el-button class="gray-btn" @click="handleSearch">查询</el-button>
|
||||
<el-button class="gray-btn" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 下载按钮 -->
|
||||
<div class="toolbar-right">
|
||||
<el-button type="primary" @click="handleDownloadGroupCourseList">下载分组班列表</el-button>
|
||||
<el-button type="primary" @click="handleDownloadWord">下载分组班学员名单Word</el-button>
|
||||
<el-button type="primary" @click="handleDownloadExcel">下载分组班学员名单Excel</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 批量操作 -->
|
||||
<el-card shadow="never" class="action-card">
|
||||
<div class="action-groups">
|
||||
<div class="action-group">
|
||||
<el-button type="primary" plain @click="handleNewGroupCourse">新建分组课</el-button>
|
||||
<el-button type="primary" plain @click="handleBatchOpen">所选班早开放报名</el-button>
|
||||
<el-button type="primary" plain @click="handleBatchCancelOpen">所选班早取消开放报名</el-button>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<el-button type="primary" plain @click="handleBatchStop">批量停止报名</el-button>
|
||||
<el-button type="primary" plain @click="handleBatchReverseRange">所选班早根据学员反向确定班次范围</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 导入数据 -->
|
||||
<el-card shadow="never" class="import-card">
|
||||
<div class="import-toolbar">
|
||||
<el-button type="primary" @click="handleDownloadTemplate">【分组课数据文件模板】下载</el-button>
|
||||
<div class="file-input">
|
||||
<input ref="fileInput" type="file" accept=".xls,.xlsx" style="display: none" @change="handleFileChange" />
|
||||
<el-button type="primary" plain @click="handleChooseFile">选择文件</el-button>
|
||||
<span class="file-name">{{ fileName }}</span>
|
||||
</div>
|
||||
<el-button type="primary" plain @click="handleUploadData">上传数据</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<!-- ==================== 2. 数据表格 ==================== -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<el-table v-loading="loading" :data="tableData" stripe border 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="100" align="center" />
|
||||
<el-table-column prop="kc" label="课程" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="jc" label="教材" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="ssjy" label="实施教员" width="150" align="center" />
|
||||
<el-table-column prop="jxcd" label="教学场地" width="150" align="center" />
|
||||
<el-table-column align="center">
|
||||
<template slot="header">
|
||||
<el-checkbox v-model="showOptionalClasses">显示可选队别班次</el-checkbox>
|
||||
</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>
|
||||
<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 label="状态" width="100" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<div class="triple-cell">
|
||||
<span>{{ row.jhxs }}</span>
|
||||
<span>{{ row.zxs }}</span>
|
||||
<span>{{ row.xf }}</span>
|
||||
</div>
|
||||
<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-column prop="kkjkrq" label="开课结课日期" width="110" align="center" :formatter="formatDate" />
|
||||
<el-table-column prop="bmrq" label="报名日期" width="120" align="center" :formatter="formatDate" />
|
||||
<el-table-column prop="jhrs" label="计划人数" width="90" align="center" />
|
||||
<el-table-column prop="yqsm" label="要求说明" width="150" 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"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 3. 详情对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="detailVisible"
|
||||
title="教学任务详情"
|
||||
width="620px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => detailVisible = val"
|
||||
>
|
||||
<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 type="primary" @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 教学任务列表(只读查询页)
|
||||
* 对应菜单: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: {
|
||||
skjy: '',
|
||||
kckmmc: '',
|
||||
kxbcnj: '',
|
||||
fzbmc: '',
|
||||
fzkzt: '拟制',
|
||||
fzkztEnabled: false,
|
||||
pxcc: '无',
|
||||
pxccEnabled: false
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: ''
|
||||
},
|
||||
groupStatusOptions: ['拟制', '已发布', '已结课'],
|
||||
trainLevelOptions: ['无', '初级', '中级', '高级'],
|
||||
|
||||
// ==================== 批量操作 ====================
|
||||
selectedRows: [],
|
||||
|
||||
// ==================== 表格数据 ====================
|
||||
loading: false,
|
||||
showOptionalClasses: false,
|
||||
/** 模拟列表数据(后端接口未提供) */
|
||||
tableData: [
|
||||
{ xh: 1, kc: '高等数学', jc: '高等数学(上册)', ssjy: '张三', jxcd: '1-301', jhxs: 48, zxs: 46, xf: 3, kkjkrq: '2017-09-03', bmrq: '2017-08-20', jhrs: 40, yqsm: '按教学计划执行' },
|
||||
{ xh: 2, kc: '军事英语', jc: '军事英语教程', ssjy: '李四', jxcd: '2-101', jhxs: 32, zxs: 30, xf: 2, kkjkrq: '2017-09-03', bmrq: '2017-08-22', jhrs: 36, yqsm: '含听力训练' },
|
||||
{ xh: 3, kc: '导弹发射原理', jc: '导弹发射原理', ssjy: '王五', jxcd: '3-205', jhxs: 40, zxs: 40, xf: 2.5, kkjkrq: '2017-09-10', bmrq: '2017-08-25', jhrs: 42, yqsm: '实验课随堂进行' },
|
||||
{ xh: 4, kc: '通信原理', jc: '通信原理', ssjy: '赵六', jxcd: '5-102', jhxs: 48, zxs: 44, xf: 3, kkjkrq: '2017-09-03', bmrq: '2017-08-28', jhrs: 38, yqsm: '' },
|
||||
{ xh: 5, kc: '联合作战指挥', jc: '联合作战指挥', ssjy: '孙七', jxcd: '学术报告厅', jhxs: 40, zxs: 40, xf: 2.5, kkjkrq: '2017-09-17', bmrq: '2017-09-01', jhrs: 45, yqsm: '理论授课+想定作业' }
|
||||
yearOptions: [],
|
||||
statusOptions: [
|
||||
{ label: '未发布', value: '未发布' },
|
||||
{ label: '发布', value: '发布' }
|
||||
],
|
||||
|
||||
// ==================== 导入 ====================
|
||||
selectedFile: null
|
||||
// ==================== 2. 表格数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
|
||||
// ==================== 3. 详情 ====================
|
||||
detailVisible: false,
|
||||
detailLoading: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fileName() {
|
||||
return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchList()
|
||||
created() {
|
||||
this.loadYearOptions().then(() => this.fetchList())
|
||||
},
|
||||
methods: {
|
||||
/** 表格日期格式化 */
|
||||
formatDate(row, column, cellValue) {
|
||||
return cellValue ? String(cellValue).substring(0, 10) : ''
|
||||
/* ---------- 年度下拉(数据来自 /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 []
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 列表加载 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为真实查询接口
|
||||
/* ---------- 通用格式化 ---------- */
|
||||
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
|
||||
setTimeout(() => {
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
if (this.searchForm.rwmc && this.searchForm.rwmc.trim()) params.rwmc = this.searchForm.rwmc.trim()
|
||||
if (this.searchForm.nd !== undefined && this.searchForm.nd !== null && this.searchForm.nd !== '') {
|
||||
params.nd = this.searchForm.nd
|
||||
}
|
||||
if (this.searchForm.zt && this.searchForm.zt.trim()) params.zt = this.searchForm.zt.trim()
|
||||
listTeachingTask(params).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}, 200)
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
handleSearch() {
|
||||
this.$message.success('查询分组课列表(前端模拟)')
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// ==================== 批量操作 ====================
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleNewGroupCourse() {
|
||||
this.$message.success('新建分组课(前端模拟)')
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleBatchOpen() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择数据')
|
||||
return
|
||||
}
|
||||
this.$message.success('所选批量开放报名(前端模拟)')
|
||||
},
|
||||
|
||||
handleBatchCancelOpen() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择数据')
|
||||
return
|
||||
}
|
||||
this.$message.success('所选批量取消开放报名(前端模拟)')
|
||||
},
|
||||
|
||||
handleBatchStop() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择数据')
|
||||
return
|
||||
}
|
||||
this.$message.success('批量停止报名(前端模拟)')
|
||||
},
|
||||
|
||||
handleBatchReverseRange() {
|
||||
if (this.selectedRows.length === 0) {
|
||||
this.$message.warning('请先选择数据')
|
||||
return
|
||||
}
|
||||
this.$message.success('所选批量根据学员反向确定班次范围(前端模拟)')
|
||||
},
|
||||
|
||||
// ==================== 下载按钮 ====================
|
||||
handleDownloadGroupCourseList() {
|
||||
this.$message.success('下载分组课列表(前端模拟)')
|
||||
},
|
||||
|
||||
handleDownloadWord() {
|
||||
this.$message.success('下载分组学员名单Word(前端模拟)')
|
||||
},
|
||||
|
||||
handleDownloadExcel() {
|
||||
this.$message.success('下载分组学员名单Excel(前端模拟)')
|
||||
},
|
||||
|
||||
// ==================== 导入 ====================
|
||||
handleChooseFile() {
|
||||
this.$refs.fileInput && this.$refs.fileInput.click()
|
||||
},
|
||||
|
||||
handleFileChange(e) {
|
||||
const input = e.target
|
||||
if (input.files && input.files.length > 0) {
|
||||
this.selectedFile = input.files[0]
|
||||
}
|
||||
},
|
||||
|
||||
handleDownloadTemplate() {
|
||||
this.$message.success('下载分组课数据文件模板(前端模拟)')
|
||||
},
|
||||
|
||||
handleUploadData() {
|
||||
if (!this.selectedFile) {
|
||||
this.$message.warning('请先选择文件')
|
||||
return
|
||||
}
|
||||
this.$message.success('上传数据(前端模拟)')
|
||||
/* ---------- 详情(只读,走真实 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
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,99 +251,45 @@ export default {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
.teaching-task-page {
|
||||
.page-title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
// ==================== 1. 查询条件区域 ====================
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.action-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.action-groups {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.action-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
|
||||
.el-button {
|
||||
margin: 0;
|
||||
.search-form {
|
||||
.search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.import-card {
|
||||
margin-bottom: 16px;
|
||||
// ==================== 2. 数据表格 ====================
|
||||
.table-card {
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.import-toolbar {
|
||||
// ==================== 3. 详情 ====================
|
||||
.detail-empty {
|
||||
min-height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.file-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.file-name {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-card {
|
||||
::v-deep(.el-table) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.triple-header,
|
||||
.triple-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.4;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,58 +11,28 @@
|
||||
<el-link type="primary" :underline="false" class="nav-link" @click="handleNextDay">后一天</el-link>
|
||||
</div>
|
||||
|
||||
<!-- 批量操作栏 -->
|
||||
<div class="toolbar-card">
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-left">
|
||||
<el-button type="primary" size="mini" :disabled="!todaySelected.length" @click="handleComing">批量设置备注信息</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!todaySelected.length" @click="handleComing">批量变更时间</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!todaySelected.length" @click="handleComing">批量平移时间</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!todaySelected.length" @click="handleComing">批量变更授课教员</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!todaySelected.length" @click="handleComing">批量变更授课场地</el-button>
|
||||
<el-button type="danger" size="mini" :disabled="!todaySelected.length" @click="handleComing">批量删除</el-button>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<el-button type="primary" size="mini" @click="handleComing">自定义格式下载</el-button>
|
||||
<el-button type="primary" size="mini" @click="handleComing">下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 今日表格 -->
|
||||
<div class="table-card">
|
||||
<el-table :data="todayList" v-loading="loading" stripe border @selection-change="todaySelected = $event">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table :data="todayList" v-loading="todayLoading" stripe border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="上课时间" width="130" align="center">
|
||||
<template slot-scope="scope">{{ formatTime(scope.row.jc) }}</template>
|
||||
<el-table-column label="上课时间" width="200" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ fmtLessonTime(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="zrdw" label="责任单位" width="110" align="center" />
|
||||
<el-table-column prop="bc" label="班次" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="skjy" label="教员" width="90" align="center" />
|
||||
<el-table-column label="场地" width="140" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jxcd || '-' }}</template>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="150" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="kcxh" label="课次序号" width="90" align="center" />
|
||||
<el-table-column label="教学内容" min-width="180" show-overflow-tooltip header-align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jxnr || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学内容方法" min-width="160" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row._jxnrff || '-' }}</template>
|
||||
<el-table-column label="教学方法" width="130" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jxff || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jybz" label="备注" width="100" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jybz || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划变更明细" width="120" align="center">
|
||||
<el-table-column label="填写状态" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openDetail(scope.row)">变更明细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openRemark(scope.row)">编辑备注</el-button>
|
||||
<el-button type="text" size="mini" class="danger-text" @click="handleComing">删除</el-button>
|
||||
<el-tag :type="txztType(scope.row.txzt)" size="mini">{{ txztText(scope.row.txzt) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-show="!loading && !todayList.length" description="当日暂无教学计划数据" />
|
||||
<el-empty v-show="!todayLoading && !todayList.length" description="当日暂无教学计划数据" />
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@@ -77,58 +47,28 @@
|
||||
<el-link type="primary" :underline="false" class="nav-link" @click="handleNextWeek">下一周</el-link>
|
||||
</div>
|
||||
|
||||
<!-- 批量操作栏 -->
|
||||
<div class="toolbar-card">
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-left">
|
||||
<el-button type="primary" size="mini" :disabled="!weekSelected.length" @click="handleComing">批量设置备注信息</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!weekSelected.length" @click="handleComing">批量变更时间</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!weekSelected.length" @click="handleComing">批量平移时间</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!weekSelected.length" @click="handleComing">批量变更授课教员</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!weekSelected.length" @click="handleComing">批量变更授课场地</el-button>
|
||||
<el-button type="danger" size="mini" :disabled="!weekSelected.length" @click="handleComing">批量删除</el-button>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<el-button type="primary" size="mini" @click="handleComing">报批下载</el-button>
|
||||
<el-button type="primary" size="mini" @click="handleComing">下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 本周表格 -->
|
||||
<div class="table-card">
|
||||
<el-table :data="weekList" v-loading="loading" stripe border @selection-change="weekSelected = $event">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table :data="weekList" v-loading="weekLoading" stripe border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="上课时间" width="170" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row._sjsj || '-' }}</template>
|
||||
<el-table-column label="上课时间" width="200" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ fmtLessonTime(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="zrdw" label="责任单位" width="100" align="center" />
|
||||
<el-table-column prop="bc" label="班次" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="skjy" label="教员" width="90" align="center" />
|
||||
<el-table-column label="场地" width="140" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jxcd || '-' }}</template>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="150" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="kcxh" label="课次序号" width="90" align="center" />
|
||||
<el-table-column label="教学内容" min-width="180" show-overflow-tooltip header-align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jxnr || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学内容方法" min-width="150" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row._jxnrff || '-' }}</template>
|
||||
<el-table-column label="教学方法" width="130" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jxff || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jybz" label="备注" width="100" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jybz || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划变更明细" width="120" align="center">
|
||||
<el-table-column label="填写状态" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openDetail(scope.row)">计划变更明细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openRemark(scope.row)">编辑备注</el-button>
|
||||
<el-button type="text" size="mini" class="danger-text" @click="handleComing">删除</el-button>
|
||||
<el-tag :type="txztType(scope.row.txzt)" size="mini">{{ txztText(scope.row.txzt) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-show="!loading && !weekList.length" description="本周暂无教学计划数据" />
|
||||
<el-empty v-show="!weekLoading && !weekList.length" description="本周暂无教学计划数据" />
|
||||
<pagination
|
||||
v-show="weekTotal > 0"
|
||||
:total="weekTotal"
|
||||
@@ -150,58 +90,36 @@
|
||||
<el-link type="primary" :underline="false" class="nav-link" @click="handleNextWeek3">下一周</el-link>
|
||||
</div>
|
||||
|
||||
<!-- 批量操作栏 -->
|
||||
<div class="toolbar-card">
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-left">
|
||||
<el-button type="primary" size="mini" :disabled="!practiceSelected.length" @click="handleComing">批量设置备注信息</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!practiceSelected.length" @click="handleComing">批量变更时间</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!practiceSelected.length" @click="handleComing">批量平移时间</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!practiceSelected.length" @click="handleComing">批量变更授课教员</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="!practiceSelected.length" @click="handleComing">批量变更授课场地</el-button>
|
||||
<el-button type="danger" size="mini" :disabled="!practiceSelected.length" @click="handleComing">批量删除</el-button>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<el-button type="primary" size="mini" @click="handleComing">报批下载</el-button>
|
||||
<el-button type="primary" size="mini" @click="handleComing">下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-alert
|
||||
class="mb8"
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="说明:后端教学实施计划课次接口未返回课程类型字段,无法按三实课类型筛选,当前展示本周全部教学实施计划课次。"
|
||||
/>
|
||||
|
||||
<!-- 三实表格 -->
|
||||
<div class="table-card">
|
||||
<el-table :data="practiceList" v-loading="loading" stripe border @selection-change="practiceSelected = $event">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table :data="practiceList" v-loading="practiceLoading" stripe border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="上课时间" width="170" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row._sjsj || '-' }}</template>
|
||||
<el-table-column label="上课时间" width="200" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ fmtLessonTime(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="zrdw" label="责任单位" width="100" align="center" />
|
||||
<el-table-column prop="bc" label="班次" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="skjy" label="教员" width="90" align="center" />
|
||||
<el-table-column label="场地" width="140" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jxcd || '-' }}</template>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="150" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="kcxh" label="课次序号" width="90" align="center" />
|
||||
<el-table-column label="教学内容" min-width="180" show-overflow-tooltip header-align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jxnr || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="教学内容方法" min-width="150" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row._jxnrff || '-' }}</template>
|
||||
<el-table-column label="教学方法" width="130" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jxff || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jybz" label="备注" width="100" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.jybz || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划变更明细" width="120" align="center">
|
||||
<el-table-column label="填写状态" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openDetail(scope.row)">计划变更明细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openRemark(scope.row)">编辑备注</el-button>
|
||||
<el-button type="text" size="mini" class="danger-text" @click="handleComing">删除</el-button>
|
||||
<el-tag :type="txztType(scope.row.txzt)" size="mini">{{ txztText(scope.row.txzt) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-show="!loading && !practiceList.length" description="本周暂无三实教学计划数据" />
|
||||
<el-empty v-show="!practiceLoading && !practiceList.length" description="本周暂无三实教学计划数据" />
|
||||
<pagination
|
||||
v-show="practiceTotal > 0"
|
||||
:total="practiceTotal"
|
||||
@@ -219,122 +137,115 @@
|
||||
<!-- 查询条件 -->
|
||||
<el-form :inline="true" class="shift-search">
|
||||
<el-form-item label="队别班次">
|
||||
<el-select v-model="shiftTeamClass" placeholder="请选择队别班次" clearable class="shift-select">
|
||||
<el-option label="一班" value="一班" />
|
||||
<el-option label="二班" value="二班" />
|
||||
<el-option label="三班" value="三班" />
|
||||
<el-option label="四班" value="四班" />
|
||||
<el-select
|
||||
v-model="shiftXydbh"
|
||||
placeholder="请选择队别班次"
|
||||
clearable
|
||||
filterable
|
||||
class="shift-select"
|
||||
>
|
||||
<el-option v-for="t in teamOptions" :key="t.xydbh" :label="t.xydmc" :value="t.xydbh" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="年度">
|
||||
<el-select v-model="shiftNd" placeholder="请选择年度" class="shift-select">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleComing">查询</el-button>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleShiftSearch">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 标题 -->
|
||||
<div class="shift-title">2026年秋季学期{{ shiftTeamClass || '' }}课程表</div>
|
||||
<div class="shift-title">{{ shiftTitle }}</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期教学实施计划</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期教学实施计划</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期课程表(周次星期)</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期课程表(周次星期)</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期课程表(班次视图)</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期课程表(班次视图)</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期课程表(排课周)含选修</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期课程表(排课周)含选修</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期教学实施计划(含选修)</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期教学实施计划(含选修)</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期课程表(周次星期)详细</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期课程表(周次星期)详细</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleComing">学期成绩表</el-button>
|
||||
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleNotProvided">学期成绩表</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-download" size="mini" @click="handleComing">课程列表另存Excel</el-button>
|
||||
<el-button type="success" plain icon="el-icon-download" size="mini" @click="handleNotProvided">课程列表另存Excel</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 班次课程表 -->
|
||||
<el-table v-loading="loading" :data="shiftList" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="课程名称/课时系数" min-width="220">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.kcmc }}</div>
|
||||
<div class="sub-text">{{ scope.row.kssk }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zrjs" label="责任教员/课次" min-width="150" />
|
||||
<el-table-column prop="bc" label="班次" min-width="120" />
|
||||
<el-table-column prop="nj" label="年级" width="80" align="center" />
|
||||
<el-table-column prop="zy" label="专业" min-width="120" />
|
||||
<el-table-column prop="jhxs" label="计划学时" width="90" align="center" />
|
||||
<el-table-column prop="yxxs" label="运行学时" width="90" align="center" />
|
||||
<el-table-column prop="khlxfs" label="考核类型方式" min-width="140" />
|
||||
<el-table-column prop="ssjs" label="实施教员" min-width="120" />
|
||||
<el-table-column prop="rscd" label="人数/场地" min-width="140" />
|
||||
<el-table-column prop="kcjd" label="课程进度" width="120" align="center" />
|
||||
<el-table-column prop="ssjhbg" label="实施计划变更" min-width="120" align="center" />
|
||||
</el-table>
|
||||
<div class="table-card">
|
||||
<el-table v-loading="shiftLoading" :data="shiftList" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="课程名称/简称" min-width="200" header-align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row._kcmc || '-' }}</div>
|
||||
<div class="sub-text">{{ scope.row.jc || '-' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="责任教员/课次" width="160" header-align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row._zrjy || '-' }}</div>
|
||||
<div class="sub-text">第{{ scope.row.kcxh || '-' }}次课</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="xydmc" label="班次" width="130" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="xs" label="计划学时" width="90" align="center" />
|
||||
<el-table-column prop="llxs" label="理论学时" width="90" align="center" />
|
||||
<el-table-column prop="sjxs" label="实践学时" width="90" align="center" />
|
||||
<el-table-column prop="cjfz" label="考核类型方式" min-width="110" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="实施教员" width="110" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row._ssjy || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="人数/场地" width="130" header-align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.rs || '-' }} 人</div>
|
||||
<div class="sub-text">{{ scope.row.jsbh || '-' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="xf" label="学分" width="80" align="center" />
|
||||
<el-table-column label="实施计划变更" width="150" header-align="center">
|
||||
<template slot-scope="scope">{{ fmtKbbdsj(scope.row.kbbdsj) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-show="!shiftLoading && !shiftList.length" description="该班次暂无课程数据" />
|
||||
<pagination
|
||||
v-show="shiftTotal > 0"
|
||||
:total="shiftTotal"
|
||||
:page.sync="shiftQuery.pageNum"
|
||||
:limit.sync="shiftQuery.pageSize"
|
||||
@pagination="getShiftList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 编辑备注弹窗 -->
|
||||
<el-dialog title="编辑备注" :visible.sync="remarkVisible" width="500px" append-to-body>
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="课程">
|
||||
<span>{{ remarkTarget.kcmc || '-' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注内容">
|
||||
<el-input v-model="remarkText" type="textarea" :rows="4" placeholder="请输入备注内容" maxlength="500" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="confirmRemark">确定</el-button>
|
||||
<el-button @click="remarkVisible = false">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 计划变更明细弹窗 -->
|
||||
<el-dialog title="计划变更明细" :visible.sync="detailVisible" width="560px" append-to-body>
|
||||
<el-descriptions :column="2" border size="small" v-if="detailTarget">
|
||||
<el-descriptions-item label="课程">{{ detailTarget.kcmc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="班次">{{ detailTarget.bc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="责任单位">{{ detailTarget.zrdw }}</el-descriptions-item>
|
||||
<el-descriptions-item label="上课时间">{{ detailTarget._sjsj || formatTime(detailTarget.jc) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="原节次">{{ detailTarget.yjc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="授课教员">{{ detailTarget.skjy }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学场地">{{ detailTarget.jxcd || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="检查结果">{{ detailTarget.jcjg || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="已通过检查" :span="2">
|
||||
<el-tag :type="detailTarget.ytgjc ? 'success' : 'info'" size="mini">{{ detailTarget.ytgjc ? '是' : '否' }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 节次 -> 时间映射
|
||||
const JC_TIME = {
|
||||
1: '08:00-08:45',
|
||||
2: '08:55-09:40',
|
||||
3: '10:00-10:45',
|
||||
4: '10:55-11:40',
|
||||
5: '14:30-15:15',
|
||||
6: '15:25-16:10',
|
||||
7: '16:20-17:05',
|
||||
8: '19:00-19:45',
|
||||
9: '19:55-20:40'
|
||||
}
|
||||
import { listTeachingPlan } from '@/api/teachBusiness/courseRunning'
|
||||
import { listStudentTeamTask } from '@/api/teachBusiness/studentTeamTask'
|
||||
import { listTeam } from '@/api/studentRecords/team'
|
||||
import { listSubject } from '@/api/teachOffice/subject'
|
||||
import { listTeacher } from '@/api/teachOffice/teacher'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
|
||||
// 节次 -> 节次区间映射
|
||||
const JC_SECTION = {
|
||||
1: '1-2节', 2: '3-4节', 3: '5-6节', 4: '7-8节', 5: '9-10节', 6: '11-12节'
|
||||
@@ -362,32 +273,36 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'today',
|
||||
loading: false,
|
||||
// 今日
|
||||
todayDate: new Date(),
|
||||
todayList: [],
|
||||
todaySelected: [],
|
||||
todayLoading: false,
|
||||
// 本周
|
||||
weekStart: getMonday(new Date()),
|
||||
weekList: [],
|
||||
weekSelected: [],
|
||||
weekLoading: false,
|
||||
weekTotal: 0,
|
||||
weekQuery: { pageNum: 1, pageSize: 20 },
|
||||
// 三实
|
||||
practiceStart: getMonday(new Date()),
|
||||
practiceList: [],
|
||||
practiceSelected: [],
|
||||
practiceLoading: false,
|
||||
practiceTotal: 0,
|
||||
practiceQuery: { pageNum: 1, pageSize: 20 },
|
||||
// 班次(仅占位数据,待对接接口)
|
||||
shiftTeamClass: '',
|
||||
// 班次
|
||||
teamOptions: [],
|
||||
shiftXydbh: '',
|
||||
shiftNd: undefined,
|
||||
shiftList: [],
|
||||
// 弹窗
|
||||
remarkVisible: false,
|
||||
remarkTarget: {},
|
||||
remarkText: '',
|
||||
detailVisible: false,
|
||||
detailTarget: null
|
||||
shiftLoading: false,
|
||||
shiftTotal: 0,
|
||||
shiftQuery: { pageNum: 1, pageSize: 20 },
|
||||
// 年度下拉数据来自 /semester/all(真实后端数据)
|
||||
yearOptions: [],
|
||||
defaultNd: undefined,
|
||||
// 名称映射(真实接口数据,用于班次 tab 课程/教员编号转名称)
|
||||
kbMap: {},
|
||||
teacherMap: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -405,32 +320,75 @@ export default {
|
||||
end.setDate(end.getDate() + 6)
|
||||
return formatDate(this.practiceStart) + '(' + this.weekDayName(this.practiceStart) + ') 至 ' +
|
||||
formatDate(end) + '(' + this.weekDayName(end) + ') 三实教学实施计划'
|
||||
},
|
||||
shiftTitle() {
|
||||
const team = this.teamOptions.find(t => t.xydbh === this.shiftXydbh)
|
||||
const name = (team && team.xydmc) || ''
|
||||
return (this.shiftNd ? this.shiftNd + '年' : '') + name + '课程表'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadYearOptions()
|
||||
this.getTodayList()
|
||||
this.getWeekList()
|
||||
this.getPracticeList()
|
||||
this.loadTeamOptions()
|
||||
this.loadKbMap()
|
||||
this.loadTeacherMap()
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 年度下拉(数据来自 /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)
|
||||
this.defaultNd = (current && current.nd) || arr[0]
|
||||
if (!this.shiftNd) this.shiftNd = this.defaultNd
|
||||
return arr
|
||||
}).catch(() => {
|
||||
this.yearOptions = []
|
||||
this.defaultNd = undefined
|
||||
return []
|
||||
})
|
||||
},
|
||||
weekDayName(d) {
|
||||
return WEEK_DAY_NAMES[d.getDay()]
|
||||
},
|
||||
formatTime(jc) {
|
||||
if (!jc) return '-'
|
||||
return JC_TIME[jc] || ('第' + jc + '节')
|
||||
},
|
||||
formatSection(jc) {
|
||||
if (!jc) return ''
|
||||
if (jc === null || jc === undefined || jc === '') return '第?节'
|
||||
return JC_SECTION[jc] || ('第' + jc + '节')
|
||||
},
|
||||
buildSjsj(rq, jc) {
|
||||
const date = (rq || '').substring(0, 10)
|
||||
/** 后端 LocalDateTime -> 日期+周X+节次区间 */
|
||||
fmtLessonTime(row) {
|
||||
const rq = row.rq || ''
|
||||
const date = String(rq).substring(0, 10)
|
||||
if (!date) return '-'
|
||||
const d = new Date(date.replace(/-/g, '/'))
|
||||
const wn = WEEK_DAY_NAMES[d.getDay()]
|
||||
const section = this.formatSection(jc)
|
||||
return (date + ' 周' + wn + ' ' + section).trim()
|
||||
return (date + ' 周' + wn + ' ' + this.formatSection(row.jc)).trim()
|
||||
},
|
||||
/** 后端 LocalDateTime -> yyyy-MM-dd HH:mm */
|
||||
fmtKbbdsj(v) {
|
||||
if (!v) return '-'
|
||||
return String(v).replace('T', ' ').substring(0, 16)
|
||||
},
|
||||
txztText(txzt) {
|
||||
if (txzt === 1) return '已填写'
|
||||
if (txzt === 2) return '已提交'
|
||||
return '未填写'
|
||||
},
|
||||
txztType(txzt) {
|
||||
if (txzt === 1) return 'success'
|
||||
if (txzt === 2) return 'primary'
|
||||
return 'info'
|
||||
},
|
||||
/* ---------- 今日 ---------- */
|
||||
handlePrevDay() {
|
||||
@@ -446,115 +404,178 @@ export default {
|
||||
this.getTodayList()
|
||||
},
|
||||
getTodayList() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
this.todayList = this.buildMockList(this.todayDate)
|
||||
this.loading = false
|
||||
}, 200)
|
||||
const day = formatDate(this.todayDate)
|
||||
const params = {
|
||||
rqStart: day + 'T00:00:00',
|
||||
rqEnd: day + 'T23:59:59',
|
||||
pageNum: 1,
|
||||
pageSize: 200
|
||||
}
|
||||
this.todayLoading = true
|
||||
listTeachingPlan(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.todayList = data.records || []
|
||||
this.todayLoading = false
|
||||
}).catch(() => {
|
||||
this.todayList = []
|
||||
this.todayLoading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 本周 ---------- */
|
||||
handlePrevWeek() {
|
||||
const d = new Date(this.weekStart)
|
||||
d.setDate(d.getDate() - 7)
|
||||
this.weekStart = d
|
||||
this.weekQuery.pageNum = 1
|
||||
this.getWeekList()
|
||||
},
|
||||
handleNextWeek() {
|
||||
const d = new Date(this.weekStart)
|
||||
d.setDate(d.getDate() + 7)
|
||||
this.weekStart = d
|
||||
this.weekQuery.pageNum = 1
|
||||
this.getWeekList()
|
||||
},
|
||||
weekRange() {
|
||||
const start = formatDate(this.weekStart) + 'T00:00:00'
|
||||
const endDate = new Date(this.weekStart)
|
||||
endDate.setDate(endDate.getDate() + 6)
|
||||
const end = formatDate(endDate) + 'T23:59:59'
|
||||
return { start: start, end: end }
|
||||
},
|
||||
getWeekList() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
this.weekList = this.buildMockWeekList(this.weekStart)
|
||||
this.weekTotal = this.weekList.length
|
||||
this.loading = false
|
||||
}, 200)
|
||||
const range = this.weekRange()
|
||||
const params = {
|
||||
rqStart: range.start,
|
||||
rqEnd: range.end,
|
||||
pageNum: this.weekQuery.pageNum,
|
||||
pageSize: this.weekQuery.pageSize
|
||||
}
|
||||
this.weekLoading = true
|
||||
listTeachingPlan(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.weekList = data.records || []
|
||||
this.weekTotal = data.total || 0
|
||||
this.weekLoading = false
|
||||
}).catch(() => {
|
||||
this.weekList = []
|
||||
this.weekTotal = 0
|
||||
this.weekLoading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 三实 ---------- */
|
||||
handlePrevWeek3() {
|
||||
const d = new Date(this.practiceStart)
|
||||
d.setDate(d.getDate() - 7)
|
||||
this.practiceStart = d
|
||||
this.practiceQuery.pageNum = 1
|
||||
this.getPracticeList()
|
||||
},
|
||||
handleNextWeek3() {
|
||||
const d = new Date(this.practiceStart)
|
||||
d.setDate(d.getDate() + 7)
|
||||
this.practiceStart = d
|
||||
this.practiceQuery.pageNum = 1
|
||||
this.getPracticeList()
|
||||
},
|
||||
practiceRange() {
|
||||
const start = formatDate(this.practiceStart) + 'T00:00:00'
|
||||
const endDate = new Date(this.practiceStart)
|
||||
endDate.setDate(endDate.getDate() + 6)
|
||||
const end = formatDate(endDate) + 'T23:59:59'
|
||||
return { start: start, end: end }
|
||||
},
|
||||
getPracticeList() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
this.practiceList = this.buildMockWeekList(this.practiceStart)
|
||||
this.practiceTotal = this.practiceList.length
|
||||
this.loading = false
|
||||
}, 200)
|
||||
},
|
||||
/* ---------- 静态示例数据(待对接接口) ---------- */
|
||||
buildMockList(date) {
|
||||
const dateStr = formatDate(date)
|
||||
const samples = [
|
||||
{ jc: 1, kcmc: '高等数学', zrdw: '基础部', bc: '一班', skjy: '张教员', jxcd: '1号教学楼-101', jxnr: '函数与极限', jxff: '讲授', jybz: '携带教材' },
|
||||
{ jc: 3, kcmc: '大学英语', zrdw: '基础部', bc: '二班', skjy: '李教员', jxcd: '2号教学楼-205', jxnr: 'Unit 3 课文精读', jxff: '讲授/讨论', jybz: '' },
|
||||
{ jc: 5, kcmc: '计算机基础', zrdw: '信息工程系', bc: '三班', skjy: '王教员', jxcd: '实验楼-303', jxnr: 'Word 文档排版', jxff: '实操', jybz: '机房上课' }
|
||||
]
|
||||
return samples.map((item, index) => ({
|
||||
...item,
|
||||
xh: index + 1,
|
||||
rq: dateStr,
|
||||
_jxnrff: [item.jxnr, item.jxff].filter(Boolean).join(' / ')
|
||||
}))
|
||||
},
|
||||
buildMockWeekList(weekStart) {
|
||||
const list = []
|
||||
const dates = []
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const d = new Date(weekStart)
|
||||
d.setDate(d.getDate() + i)
|
||||
dates.push(formatDate(d))
|
||||
// 后端 plan/list 接口未返回课程类型字段,无法按三实课筛选,与本周共用同一数据源
|
||||
const range = this.practiceRange()
|
||||
const params = {
|
||||
rqStart: range.start,
|
||||
rqEnd: range.end,
|
||||
pageNum: this.practiceQuery.pageNum,
|
||||
pageSize: this.practiceQuery.pageSize
|
||||
}
|
||||
const courses = [
|
||||
{ jc: 1, kcmc: '高等数学', zrdw: '基础部', bc: '一班', skjy: '张教员', jxcd: '1号教学楼-101', jxnr: '函数与极限', jxff: '讲授', jybz: '携带教材' },
|
||||
{ jc: 2, kcmc: '大学英语', zrdw: '基础部', bc: '二班', skjy: '李教员', jxcd: '2号教学楼-205', jxnr: 'Unit 3 课文精读', jxff: '讲授/讨论', jybz: '' },
|
||||
{ jc: 3, kcmc: '计算机基础', zrdw: '信息工程系', bc: '三班', skjy: '王教员', jxcd: '实验楼-303', jxnr: 'Word 文档排版', jxff: '实操', jybz: '机房上课' },
|
||||
{ jc: 4, kcmc: '军事理论', zrdw: '政工系', bc: '一班', skjy: '赵教员', jxcd: '3号教学楼-110', jxnr: '国防动员概述', jxff: '讲授', jybz: '' }
|
||||
]
|
||||
dates.forEach((dateStr, i) => {
|
||||
courses.forEach((item, idx) => {
|
||||
// 隔天轮换部分课程,保证每周有内容且不重复
|
||||
if ((i + idx) % 2 === 0) {
|
||||
list.push({
|
||||
...item,
|
||||
xh: list.length + 1,
|
||||
rq: dateStr,
|
||||
_sjsj: this.buildSjsj(dateStr, item.jc),
|
||||
_jxnrff: [item.jxnr, item.jxff].filter(Boolean).join(' / ')
|
||||
})
|
||||
}
|
||||
})
|
||||
this.practiceLoading = true
|
||||
listTeachingPlan(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.practiceList = data.records || []
|
||||
this.practiceTotal = data.total || 0
|
||||
this.practiceLoading = false
|
||||
}).catch(() => {
|
||||
this.practiceList = []
|
||||
this.practiceTotal = 0
|
||||
this.practiceLoading = false
|
||||
})
|
||||
return list
|
||||
},
|
||||
/* ---------- 弹窗 ---------- */
|
||||
openRemark(row) {
|
||||
this.remarkTarget = row
|
||||
this.remarkText = row.jybz || ''
|
||||
this.remarkVisible = true
|
||||
/* ---------- 班次 ---------- */
|
||||
loadTeamOptions() {
|
||||
listTeam({ pageNum: 1, pageSize: 1000 }).then(response => {
|
||||
const data = response.data || {}
|
||||
this.teamOptions = data.records || []
|
||||
}).catch(() => {
|
||||
this.teamOptions = []
|
||||
})
|
||||
},
|
||||
confirmRemark() {
|
||||
this.$message.success('备注已更新')
|
||||
this.remarkVisible = false
|
||||
loadKbMap() {
|
||||
listSubject({ pageNum: 1, pageSize: 1000 }).then(response => {
|
||||
const data = response.data || {}
|
||||
const map = {}
|
||||
;(data.records || []).forEach(item => {
|
||||
if (item.kbh) map[item.kbh] = item.kmc
|
||||
})
|
||||
this.kbMap = map
|
||||
}).catch(() => {
|
||||
this.kbMap = {}
|
||||
})
|
||||
},
|
||||
openDetail(row) {
|
||||
this.detailTarget = row
|
||||
this.detailVisible = true
|
||||
loadTeacherMap() {
|
||||
listTeacher({ pageNum: 1, pageSize: 1000 }).then(response => {
|
||||
const data = response.data || {}
|
||||
const map = {}
|
||||
;(data.records || []).forEach(item => {
|
||||
if (item.jybh) map[item.jybh] = item.jyxm
|
||||
})
|
||||
this.teacherMap = map
|
||||
}).catch(() => {
|
||||
this.teacherMap = {}
|
||||
})
|
||||
},
|
||||
handleComing() {
|
||||
this.$message.info('功能建设中,敬请期待')
|
||||
handleShiftSearch() {
|
||||
if (!this.shiftXydbh) {
|
||||
this.$message.warning('请先选择队别班次')
|
||||
return
|
||||
}
|
||||
this.shiftQuery.pageNum = 1
|
||||
this.getShiftList()
|
||||
},
|
||||
getShiftList() {
|
||||
const params = {
|
||||
xydbh: this.shiftXydbh,
|
||||
nd: this.shiftNd,
|
||||
pageNum: this.shiftQuery.pageNum,
|
||||
pageSize: this.shiftQuery.pageSize
|
||||
}
|
||||
this.shiftLoading = true
|
||||
listStudentTeamTask(params).then(response => {
|
||||
const data = response.data || {}
|
||||
const team = this.teamOptions.find(t => t.xydbh === this.shiftXydbh)
|
||||
this.shiftList = (data.records || []).map(item => ({
|
||||
...item,
|
||||
xydmc: (team && team.xydmc) || item.xydbh,
|
||||
_kcmc: this.kbMap[item.kbh] || item.kbh,
|
||||
_zrjy: this.teacherMap[item.jysjhjybh] || item.jysjhjybh || '-',
|
||||
_ssjy: this.teacherMap[item.jybh] || item.jybh || '-'
|
||||
}))
|
||||
this.shiftTotal = data.total || 0
|
||||
this.shiftLoading = false
|
||||
}).catch(() => {
|
||||
this.shiftList = []
|
||||
this.shiftTotal = 0
|
||||
this.shiftLoading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 无后端接口的操作 ---------- */
|
||||
handleNotProvided() {
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -573,6 +594,10 @@ export default {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 日期/周次导航 */
|
||||
.nav-header {
|
||||
display: flex;
|
||||
@@ -596,31 +621,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
/* 批量操作栏 */
|
||||
.toolbar-card {
|
||||
margin-bottom: 12px;
|
||||
padding: 10px 14px;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
|
||||
.toolbar-left,
|
||||
.toolbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 表格区 */
|
||||
.table-card {
|
||||
.danger-text {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<!-- 近期申请统计卡片 -->
|
||||
<!-- 统计卡片 -->
|
||||
<div class="section-card">
|
||||
<div class="section-title">近期课表调整申请</div>
|
||||
<div class="section-title">调课申请统计(当前页)</div>
|
||||
<div class="stat-grid">
|
||||
<div
|
||||
v-for="card in statCards"
|
||||
@@ -22,19 +22,18 @@
|
||||
|
||||
<!-- 查询条件 -->
|
||||
<div class="section-card">
|
||||
<el-form :model="queryParams" :inline="true" size="small" class="search-form">
|
||||
<el-form-item label="课程名称">
|
||||
<el-input v-model="queryParams.kcmc" placeholder="请输入课程名称" clearable style="width: 180px" @keyup.enter.native="handleQuery" />
|
||||
<el-form :model="queryParams" :inline="true" size="small" class="search-form" @submit.native.prevent>
|
||||
<el-form-item label="年度">
|
||||
<el-select v-model="queryParams.nd" placeholder="请选择年度" clearable style="width: 140px">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="队别(班次)">
|
||||
<el-input v-model="queryParams.dbbc" placeholder="请输入队别班次" clearable style="width: 160px" @keyup.enter.native="handleQuery" />
|
||||
<el-form-item label="申请教员编号">
|
||||
<el-input v-model="queryParams.sqjybh" placeholder="请输入申请教员编号" clearable style="width: 180px" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="申请教员">
|
||||
<el-input v-model="queryParams.sqjy" placeholder="请输入申请教员" clearable style="width: 160px" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 140px">
|
||||
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
<el-form-item label="教研室审批状态">
|
||||
<el-select v-model="queryParams.jyspzzt" placeholder="请选择" clearable style="width: 150px">
|
||||
<el-option v-for="item in auditStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -53,87 +52,270 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table :data="filteredData" v-loading="loading" size="small" border stripe class="compact-table" max-height="520">
|
||||
<el-table :data="tableData" v-loading="loading" size="small" border stripe class="compact-table" max-height="520">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="kcmc" label="课程名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="jxsj" label="教学时间" width="110" align="center" />
|
||||
<el-table-column prop="sksj" label="上课时间" width="180" />
|
||||
<el-table-column prop="jy" label="教员" width="90" align="center" />
|
||||
<el-table-column prop="jxcd" label="教学场地" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="dbbc" label="队别(班次)" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="sqjy" label="申请教员" width="90" align="center" />
|
||||
<el-table-column prop="zxkb" label="拟调整时间" width="180" />
|
||||
<el-table-column label="申请类型" width="90" align="center">
|
||||
<el-table-column prop="kcmc" label="课程名称" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="申请教员" min-width="110" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.sqjyxm || scope.row.sqjybh || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sy" label="调课事由" min-width="180" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="拟调整时间" width="170" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ fmtRqJc(scope.row.rq, scope.row.jc) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="nd" label="年度" width="80" align="center" />
|
||||
<el-table-column label="教研室审批状态" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="typeTag(scope.row.lx)" size="mini">{{ scope.row.lx }}</el-tag>
|
||||
<el-tag :type="auditStatusTag(scope.row.jyspzzt).type" size="mini">{{ auditStatusTag(scope.row.jyspzzt).label }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<el-table-column label="教研室查收状态" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="statusTag(scope.row.status).type" size="mini">{{ statusTag(scope.row.status).label }}</el-tag>
|
||||
<el-tag :type="receiveStatusTag(scope.row.jyscszt).type" size="mini">{{ receiveStatusTag(scope.row.jyscszt).label }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<el-table-column label="创建时间" width="150" align="center">
|
||||
<template slot-scope="scope">{{ fmtDateTime(scope.row.cjsj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="210" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" icon="el-icon-view" @click="openDetail(scope.row)">查看</el-button>
|
||||
<template v-if="scope.row.status === '0'">
|
||||
<el-button type="text" size="mini" icon="el-icon-check" @click="approve(scope.row)">批准</el-button>
|
||||
<el-button type="text" size="mini" icon="el-icon-close" class="danger-btn" @click="reject(scope.row)">驳回</el-button>
|
||||
</template>
|
||||
<el-button v-else type="text" size="mini" class="danger-btn" @click="removeRow(scope.row)">删除</el-button>
|
||||
<div class="ops-cell">
|
||||
<el-button type="text" size="mini" icon="el-icon-view" @click="openDetail(scope.row)">详情</el-button>
|
||||
<el-dropdown v-if="showAuditMenu(scope.row)" trigger="click" @command="cmd => openAudit(scope.row, cmd)">
|
||||
<el-button type="text" size="mini" @click.stop>审批<i class="el-icon-arrow-down el-icon--right" /></el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item v-if="scope.row.jyspzzt === 0" command="jys">教研室审批</el-dropdown-item>
|
||||
<el-dropdown-item v-if="scope.row.jyspzzt === 1" command="jxx">教学系审批</el-dropdown-item>
|
||||
<el-dropdown-item v-if="scope.row.jyspzzt === 1" command="jg">机关审批</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-dropdown v-if="showReceiveMenu(scope.row)" trigger="click" @command="cmd => openReceive(scope.row, cmd)">
|
||||
<el-button type="text" size="mini" @click.stop>查收<i class="el-icon-arrow-down el-icon--right" /></el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item v-if="scope.row.jyscszt === 0" command="jys">教研室查收</el-dropdown-item>
|
||||
<el-dropdown-item command="jg">机关查收</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button v-if="scope.row.sczt === 0 && scope.row.jyspzzt !== 1" type="text" size="mini" class="danger-btn" @click="handleCancel(scope.row)">撤销</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-show="!loading && filteredData.length === 0" description="暂无调整申请" />
|
||||
<el-empty v-show="!loading && tableData.length === 0" description="暂无调整申请" />
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="loadList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 新增申请弹窗 -->
|
||||
<el-dialog title="新增课表调整申请" :visible.sync="dialogVisible" width="640px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="课程名称" prop="kcmc">
|
||||
<el-input v-model="form.kcmc" placeholder="请输入课程名称" />
|
||||
<el-dialog title="新增课表调整申请" :visible.sync="addVisible" width="640px" append-to-body>
|
||||
<el-form ref="addForm" :model="addForm" :rules="addRules" label-width="110px">
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-select v-model="addForm.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="lx">
|
||||
<el-radio-group v-model="form.lx">
|
||||
<el-radio label="调课" />
|
||||
<el-radio label="停课" />
|
||||
<el-radio label="补课" />
|
||||
</el-radio-group>
|
||||
<el-form-item label="课次编号" prop="sskcbbh">
|
||||
<el-input v-model="addForm.sskcbbh" placeholder="请输入课次编号" />
|
||||
<el-button type="primary" plain size="mini" class="pick-lesson-btn" :loading="lessonLoading" @click="loadAdjustableLessons">选择可供调课课次</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="队别(班次)" prop="dbbc">
|
||||
<el-input v-model="form.dbbc" placeholder="请输入队别班次" />
|
||||
<el-form-item label="调课事由" prop="sy">
|
||||
<el-input v-model="addForm.sy" type="textarea" :rows="2" placeholder="请输入调课事由" />
|
||||
</el-form-item>
|
||||
<el-form-item label="原上课时间" prop="sksj">
|
||||
<el-input v-model="form.sksj" placeholder="如:周一 第3-4节" />
|
||||
<el-form-item label="拟调整日期" prop="rq">
|
||||
<el-date-picker v-model="addForm.rq" type="date" value-format="yyyy-MM-dd" placeholder="请选择日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="拟调整时间" prop="zxkb">
|
||||
<el-input v-model="form.zxkb" placeholder="请输入拟调整后的上课时间" />
|
||||
<el-form-item label="拟调整节次" prop="jc">
|
||||
<el-select v-model="addForm.jc" placeholder="请选择节次" style="width: 100%">
|
||||
<el-option v-for="n in jcOptions" :key="n" :label="jcLabel(n)" :value="n" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="申请理由" prop="bz">
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入申请理由" />
|
||||
<el-form-item label="申请教员编号" prop="sqjybh">
|
||||
<el-input v-model="addForm.sqjybh" placeholder="请输入申请教员编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="教学内容">
|
||||
<el-input v-model="addForm.jxnr" placeholder="选填" />
|
||||
</el-form-item>
|
||||
<el-form-item label="教学要点">
|
||||
<el-input v-model="addForm.jxyd" placeholder="选填" />
|
||||
</el-form-item>
|
||||
<el-form-item label="教学方法">
|
||||
<el-input v-model="addForm.jxff" placeholder="选填" />
|
||||
</el-form-item>
|
||||
<el-form-item label="教学保障备注">
|
||||
<el-input v-model="addForm.jxbzbz" placeholder="选填" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用车信息">
|
||||
<el-input v-model="addForm.ycxx" placeholder="选填" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="addForm.bz" type="textarea" :rows="2" placeholder="选填" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" :loading="submitLoading" @click="submitForm">提交申请</el-button>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="addLoading" @click="submitAdd">提交申请</el-button>
|
||||
<el-button @click="addVisible = false">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 可供调课课次选择弹窗 -->
|
||||
<el-dialog title="选择可供调课课次" :visible.sync="lessonDialogVisible" width="760px" append-to-body>
|
||||
<el-table :data="lessonOptions" v-loading="lessonLoading" size="small" border stripe max-height="420">
|
||||
<el-table-column prop="kcmc" label="课程名称" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="原上课时间" width="160" align="center">
|
||||
<template slot-scope="scope">{{ fmtRqJc(scope.row.rq, scope.row.jc) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="xydmc" label="学员队" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="kcxh" label="课次序号" width="90" align="center" />
|
||||
<el-table-column prop="jsbh" label="教室编号" width="110" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="操作" width="90" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="pickLesson(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-show="!lessonLoading && lessonOptions.length === 0" description="暂无可供调课课次" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 审批弹窗 -->
|
||||
<el-dialog :title="auditTitle" :visible.sync="auditVisible" width="520px" append-to-body>
|
||||
<el-form ref="auditForm" :model="auditForm" label-width="100px">
|
||||
<el-form-item label="审批结果" required>
|
||||
<el-radio-group v-model="auditForm.spzt">
|
||||
<el-radio :label="1">同意</el-radio>
|
||||
<el-radio :label="2">发回</el-radio>
|
||||
<el-radio :label="3">拒绝</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="审批意见">
|
||||
<el-input v-model="auditForm.fhyj" type="textarea" :rows="3" placeholder="请输入审批意见(发回/拒绝时必填)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="审批人编号" required>
|
||||
<el-input v-model="auditForm.sprbh" placeholder="请输入审批人编号" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="auditForm.auditRole === 'jg'" label="机关编号" required>
|
||||
<el-input v-model="auditForm.jgbh" placeholder="请输入机关编号" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" :loading="auditLoading" @click="submitAudit">确定</el-button>
|
||||
<el-button @click="auditVisible = false">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 查收弹窗 -->
|
||||
<el-dialog :title="receiveTitle" :visible.sync="receiveVisible" width="460px" append-to-body>
|
||||
<el-form ref="receiveForm" :model="receiveForm" label-width="100px">
|
||||
<el-form-item v-if="receiveForm.type === 'jg'" label="机关编号" required>
|
||||
<el-input v-model="receiveForm.jgbh" placeholder="请输入机关编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="查收人编号" required>
|
||||
<el-input v-model="receiveForm.csrbh" placeholder="请输入查收人编号" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" :loading="receiveLoading" @click="submitReceive">确定</el-button>
|
||||
<el-button @click="receiveVisible = false">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 查看详情弹窗 -->
|
||||
<el-dialog title="申请详情" :visible.sync="detailVisible" width="580px" append-to-body>
|
||||
<el-descriptions v-if="detailTarget" :column="2" border size="small">
|
||||
<el-descriptions-item label="课程名称">{{ detailTarget.kcmc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请类型">
|
||||
<el-tag :type="typeTag(detailTarget.lx)" size="mini">{{ detailTarget.lx }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="队别(班次)">{{ detailTarget.dbbc }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教员">{{ detailTarget.jy }} / {{ detailTarget.sqjy }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学场地">{{ detailTarget.jxcd }}</el-descriptions-item>
|
||||
<el-descriptions-item label="执行时间">{{ detailTarget.zxsj }}</el-descriptions-item>
|
||||
<el-descriptions-item label="原上课时间" :span="2">{{ detailTarget.sksj }}</el-descriptions-item>
|
||||
<el-descriptions-item label="拟调整时间" :span="2">{{ detailTarget.zxkb }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请理由" :span="2">{{ detailTarget.bz }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-dialog title="申请详情" :visible.sync="detailVisible" width="760px" append-to-body>
|
||||
<div v-loading="detailLoading">
|
||||
<el-descriptions v-if="detailData" :column="2" border size="small">
|
||||
<el-descriptions-item label="课程名称">{{ detailData.kcmc || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请教员">{{ detailData.sqjyxm || detailData.sqjybh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="调课事由" :span="2">{{ detailData.sy || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="拟调整时间">{{ fmtRqJc(detailData.rq, detailData.jc) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年度">{{ detailData.nd || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ fmtDateTime(detailData.cjsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室审批状态">
|
||||
<el-tag :type="auditStatusTag(detailData.jyspzzt).type" size="mini">{{ auditStatusTag(detailData.jyspzzt).label }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室查收状态">
|
||||
<el-tag :type="receiveStatusTag(detailData.jyscszt).type" size="mini">{{ receiveStatusTag(detailData.jyscszt).label }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室审批人">{{ detailData.jyspzrbh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室审批时间">{{ fmtDateTime(detailData.jyspzsj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室查收人">{{ detailData.jyscsrbh || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教研室查收时间">{{ fmtDateTime(detailData.jyscssj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="发回意见" :span="2">{{ detailData.fhyj || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学内容" :span="2">{{ detailData.jxnr || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学要点" :span="2">{{ detailData.jxyd || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学方法" :span="2">{{ detailData.jxff || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学保障备注" :span="2">{{ detailData.jxbzbz || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="用车信息" :span="2">{{ detailData.ycxx || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ detailData.bz || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 新教室 -->
|
||||
<div v-if="detailData && detailData.roomList && detailData.roomList.length" class="sub-section">
|
||||
<div class="sub-title">新教室</div>
|
||||
<el-table :data="detailData.roomList" size="small" border stripe>
|
||||
<el-table-column prop="jsbh" label="教室编号" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="jsmc" label="教室名称" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="bz" label="备注" min-width="160" show-overflow-tooltip header-align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 新辅助教员 -->
|
||||
<div v-if="detailData && detailData.teacherList && detailData.teacherList.length" class="sub-section">
|
||||
<div class="sub-title">新辅助教员</div>
|
||||
<el-table :data="detailData.teacherList" size="small" border stripe>
|
||||
<el-table-column prop="fzjybh" label="教员编号" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="fzjyxm" label="教员姓名" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="是否主教员" width="100" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.zjy === 1 ? '是' : '否' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bz" label="备注" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 新学员队 -->
|
||||
<div v-if="detailData && detailData.teamList && detailData.teamList.length" class="sub-section">
|
||||
<div class="sub-title">新学员队</div>
|
||||
<el-table :data="detailData.teamList" size="small" border stripe>
|
||||
<el-table-column prop="xydbh" label="学员队编号" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="xydmc" label="学员队名称" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 新保障明细 -->
|
||||
<div v-if="detailData && detailData.supportList && detailData.supportList.length" class="sub-section">
|
||||
<div class="sub-title">新保障明细</div>
|
||||
<el-table :data="detailData.supportList" size="small" border stripe>
|
||||
<el-table-column prop="bztgmxbh" label="保障编号" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="bztgmxmc" label="保障名称" min-width="160" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="sl" label="数量" width="80" align="center" />
|
||||
<el-table-column prop="bz" label="备注" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 机关审批记录 -->
|
||||
<div v-if="detailData && detailData.auditList && detailData.auditList.length" class="sub-section">
|
||||
<div class="sub-title">机关审批记录</div>
|
||||
<el-table :data="detailData.auditList" size="small" border stripe>
|
||||
<el-table-column prop="jgmc" label="机关" min-width="140" show-overflow-tooltip header-align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jgmc || scope.row.jgbh || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批状态" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="auditStatusTag(scope.row.spzt).type" size="mini">{{ auditStatusTag(scope.row.spzt).label }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sprxm" label="审批人" min-width="110" show-overflow-tooltip header-align="center">
|
||||
<template slot-scope="scope">{{ scope.row.sprxm || scope.row.sprbh || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批时间" width="150" align="center">
|
||||
<template slot-scope="scope">{{ fmtDateTime(scope.row.spsj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fhyj" label="发回意见" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
@@ -142,175 +324,371 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 课表调整申请静态示例数据(待对接 getTimetableAdjustList 接口)
|
||||
const MOCK_LIST = [
|
||||
{ id: 1, kcmc: '高等数学', lx: '调课', jxsj: '2026-2027-1', sksj: '周一 第1-2节', zxkb: '周二 第3-4节', jy: '张教员', sqjy: '张教员', jxcd: '1号教学楼-101', dbbc: '一班', zxsj: '2026-09-01', bz: '因学院集中活动调整上课时间', status: '0' },
|
||||
{ id: 2, kcmc: '大学英语', lx: '停课', jxsj: '2026-2027-1', sksj: '周三 第5-6节', zxkb: '—', jy: '李教员', sqjy: '王教员', jxcd: '1号教学楼-205', dbbc: '二班', zxsj: '2026-09-03', bz: '教员参加教研会议,申请停课顺延', status: '1' },
|
||||
{ id: 3, kcmc: '计算机基础', lx: '补课', jxsj: '2026-2027-1', sksj: '周五 第7-8节', zxkb: '周六 第1-2节', jy: '王教员', sqjy: '王教员', jxcd: '实验楼-303', dbbc: '三班', zxsj: '2026-09-04', bz: '补上周五因停课落下的课程', status: '1' },
|
||||
{ id: 4, kcmc: '军事理论', lx: '调课', jxsj: '2026-2027-1', sksj: '周四 第3-4节', zxkb: '周五 第3-4节', jy: '赵教员', sqjy: '赵教员', jxcd: '3号教学楼-110', dbbc: '一班', zxsj: '2026-09-05', bz: '场地临时被占用,调换上课时间', status: '2' },
|
||||
{ id: 5, kcmc: '高等数学', lx: '补课', jxsj: '2026-2027-1', sksj: '周二 第1-2节', zxkb: '周四 第7-8节', jy: '张教员', sqjy: '张教员', jxcd: '1号教学楼-101', dbbc: '二班', zxsj: '2026-09-06', bz: '补国庆假期调休停上的课程', status: '0' }
|
||||
]
|
||||
import {
|
||||
listScheduleAdjust,
|
||||
listAdjustableLessons,
|
||||
getScheduleAdjustDetail,
|
||||
submitScheduleAdjust,
|
||||
auditByTeachingOffice,
|
||||
auditByTeachingDepartment,
|
||||
auditByAuthority,
|
||||
receiveByTeachingOffice,
|
||||
receiveByAuthority,
|
||||
cancelScheduleAdjust
|
||||
} from '@/api/teachBusiness/courseRunning'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
|
||||
// 状态描述
|
||||
const STATUS_MAP = {
|
||||
'0': { label: '待审批', type: 'warning' },
|
||||
'1': { label: '已批准', type: 'success' },
|
||||
'2': { label: '已驳回', type: 'danger' }
|
||||
// 节次 -> 节次区间映射
|
||||
const JC_SECTION = {
|
||||
1: '1-2节', 2: '3-4节', 3: '5-6节', 4: '7-8节', 5: '9-10节', 6: '11-12节'
|
||||
}
|
||||
|
||||
// 审批状态:0-未审批,1-已同意,2-已发回,3-已拒绝
|
||||
const AUDIT_STATUS = {
|
||||
0: { label: '未审批', type: 'info' },
|
||||
1: { label: '已同意', type: 'success' },
|
||||
2: { label: '已发回', type: 'warning' },
|
||||
3: { label: '已拒绝', type: 'danger' }
|
||||
}
|
||||
|
||||
// 查收状态:0-未查收,1-已查收
|
||||
const RECEIVE_STATUS = {
|
||||
0: { label: '未查收', type: 'info' },
|
||||
1: { label: '已查收', type: 'success' }
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'TimetableAdjust',
|
||||
data() {
|
||||
const curUserName = (this.$store.state.user && this.$store.state.user.name) || ''
|
||||
return {
|
||||
curUserName: curUserName,
|
||||
loading: false,
|
||||
submitLoading: false,
|
||||
allData: [],
|
||||
tableData: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
kcmc: undefined,
|
||||
dbbc: undefined,
|
||||
sqjy: undefined,
|
||||
status: undefined
|
||||
nd: undefined,
|
||||
sqjybh: undefined,
|
||||
jyspzzt: undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
statusOptions: [
|
||||
{ label: '待审批', value: '0' },
|
||||
{ label: '已批准', value: '1' },
|
||||
{ label: '已驳回', value: '2' }
|
||||
// 年度下拉数据来自 /semester/all(真实后端数据)
|
||||
yearOptions: [],
|
||||
defaultNd: undefined,
|
||||
jcOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||
auditStatusOptions: [
|
||||
{ label: '未审批', value: 0 },
|
||||
{ label: '已同意', value: 1 },
|
||||
{ label: '已发回', value: 2 },
|
||||
{ label: '已拒绝', value: 3 }
|
||||
],
|
||||
statCards: [],
|
||||
dialogVisible: false,
|
||||
// 新增申请
|
||||
addVisible: false,
|
||||
addLoading: false,
|
||||
addForm: {},
|
||||
addRules: {
|
||||
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||
sskcbbh: [{ required: true, message: '请输入课次编号', trigger: 'blur' }],
|
||||
sy: [{ required: true, message: '请输入调课事由', trigger: 'blur' }],
|
||||
rq: [{ required: true, message: '请选择拟调整日期', trigger: 'change' }],
|
||||
jc: [{ required: true, message: '请选择拟调整节次', trigger: 'change' }],
|
||||
sqjybh: [{ required: true, message: '请输入申请教员编号', trigger: 'blur' }]
|
||||
},
|
||||
// 可供调课课次
|
||||
lessonDialogVisible: false,
|
||||
lessonLoading: false,
|
||||
lessonOptions: [],
|
||||
// 审批
|
||||
auditVisible: false,
|
||||
auditLoading: false,
|
||||
auditTitle: '审批',
|
||||
auditForm: { ssdksqbh: '', auditRole: 'jys', spzt: 1, fhyj: '', sprbh: '', jgbh: '' },
|
||||
// 查收
|
||||
receiveVisible: false,
|
||||
receiveLoading: false,
|
||||
receiveTitle: '查收',
|
||||
receiveForm: { ssdksqbh: '', type: 'jys', csrbh: '', jgbh: '' },
|
||||
// 详情
|
||||
detailVisible: false,
|
||||
detailTarget: null,
|
||||
form: {},
|
||||
rules: {
|
||||
kcmc: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
|
||||
lx: [{ required: true, message: '请选择申请类型', trigger: 'change' }],
|
||||
dbbc: [{ required: true, message: '请输入队别班次', trigger: 'blur' }],
|
||||
bz: [{ required: true, message: '请输入申请理由', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filteredData() {
|
||||
const q = this.queryParams
|
||||
return this.allData.filter(item => {
|
||||
if (q.kcmc && !(item.kcmc || '').includes(q.kcmc)) return false
|
||||
if (q.dbbc && !(item.dbbc || '').includes(q.dbbc)) return false
|
||||
if (q.sqjy && !(item.sqjy || '').includes(q.sqjy)) return false
|
||||
if (q.status !== undefined && q.status !== '' && item.status !== q.status) return false
|
||||
return true
|
||||
})
|
||||
detailLoading: false,
|
||||
detailData: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
this.loadYearOptions().then(() => this.loadList())
|
||||
},
|
||||
methods: {
|
||||
typeTag(lx) {
|
||||
const map = { '调课': 'warning', '停课': 'danger', '补课': 'success' }
|
||||
return map[lx] || 'info'
|
||||
/* ---------- 年度下拉(数据来自 /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)
|
||||
this.defaultNd = (current && current.nd) || arr[0]
|
||||
if (!this.queryParams.nd) this.queryParams.nd = this.defaultNd
|
||||
return arr
|
||||
}).catch(() => {
|
||||
this.yearOptions = []
|
||||
this.defaultNd = undefined
|
||||
return []
|
||||
})
|
||||
},
|
||||
statusTag(status) {
|
||||
return STATUS_MAP[status] || { label: status, type: 'info' }
|
||||
/* ---------- 通用格式化 ---------- */
|
||||
fmtDateTime(v) {
|
||||
if (!v) return '-'
|
||||
return String(v).replace('T', ' ').substring(0, 16)
|
||||
},
|
||||
loadData() {
|
||||
fmtRqJc(rq, jc) {
|
||||
if (!rq) return '-'
|
||||
const date = String(rq).substring(0, 10)
|
||||
const sec = jc === null || jc === undefined || jc === '' ? '第?节' : (JC_SECTION[jc] || '第' + jc + '节')
|
||||
return date + ' ' + sec
|
||||
},
|
||||
jcLabel(n) {
|
||||
return JC_SECTION[n] || ('第' + n + '节')
|
||||
},
|
||||
auditStatusTag(v) {
|
||||
return AUDIT_STATUS[v] || { label: '-', type: 'info' }
|
||||
},
|
||||
receiveStatusTag(v) {
|
||||
return RECEIVE_STATUS[v] || { label: '-', type: 'info' }
|
||||
},
|
||||
/* ---------- 列表查询 ---------- */
|
||||
loadList() {
|
||||
const params = {
|
||||
pageNum: this.queryParams.pageNum,
|
||||
pageSize: this.queryParams.pageSize
|
||||
}
|
||||
if (this.queryParams.nd) params.nd = this.queryParams.nd
|
||||
if (this.queryParams.sqjybh) params.sqjybh = this.queryParams.sqjybh
|
||||
if (this.queryParams.jyspzzt !== undefined && this.queryParams.jyspzzt !== '') {
|
||||
params.jyspzzt = this.queryParams.jyspzzt
|
||||
}
|
||||
this.loading = true
|
||||
// 模拟接口延迟,后续替换为真实接口
|
||||
setTimeout(() => {
|
||||
this.allData = MOCK_LIST.map((item, index) => ({ ...item, xh: index + 1 }))
|
||||
listScheduleAdjust(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.refreshStatCards()
|
||||
this.loading = false
|
||||
}, 200)
|
||||
},
|
||||
refreshStatCards() {
|
||||
const total = this.allData.length
|
||||
const pending = this.allData.filter(i => i.status === '0').length
|
||||
const approved = this.allData.filter(i => i.status === '1').length
|
||||
const rejected = this.allData.filter(i => i.status === '2').length
|
||||
this.statCards = [
|
||||
{ title: '申请总数', value: total, gradient: 'linear-gradient(135deg, #00875a 0%, #00b877 100%)' },
|
||||
{ title: '待审批', value: pending, gradient: 'linear-gradient(135deg, #e6a23c 0%, #f8b04c 100%)' },
|
||||
{ title: '已批准', value: approved, gradient: 'linear-gradient(135deg, #409eff 0%, #66b1ff 100%)' },
|
||||
{ title: '已驳回', value: rejected, gradient: 'linear-gradient(135deg, #f56c6c 0%, #f78989 100%)' }
|
||||
]
|
||||
},
|
||||
handleStatClick(card) {
|
||||
const statusMap = { '待审批': '0', '已批准': '1', '已驳回': '2' }
|
||||
if (statusMap[card.title]) {
|
||||
this.queryParams.status = this.queryParams.status === statusMap[card.title] ? undefined : statusMap[card.title]
|
||||
this.$message.info(`已按「${card.title}」筛选`)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.refreshStatCards()
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.$message.success('查询完成')
|
||||
this.queryParams.pageNum = 1
|
||||
this.loadList()
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
kcmc: undefined,
|
||||
dbbc: undefined,
|
||||
sqjy: undefined,
|
||||
status: undefined
|
||||
nd: this.defaultNd,
|
||||
sqjybh: undefined,
|
||||
jyspzzt: undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
this.loadList()
|
||||
},
|
||||
refreshStatCards() {
|
||||
const list = this.tableData
|
||||
this.statCards = [
|
||||
{ title: '本页申请', value: list.length, gradient: 'linear-gradient(135deg, #00875a 0%, #00b877 100%)', filter: undefined },
|
||||
{ title: '教研室待审批', value: list.filter(i => i.jyspzzt === 0).length, gradient: 'linear-gradient(135deg, #e6a23c 0%, #f8b04c 100%)', filter: 0 },
|
||||
{ title: '教研室已同意', value: list.filter(i => i.jyspzzt === 1).length, gradient: 'linear-gradient(135deg, #409eff 0%, #66b1ff 100%)', filter: 1 },
|
||||
{ title: '教研室已拒绝', value: list.filter(i => i.jyspzzt === 3).length, gradient: 'linear-gradient(135deg, #f56c6c 0%, #f78989 100%)', filter: 3 }
|
||||
]
|
||||
},
|
||||
handleStatClick(card) {
|
||||
if (card.filter === undefined) return
|
||||
this.queryParams.jyspzzt = this.queryParams.jyspzzt === card.filter ? undefined : card.filter
|
||||
this.handleQuery()
|
||||
},
|
||||
/* ---------- 新增申请 ---------- */
|
||||
openAdd() {
|
||||
this.form = { kcmc: '', lx: '调课', dbbc: '', sksj: '', zxkb: '', bz: '' }
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
this.dialogVisible = true
|
||||
this.addForm = {
|
||||
nd: this.defaultNd || this.yearOptions[0],
|
||||
sskcbbh: '',
|
||||
sy: '',
|
||||
rq: '',
|
||||
jc: 1,
|
||||
sqjybh: this.curUserName,
|
||||
jxnr: '',
|
||||
jxyd: '',
|
||||
jxff: '',
|
||||
jxbzbz: '',
|
||||
ycxx: '',
|
||||
bz: ''
|
||||
}
|
||||
this.$nextTick(() => this.$refs.addForm && this.$refs.addForm.clearValidate())
|
||||
this.addVisible = true
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (!valid) return
|
||||
this.submitLoading = true
|
||||
setTimeout(() => {
|
||||
const nextId = this.allData.length ? Math.max(...this.allData.map(i => i.id)) + 1 : 1
|
||||
this.allData.unshift({
|
||||
id: nextId,
|
||||
kcmc: this.form.kcmc,
|
||||
lx: this.form.lx,
|
||||
jxsj: '2026-2027-1',
|
||||
sksj: this.form.sksj || '待定',
|
||||
zxkb: this.form.lx === '停课' ? '—' : (this.form.zxkb || '待定'),
|
||||
jy: '-',
|
||||
sqjy: this.form.sqjy || '-',
|
||||
jxcd: '-',
|
||||
dbbc: this.form.dbbc,
|
||||
zxsj: this.getNow(),
|
||||
bz: this.form.bz,
|
||||
status: '0'
|
||||
})
|
||||
this.refreshStatCards()
|
||||
this.submitLoading = false
|
||||
this.dialogVisible = false
|
||||
this.$message.success('申请已提交')
|
||||
}, 300)
|
||||
loadAdjustableLessons() {
|
||||
if (!this.addForm.nd) {
|
||||
this.$message.warning('请先选择年度')
|
||||
return
|
||||
}
|
||||
this.lessonLoading = true
|
||||
listAdjustableLessons({ nd: this.addForm.nd }).then(response => {
|
||||
this.lessonOptions = response.data || []
|
||||
this.lessonLoading = false
|
||||
this.lessonDialogVisible = true
|
||||
}).catch(() => {
|
||||
this.lessonLoading = false
|
||||
this.$message.info('后端暂未提供可供调课课次接口,请手动填写课次编号')
|
||||
})
|
||||
},
|
||||
getNow() {
|
||||
const d = new Date()
|
||||
const p = n => (n < 10 ? '0' + n : '' + n)
|
||||
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate())
|
||||
pickLesson(row) {
|
||||
this.addForm.sskcbbh = row.sskcbbh
|
||||
this.lessonDialogVisible = false
|
||||
this.$message.success('已选择课次:' + (row.kcmc || row.sskcbbh))
|
||||
},
|
||||
approve(row) {
|
||||
row.status = '1'
|
||||
this.refreshStatCards()
|
||||
this.$message.success('已批准该申请')
|
||||
submitAdd() {
|
||||
this.$refs.addForm.validate(valid => {
|
||||
if (!valid) return
|
||||
const payload = {
|
||||
sskcbbh: this.addForm.sskcbbh,
|
||||
sy: this.addForm.sy,
|
||||
rq: this.addForm.rq + 'T00:00:00',
|
||||
jc: this.addForm.jc,
|
||||
nd: this.addForm.nd,
|
||||
sqjybh: this.addForm.sqjybh
|
||||
}
|
||||
;['jxnr', 'jxyd', 'jxff', 'jxbzbz', 'ycxx', 'bz'].forEach(key => {
|
||||
if (this.addForm[key]) payload[key] = this.addForm[key]
|
||||
})
|
||||
this.addLoading = true
|
||||
submitScheduleAdjust(payload).then(() => {
|
||||
this.addLoading = false
|
||||
this.addVisible = false
|
||||
this.$message.success('申请提交成功')
|
||||
this.loadList()
|
||||
}).catch(() => {
|
||||
this.addLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
reject(row) {
|
||||
row.status = '2'
|
||||
this.refreshStatCards()
|
||||
this.$message.warning('已驳回该申请')
|
||||
/* ---------- 审批 ---------- */
|
||||
showAuditMenu(row) {
|
||||
return row.sczt === 0 && (row.jyspzzt === 0 || row.jyspzzt === 1)
|
||||
},
|
||||
removeRow(row) {
|
||||
this.$confirm('确认删除该申请?', '提示', { type: 'warning' })
|
||||
openAudit(row, role) {
|
||||
const titleMap = { jys: '教研室审批', jxx: '教学系审批', jg: '机关审批' }
|
||||
this.auditTitle = titleMap[role] || '审批'
|
||||
this.auditForm = {
|
||||
ssdksqbh: row.ssdksqbh,
|
||||
auditRole: role,
|
||||
spzt: 1,
|
||||
fhyj: '',
|
||||
sprbh: this.curUserName,
|
||||
jgbh: ''
|
||||
}
|
||||
this.auditVisible = true
|
||||
},
|
||||
submitAudit() {
|
||||
const f = this.auditForm
|
||||
if (!f.sprbh) {
|
||||
this.$message.warning('请填写审批人编号')
|
||||
return
|
||||
}
|
||||
if (f.auditRole === 'jg' && !f.jgbh) {
|
||||
this.$message.warning('请填写机关编号')
|
||||
return
|
||||
}
|
||||
const payload = {
|
||||
ssdksqbh: f.ssdksqbh,
|
||||
auditRole: f.auditRole,
|
||||
spzt: f.spzt,
|
||||
fhyj: f.fhyj,
|
||||
sprbh: f.sprbh
|
||||
}
|
||||
if (f.jgbh) payload.jgbh = f.jgbh
|
||||
const apiMap = {
|
||||
jys: auditByTeachingOffice,
|
||||
jxx: auditByTeachingDepartment,
|
||||
jg: auditByAuthority
|
||||
}
|
||||
this.auditLoading = true
|
||||
apiMap[f.auditRole](payload).then(() => {
|
||||
this.auditLoading = false
|
||||
this.auditVisible = false
|
||||
this.$message.success('审批成功')
|
||||
this.loadList()
|
||||
}).catch(() => {
|
||||
this.auditLoading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 查收 ---------- */
|
||||
showReceiveMenu(row) {
|
||||
return row.sczt === 0 && row.jyspzzt === 1
|
||||
},
|
||||
openReceive(row, type) {
|
||||
this.receiveTitle = type === 'jys' ? '教研室查收' : '机关查收'
|
||||
this.receiveForm = {
|
||||
ssdksqbh: row.ssdksqbh,
|
||||
type: type,
|
||||
csrbh: this.curUserName,
|
||||
jgbh: ''
|
||||
}
|
||||
this.receiveVisible = true
|
||||
},
|
||||
submitReceive() {
|
||||
const f = this.receiveForm
|
||||
if (!f.csrbh) {
|
||||
this.$message.warning('请填写查收人编号')
|
||||
return
|
||||
}
|
||||
if (f.type === 'jg' && !f.jgbh) {
|
||||
this.$message.warning('请填写机关编号')
|
||||
return
|
||||
}
|
||||
const params = { ssdksqbh: f.ssdksqbh, csrbh: f.csrbh }
|
||||
if (f.jgbh) params.jgbh = f.jgbh
|
||||
const api = f.type === 'jys' ? receiveByTeachingOffice : receiveByAuthority
|
||||
this.receiveLoading = true
|
||||
api(params).then(() => {
|
||||
this.receiveLoading = false
|
||||
this.receiveVisible = false
|
||||
this.$message.success('查收成功')
|
||||
this.loadList()
|
||||
}).catch(() => {
|
||||
this.receiveLoading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 撤销 ---------- */
|
||||
handleCancel(row) {
|
||||
this.$confirm('确认撤销该调课申请?撤销后课次将恢复原时间。', '提示', { type: 'warning' })
|
||||
.then(() => {
|
||||
this.allData = this.allData.filter(i => i.id !== row.id)
|
||||
this.refreshStatCards()
|
||||
this.$message.success('删除成功')
|
||||
cancelScheduleAdjust({ ssdksqbh: row.ssdksqbh, sqjybh: row.sqjybh }).then(() => {
|
||||
this.$message.success('撤销成功')
|
||||
this.loadList()
|
||||
}).catch(() => {})
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
/* ---------- 详情 ---------- */
|
||||
openDetail(row) {
|
||||
this.detailTarget = row
|
||||
this.detailVisible = true
|
||||
this.detailLoading = true
|
||||
this.detailData = null
|
||||
getScheduleAdjustDetail(row.ssdksqbh).then(response => {
|
||||
this.detailData = response.data || {}
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
this.detailData = null
|
||||
this.detailLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,6 +783,30 @@ export default {
|
||||
color: #f78989;
|
||||
}
|
||||
}
|
||||
|
||||
.ops-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0 4px;
|
||||
}
|
||||
|
||||
.pick-lesson-btn {
|
||||
margin-top: 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sub-section {
|
||||
margin-top: 16px;
|
||||
|
||||
.sub-title {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #303133;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
|
||||
@@ -5,9 +5,16 @@
|
||||
<div class="section-header">
|
||||
<div>
|
||||
<div class="section-title">教学资源冲突检查</div>
|
||||
<div class="section-desc">2026年秋季学期教学资源冲突检查,可单独检查或执行全部检查</div>
|
||||
<div class="section-desc">当前检查年度:{{ nd ? nd + ' 年' : '未选择' }},可单独检查或执行全部检查</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<el-form inline class="toolbar-form" @submit.native.prevent>
|
||||
<el-form-item label="年度" class="year-item">
|
||||
<el-select v-model="nd" placeholder="请选择年度" style="width: 130px" @change="handleNdChange">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y + ' 年'" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button size="mini" :disabled="loading" @click="handleReset">重置</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="handleCheckAll">执行全部检查</el-button>
|
||||
</div>
|
||||
@@ -20,7 +27,7 @@
|
||||
:key="item.key"
|
||||
class="check-item-card"
|
||||
:class="{ active: activeKey === item.key }"
|
||||
@click="activeKey = item.checked ? item.key : activeKey"
|
||||
@click="selectCard(item)"
|
||||
>
|
||||
<div class="check-item-header">
|
||||
<span class="check-item-name">{{ item.label }}</span>
|
||||
@@ -45,145 +52,228 @@
|
||||
冲突明细
|
||||
<span v-if="activeKey" class="active-label">— {{ activeLabel }}</span>
|
||||
</div>
|
||||
<span v-if="activeKey" class="detail-count">共 {{ activeDetails.length }} 条记录</span>
|
||||
<span v-if="activeKey" class="detail-count">共 {{ detailTotal }} 条记录</span>
|
||||
</div>
|
||||
<el-table v-if="activeKey" :data="activeDetails" border stripe size="mini" max-height="500">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="冲突号" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="danger" size="mini">#{{ Math.floor(scope.$index / 2) + 1 }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kcmc" label="课程" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column label="日期" width="100">
|
||||
<template slot-scope="scope">{{ formatDateStr(scope.row.rq) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jc" label="节次" width="70" align="center" />
|
||||
<el-table-column prop="bc" label="班次" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="skjy" label="教员" width="90" />
|
||||
<el-table-column prop="jxcd" label="场地" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="zrdw" label="责任单位" width="100" />
|
||||
</el-table>
|
||||
<template v-if="activeKey">
|
||||
<el-table v-loading="detailLoading" :data="activeDetails" border stripe size="mini" max-height="500">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="冲突号" width="90" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.conflictNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="courseNames" label="课程" min-width="150" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="日期" width="100" align="center">
|
||||
<template slot-scope="scope">{{ fmtDate(scope.row.rq) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jc" label="节次" width="70" align="center" />
|
||||
<el-table-column prop="xydNames" label="班次" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="teacherNames" label="教员" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="classroomNames" label="场地" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="responsibleDept" label="责任单位" min-width="110" show-overflow-tooltip header-align="center" />
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-if="detailTotal > 0"
|
||||
class="detail-pagination"
|
||||
background
|
||||
layout="total, prev, pager, next"
|
||||
:current-page="detailQuery.pageNum"
|
||||
:page-size="detailQuery.pageSize"
|
||||
:total="detailTotal"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
<el-empty v-if="detailTotal === 0 && !detailLoading" description="暂无冲突明细" />
|
||||
</template>
|
||||
<el-empty v-else v-show="!loading" description="点击上方卡片「检查」按钮,在此查看冲突明细" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 教学计划静态示例数据(待对接 getTeachingPlanList 接口)
|
||||
const MOCK_PLANS = [
|
||||
{ kcmc: '高等数学', rq: '2026-09-01', jc: 1, bc: '一班', skjy: '张教员', jxcd: '1号教学楼-101', zrdw: '基础部' },
|
||||
{ kcmc: '高等数学', rq: '2026-09-01', jc: 1, bc: '一班', skjy: '张教员', jxcd: '1号教学楼-101', zrdw: '基础部' },
|
||||
{ kcmc: '大学英语', rq: '2026-09-01', jc: 1, bc: '二班', skjy: '李教员', jxcd: '1号教学楼-101', zrdw: '基础部' },
|
||||
{ kcmc: '大学英语', rq: '2026-09-02', jc: 3, bc: '二班', skjy: '李教员', jxcd: '2号教学楼-205', zrdw: '基础部' },
|
||||
{ kcmc: '计算机基础', rq: '2026-09-01', jc: 1, bc: '三班', skjy: '王教员', jxcd: '实验楼-303', zrdw: '信息工程系' },
|
||||
{ kcmc: '军事理论', rq: '2026-09-02', jc: 3, bc: '一班', skjy: '赵教员', jxcd: '3号教学楼-110', zrdw: '政工系' }
|
||||
]
|
||||
import { checkConflict, checkAllConflict, resetConflict, getConflictDetails } from '@/api/teachBusiness/timetableConflict'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
|
||||
function formatDateStr(rq) {
|
||||
return (rq || '').substring(0, 10)
|
||||
}
|
||||
// 四类检查卡片定义(标题/描述与后端 TimetableConflictDimension 枚举一致,作为页面布局常量;
|
||||
// 检查状态与冲突数完全来自后端接口)
|
||||
const CARD_DEFS = [
|
||||
{ key: 'TEAM_CONFLICT', label: '教学班时间冲突检查', desc: '同一教学班次在同一时间段被安排多门课程' },
|
||||
{ key: 'ELECTIVE_REQUIRED_CONFLICT', label: '教学班必修与选修时间冲突检查', desc: '教学班次必修课与选修课时间重叠' },
|
||||
{ key: 'TEACHER_CONFLICT', label: '教员时间冲突检查', desc: '同一教员在同一时间段被安排多门课程' },
|
||||
{ key: 'CLASSROOM_CONFLICT', label: '教室时间冲突检查', desc: '同一教室在同一时间段被多门课程占用' }
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'TimetableConflict',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
allRecords: [],
|
||||
detailLoading: false,
|
||||
// 年度(数据来自 /semester/all,真实后端数据)
|
||||
nd: undefined,
|
||||
yearOptions: [],
|
||||
conflictItems: CARD_DEFS.map(c => ({ ...c, count: 0, checked: false })),
|
||||
activeKey: '',
|
||||
conflictItems: [
|
||||
{ key: 'jxbssj', label: '教学班次时间冲突检查', desc: '同一教学班次在同一时间段被安排多门课程', count: 0, checked: false, details: [] },
|
||||
{ key: 'jxbskcsj', label: '教学班次必修与选修时间冲突检查', desc: '教学班次必修课与选修课时间重叠', count: 0, checked: false, details: [] },
|
||||
{ key: 'jysj', label: '教员时间冲突检查', desc: '同一教员在同一时间段被安排多门课程', count: 0, checked: false, details: [] },
|
||||
{ key: 'jssj', label: '教室时间冲突检查', desc: '同一教室在同一时间段被多门课程占用', count: 0, checked: false, details: [] }
|
||||
]
|
||||
activeDetails: [],
|
||||
detailTotal: 0,
|
||||
detailQuery: { pageNum: 1, pageSize: 20 }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeLabel() {
|
||||
const item = this.conflictItems.find(i => i.key === this.activeKey)
|
||||
return item ? item.label : ''
|
||||
},
|
||||
// 当前选中检查项的展开明细(打平所有冲突记录)
|
||||
activeDetails() {
|
||||
const item = this.conflictItems.find(i => i.key === this.activeKey)
|
||||
if (!item) return []
|
||||
const flat = []
|
||||
item.details.forEach(d => {
|
||||
d.items.forEach(it => flat.push(it))
|
||||
})
|
||||
return flat
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 初始化演示数据(模拟接口返回)
|
||||
this.allRecords = MOCK_PLANS.map((item, index) => ({ ...item, xh: index + 1 }))
|
||||
this.loadYearOptions()
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 年度下拉(数据来自 /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)
|
||||
this.nd = (current && current.nd) || arr[0]
|
||||
return arr
|
||||
}).catch(() => {
|
||||
this.yearOptions = []
|
||||
this.nd = undefined
|
||||
return []
|
||||
})
|
||||
},
|
||||
fmtDate(rq) {
|
||||
return (rq || '').substring(0, 10)
|
||||
},
|
||||
getStatus(item) {
|
||||
if (!item.checked) return { type: 'info', text: '未检查' }
|
||||
return item.count > 0
|
||||
? { type: 'danger', text: '存在 ' + item.count + ' 处冲突' }
|
||||
: { type: 'success', text: '无冲突' }
|
||||
},
|
||||
/** 通用冲突检测:按分组字段找 > 1 的记录 */
|
||||
detectConflicts(records, groupFields) {
|
||||
const map = {}
|
||||
records.forEach(item => {
|
||||
const key = groupFields.map(f => f + '=' + (item[f] !== undefined && item[f] !== null ? item[f] : '')).join('|') +
|
||||
'|rq=' + formatDateStr(item.rq) + '|jc=' + (item.jc !== undefined && item.jc !== null ? item.jc : '')
|
||||
if (!map[key]) map[key] = []
|
||||
map[key].push(item)
|
||||
})
|
||||
return Object.keys(map)
|
||||
.filter(k => map[k].length > 1)
|
||||
.map(k => ({ key: k, items: map[k] }))
|
||||
.sort((a, b) => a.key.localeCompare(b.key))
|
||||
/* 用后端返回的单卡片结果同步对应卡片状态 */
|
||||
applyCard(card) {
|
||||
if (!card) return
|
||||
const item = this.conflictItems.find(i => i.key === card.dimensionCode)
|
||||
if (!item) return
|
||||
item.checked = card.checked
|
||||
item.count = card.conflictCount
|
||||
},
|
||||
applySummary(summary) {
|
||||
if (!summary || !summary.cards) return
|
||||
summary.cards.forEach(card => this.applyCard(card))
|
||||
},
|
||||
/* ---------- 单个检查 ---------- */
|
||||
handleCheck(item) {
|
||||
if (this.allRecords.length === 0) return
|
||||
let details = []
|
||||
switch (item.key) {
|
||||
case 'jxbssj':
|
||||
details = this.detectConflicts(this.allRecords, ['bc'])
|
||||
break
|
||||
case 'jxbskcsj':
|
||||
details = this.detectConflicts(this.allRecords, ['bc'])
|
||||
break
|
||||
case 'jysj':
|
||||
details = this.detectConflicts(this.allRecords, ['skjy'])
|
||||
break
|
||||
case 'jssj':
|
||||
details = this.detectConflicts(this.allRecords, ['jxcd'])
|
||||
break
|
||||
}
|
||||
item.details = details
|
||||
item.count = details.length
|
||||
item.checked = true
|
||||
this.activeKey = item.key
|
||||
if (item.count > 0) {
|
||||
this.$message.warning('「' + item.label + '」发现 ' + item.count + ' 处冲突')
|
||||
} else {
|
||||
this.$message.success('「' + item.label + '」未发现冲突')
|
||||
if (!this.nd) {
|
||||
this.$message.warning('请先选择年度')
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
checkConflict({ nd: this.nd, dimensionCode: item.key }).then(response => {
|
||||
this.applyCard(response.data)
|
||||
this.activeKey = item.key
|
||||
this.detailQuery.pageNum = 1
|
||||
this.loadDetails()
|
||||
if (item.count > 0) {
|
||||
this.$message.warning('「' + item.label + '」检查完成,发现 ' + item.count + ' 处冲突')
|
||||
} else {
|
||||
this.$message.success('「' + item.label + '」检查完成,未发现冲突')
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 全部检查 ---------- */
|
||||
handleCheckAll() {
|
||||
this.conflictItems.forEach(item => this.handleCheck(item))
|
||||
const firstConflict = this.conflictItems.find(i => i.count > 0)
|
||||
if (firstConflict) {
|
||||
this.activeKey = firstConflict.key
|
||||
if (!this.nd) {
|
||||
this.$message.warning('请先选择年度')
|
||||
return
|
||||
}
|
||||
const total = this.conflictItems.reduce((sum, item) => sum + item.count, 0)
|
||||
this.$message.success('全部检查完成,共发现 ' + total + ' 处冲突')
|
||||
this.loading = true
|
||||
checkAllConflict({ nd: this.nd }).then(response => {
|
||||
const summary = response.data
|
||||
this.applySummary(summary)
|
||||
const total = summary ? summary.totalConflictCount : 0
|
||||
this.$message.success('全部检查完成,共发现 ' + total + ' 处冲突')
|
||||
const firstConflict = this.conflictItems.find(i => i.checked && i.count > 0)
|
||||
const firstChecked = this.conflictItems.find(i => i.checked)
|
||||
this.activeKey = firstConflict ? firstConflict.key : (firstChecked ? firstChecked.key : '')
|
||||
this.detailQuery.pageNum = 1
|
||||
if (this.activeKey) {
|
||||
this.loadDetails()
|
||||
} else {
|
||||
this.activeDetails = []
|
||||
this.detailTotal = 0
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/* ---------- 重置 ---------- */
|
||||
handleReset() {
|
||||
this.conflictItems.forEach(item => {
|
||||
item.count = 0
|
||||
item.checked = false
|
||||
item.details = []
|
||||
if (!this.nd) {
|
||||
this.$message.warning('请先选择年度')
|
||||
return
|
||||
}
|
||||
resetConflict({ nd: this.nd }).then(response => {
|
||||
this.applySummary(response.data)
|
||||
this.activeKey = ''
|
||||
this.activeDetails = []
|
||||
this.detailTotal = 0
|
||||
this.$message.success('检查结果已重置')
|
||||
})
|
||||
},
|
||||
/* 点击卡片:仅已检查的卡片可查看其明细 */
|
||||
selectCard(item) {
|
||||
if (!item.checked) return
|
||||
this.activeKey = item.key
|
||||
this.detailQuery.pageNum = 1
|
||||
this.loadDetails()
|
||||
},
|
||||
/* ---------- 冲突明细 ---------- */
|
||||
loadDetails() {
|
||||
if (!this.activeKey) {
|
||||
this.activeDetails = []
|
||||
this.detailTotal = 0
|
||||
return
|
||||
}
|
||||
this.detailLoading = true
|
||||
getConflictDetails({
|
||||
nd: this.nd,
|
||||
dimensionCode: this.activeKey,
|
||||
pageNum: this.detailQuery.pageNum,
|
||||
pageSize: this.detailQuery.pageSize
|
||||
}).then(response => {
|
||||
const page = response.data || {}
|
||||
this.activeDetails = page.records || []
|
||||
this.detailTotal = page.total || 0
|
||||
}).catch(() => {
|
||||
this.activeDetails = []
|
||||
this.detailTotal = 0
|
||||
}).finally(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
},
|
||||
handlePageChange(page) {
|
||||
this.detailQuery.pageNum = page
|
||||
this.loadDetails()
|
||||
},
|
||||
/* 切换年度:该年度检查状态未知,重置为未检查 */
|
||||
handleNdChange() {
|
||||
this.conflictItems.forEach(i => {
|
||||
i.checked = false
|
||||
i.count = 0
|
||||
})
|
||||
this.activeKey = ''
|
||||
this.$message.info('已重置检查结果')
|
||||
this.activeDetails = []
|
||||
this.detailTotal = 0
|
||||
this.detailQuery.pageNum = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,6 +306,14 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.toolbar-form {
|
||||
margin-right: 4px;
|
||||
|
||||
.year-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,5 +408,10 @@ export default {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.detail-pagination {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,100 +2,46 @@
|
||||
<div class="app-container training-plan-page">
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="120px" class="search-form">
|
||||
<el-row :gutter="32">
|
||||
<!-- 左栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form :model="searchForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="专业名称">
|
||||
<el-input v-model="searchForm.zymc" placeholder="请输入专业名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="专业方向">
|
||||
<el-input v-model="searchForm.zyfx" placeholder="请输入专业方向" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.pxlxEnabled">培训类型</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.pxlx" placeholder="请选择培训类型" clearable class="w-full"
|
||||
:disabled="!searchForm.pxlxEnabled">
|
||||
<el-option v-for="item in pxlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.pxccEnabled">培训层次</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.pxcc" placeholder="请选择培训层次" clearable class="w-full"
|
||||
:disabled="!searchForm.pxccEnabled">
|
||||
<el-option v-for="item in pxccOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义分类">
|
||||
<el-input v-model="searchForm.zdyfl" placeholder="请输入自定义分类" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.zgzyEnabled">主干专业</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.zgzy" placeholder="请选择" clearable class="w-full"
|
||||
:disabled="!searchForm.zgzyEnabled">
|
||||
<el-option v-for="item in zgzyOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-input v-model="searchForm.zymc" placeholder="请输入专业名称(模糊)" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 右栏 -->
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="专业代码">
|
||||
<el-input v-model="searchForm.zydm" placeholder="请输入专业代码" clearable />
|
||||
<el-input v-model="searchForm.zydm" placeholder="请输入专业代码(模糊)" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="学年制">
|
||||
<el-input v-model="searchForm.xnz" placeholder="请输入学年制" clearable />
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="培训类型">
|
||||
<el-input v-model="searchForm.pxlx" placeholder="请输入培训类型(精确)" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.pxlx2Enabled">培训类型2</el-checkbox>
|
||||
</template>
|
||||
<el-select v-model="searchForm.pxlx2" placeholder="请选择培训类型2" clearable class="w-full"
|
||||
:disabled="!searchForm.pxlx2Enabled">
|
||||
<el-option v-for="item in pxlx2Options" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="searchForm.qyztEnabled">启用状态</el-checkbox>
|
||||
</template>
|
||||
<el-radio-group v-model="searchForm.qyzt" :disabled="!searchForm.qyztEnabled">
|
||||
<el-radio :label="'启用'">启用</el-radio>
|
||||
<el-radio :label="'停用'">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="大纲版本">
|
||||
<el-input v-model="searchForm.zybb" placeholder="请输入大纲版本" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="培养目标">
|
||||
<el-input v-model="searchForm.pymb" placeholder="请输入培养目标" clearable />
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="培训层次">
|
||||
<el-input v-model="searchForm.pxcc" placeholder="请输入培训层次(精确)" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="search-footer">
|
||||
<div class="notice">注意:勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 操作与上传区域 ==================== -->
|
||||
<el-card shadow="never" class="action-card">
|
||||
<div class="action-row">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleOpenAdd">新建</el-button>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新建</el-button>
|
||||
<el-button icon="el-icon-download" @click="handleDownload">下载</el-button>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<el-button type="primary" @click="handleTemplateDownload">【人才培养方案目录模板】下载</el-button>
|
||||
<el-button icon="el-icon-download" @click="handleTemplateDownload">【人才培养方案目录模板】下载</el-button>
|
||||
</div>
|
||||
<div class="upload-row">
|
||||
<div class="upload-left">
|
||||
@@ -114,237 +60,387 @@
|
||||
|
||||
<!-- ==================== 3. 数据表格区域 ==================== -->
|
||||
<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="jxgljg" label="教学管理机构" show-overflow-tooltip />
|
||||
<el-table-column prop="xkzyxx" label="学科专业信息" show-overflow-tooltip />
|
||||
<el-table-column prop="rpyx" label="人培信息" width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="fl" label="分类" align="center" />
|
||||
<el-table-column prop="xylb" label="学员类别" align="center" />
|
||||
<el-table-column prop="xnz" label="学年制" align="center" />
|
||||
<el-table-column prop="xsfb" label="学时分布" align="center" />
|
||||
<el-table-column prop="zt" label="状态" align="center" />
|
||||
<el-table-column prop="wjzl" label="文件资料" align="center" />
|
||||
<el-table-column label="操作" align="center" fixed="right" width="140">
|
||||
<div class="list-header">
|
||||
<div class="list-title">人才培养方案列表</div>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" border stripe highlight-current-row>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="zydh" label="专业代号" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="zymc" label="专业名称" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="zyfx" label="专业方向" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="zydm" label="专业代码" min-width="110" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="pxlx" label="培训类型" min-width="110" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="pxcc" label="培训层次" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="pxlx2" label="培训类型2" min-width="110" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="xylb" label="学员类别" min-width="100" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="xnz" label="学年制" min-width="80" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="xqs" label="学期数" width="80" align="center" />
|
||||
<el-table-column prop="zybb" label="专业版本" min-width="100" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="主干专业" width="90" align="center">
|
||||
<template slot-scope="scope">{{ fmtYesNo(scope.row.zgzy) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" style="color: #f56c6c" :disabled="scope.row.ty === 1 || scope.row.zt === '停用'"
|
||||
@click="handleDisable(scope.row)">
|
||||
停用
|
||||
</el-button>
|
||||
<el-tag :type="isTrue(scope.row.ty) ? 'danger' : 'success'" size="mini">
|
||||
{{ isTrue(scope.row.ty) ? '停用' : '启用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="启用时间" width="150" align="center">
|
||||
<template slot-scope="scope">{{ fmtDateTime(scope.row.qysj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="停用时间" width="150" align="center">
|
||||
<template slot-scope="scope">{{ fmtDateTime(scope.row.tysj) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
|
||||
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" icon="el-icon-circle-close" class="danger-text-btn"
|
||||
:disabled="isTrue(scope.row.ty)" @click="handleDisable(scope.row)">停用</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
background
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
: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"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog :visible.sync="dialogVisible" :title="dialogTitle" width="1000px" :align-center="true"
|
||||
:destroy-on-close="true">
|
||||
<div v-loading="editLoading">
|
||||
<el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="140px" class="add-form">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业代号" prop="zydh">
|
||||
<el-input v-model="addForm.zydh" placeholder="请输入专业代号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业名称" prop="zymc">
|
||||
<el-input v-model="addForm.zymc" placeholder="请输入专业名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业方向">
|
||||
<el-input v-model="addForm.zyfx" placeholder="请输入专业方向" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业代码" prop="zydm">
|
||||
<el-input v-model="addForm.zydm" placeholder="请输入专业代码" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业版本">
|
||||
<el-input v-model="addForm.zybb" placeholder="请输入专业版本" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训层次" prop="pxcc">
|
||||
<el-input v-model="addForm.pxcc" placeholder="硕士研究生/博士研究生/本科" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训类型" prop="pxlx">
|
||||
<el-input v-model="addForm.pxlx" placeholder="学历教育/非学历教育" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训类型2">
|
||||
<el-input v-model="addForm.pxlx2" placeholder="全日制/非全日制" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学员类别">
|
||||
<el-input v-model="addForm.xylb" placeholder="请输入学员类别" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学年制">
|
||||
<el-input v-model="addForm.xnz" placeholder="两年半/三年/四年" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期数">
|
||||
<el-input-number v-model="addForm.xqs" :min="1" :max="12" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="自定义分类">
|
||||
<el-input v-model="addForm.zdyfl" placeholder="兵器类/电子信息类" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学管理机构编号">
|
||||
<el-input v-model="addForm.jxgljgbh" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="规范名称">
|
||||
<el-input v-model="addForm.gfmc" placeholder="请输入规范名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业备注">
|
||||
<el-input v-model="addForm.zybz" placeholder="请输入备注" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="培养目标" prop="pymb">
|
||||
<el-input v-model="addForm.pymb" type="textarea" :rows="3" placeholder="请输入培养目标" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-dialog :title="dialog.title" :visible.sync="dialog.visible" width="860px" append-to-body
|
||||
:close-on-click-modal="false">
|
||||
<el-form ref="trainingForm" :model="dialog.form" :rules="rules" label-width="130px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业代号" prop="zydh">
|
||||
<el-input v-model="dialog.form.zydh" placeholder="请输入专业代号(主键)" :disabled="dialog.isEdit" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业名称" prop="zymc">
|
||||
<el-input v-model="dialog.form.zymc" placeholder="请输入专业名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业代码" prop="zydm">
|
||||
<el-input v-model="dialog.form.zydm" placeholder="请输入专业代码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业方向">
|
||||
<el-input v-model="dialog.form.zyfx" placeholder="请输入专业方向" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训层次" prop="pxcc">
|
||||
<el-input v-model="dialog.form.pxcc" placeholder="请输入培训层次" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训类型" prop="pxlx">
|
||||
<el-input v-model="dialog.form.pxlx" placeholder="请输入培训类型" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="培训类型2">
|
||||
<el-input v-model="dialog.form.pxlx2" placeholder="请输入培训类型2" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学员类别">
|
||||
<el-input v-model="dialog.form.xylb" placeholder="请输入学员类别" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学年制">
|
||||
<el-input v-model="dialog.form.xnz" placeholder="请输入学年制" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期数">
|
||||
<el-input-number v-model="dialog.form.xqs" :min="1" :max="20" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业版本">
|
||||
<el-input v-model="dialog.form.zybb" placeholder="请输入专业版本" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="自定义分类">
|
||||
<el-input v-model="dialog.form.zdyfl" placeholder="请输入自定义分类" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学管理机构编号">
|
||||
<el-input v-model="dialog.form.jxgljgbh" placeholder="请输入教学管理机构编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="规范名称">
|
||||
<el-input v-model="dialog.form.gfmc" placeholder="请输入规范名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业规范">
|
||||
<el-input v-model="dialog.form.zygf" placeholder="请输入专业规范" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="简称">
|
||||
<el-input v-model="dialog.form.jc" placeholder="请输入简称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主干专业">
|
||||
<el-radio-group v-model="dialog.form.zgzy">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专业备注">
|
||||
<el-input v-model="dialog.form.zybz" placeholder="请输入专业备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="培养目标">
|
||||
<el-input v-model="dialog.form.pymb" type="textarea" :rows="3" placeholder="请输入培养目标" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" :loading="dialog.submitting" @click="submitDialog">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 详情弹窗 -->
|
||||
<el-dialog title="人才培养方案详情" :visible.sync="detail.visible" width="760px" append-to-body
|
||||
:close-on-click-modal="false">
|
||||
<div v-loading="detail.loading" class="detail-body">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="专业代号">{{ fmtVal(detail.data.zydh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业名称">{{ fmtVal(detail.data.zymc) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业代码">{{ fmtVal(detail.data.zydm) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业方向">{{ fmtVal(detail.data.zyfx) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训类型">{{ fmtVal(detail.data.pxlx) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训层次">{{ fmtVal(detail.data.pxcc) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培训类型2">{{ fmtVal(detail.data.pxlx2) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学员类别">{{ fmtVal(detail.data.xylb) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学年制">{{ fmtVal(detail.data.xnz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学期数">{{ fmtVal(detail.data.xqs) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业版本">{{ fmtVal(detail.data.zybb) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="主干专业">{{ fmtYesNo(detail.data.zgzy) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="自定义分类">{{ fmtVal(detail.data.zdyfl) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学管理机构编号">{{ fmtVal(detail.data.jxgljgbh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="规范名称">{{ fmtVal(detail.data.gfmc) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业规范">{{ fmtVal(detail.data.zygf) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="简称">{{ fmtVal(detail.data.jc) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业标识号">{{ fmtVal(detail.data.zybsh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学科专业信息标识号">{{ fmtVal(detail.data.xkzyxxbsh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="教学大纲编号">{{ fmtVal(detail.data.jxdgbh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="人培编号">{{ fmtVal(detail.data.rpbh) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="节次类别">{{ fmtVal(detail.data.jclb) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="系统模式">{{ fmtVal(detail.data.xtms) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="启用时间">{{ fmtDateTime(detail.data.qysj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="停用时间">{{ fmtDateTime(detail.data.tysj) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="专业备注" :span="2">{{ fmtVal(detail.data.zybz) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="培养目标" :span="2">{{ fmtVal(detail.data.pymb) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" :loading="addLoading" @click="handleSubmit">保存</el-button>
|
||||
<el-button @click="detail.visible = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 各下拉框选项:数据待后端接口返回后替换
|
||||
const PXLX_OPTIONS = [] // 培训类型
|
||||
const PXCC_OPTIONS = [] // 培训层次
|
||||
const ZGZY_OPTIONS = [] // 主干专业
|
||||
const PXLX2_OPTIONS = [] // 培训类型2
|
||||
import {
|
||||
addTraining,
|
||||
disableTraining,
|
||||
updateTraining,
|
||||
getTraining,
|
||||
listTraining
|
||||
} from '@/api/teachBusiness/training'
|
||||
|
||||
export default {
|
||||
name: 'TrainingPlan',
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
pxlx: PXLX_OPTIONS,
|
||||
pxcc: PXCC_OPTIONS,
|
||||
zgzy: ZGZY_OPTIONS,
|
||||
pxlx2: PXLX2_OPTIONS
|
||||
},
|
||||
// 查询条件
|
||||
loading: false,
|
||||
// 查询条件(仅传后端 ZYBMapper 支持的字段)
|
||||
searchForm: {
|
||||
zymc: '', zyfx: '',
|
||||
pxlxEnabled: false, pxlx: '',
|
||||
pxccEnabled: false, pxcc: '',
|
||||
zdyfl: '',
|
||||
zgzyEnabled: false, zgzy: '',
|
||||
zydm: '', xnz: '',
|
||||
pxlx2Enabled: false, pxlx2: '',
|
||||
qyztEnabled: false, qyzt: '启用',
|
||||
zybb: '', pymb: ''
|
||||
zymc: '',
|
||||
zydm: '',
|
||||
pxlx: '',
|
||||
pxcc: ''
|
||||
},
|
||||
// 列表
|
||||
loading: false,
|
||||
tableData: [],
|
||||
selectedRows: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
// 上传
|
||||
selectedFile: null,
|
||||
fileName: '',
|
||||
// 新增/编辑弹窗
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新建',
|
||||
editLoading: false,
|
||||
addLoading: false,
|
||||
addForm: {
|
||||
zydh: '', zymc: '', zyfx: '', zydm: '', zybb: '', pxcc: '', pxlx: '',
|
||||
pxlx2: '', xylb: '', xnz: '', xqs: 1, zdyfl: '', jxgljgbh: '',
|
||||
gfmc: '', zybz: '', pymb: ''
|
||||
dialog: {
|
||||
visible: false,
|
||||
title: '',
|
||||
isEdit: false,
|
||||
submitting: false,
|
||||
form: this.createEmptyForm()
|
||||
},
|
||||
// 详情弹窗
|
||||
detail: {
|
||||
visible: false,
|
||||
loading: false,
|
||||
data: {}
|
||||
},
|
||||
rules: {
|
||||
zydh: [{ required: true, message: '请输入专业代号', trigger: 'blur' }],
|
||||
zymc: [{ required: true, message: '请输入专业名称', trigger: 'blur' }],
|
||||
zydm: [{ required: true, message: '请输入专业代码', trigger: 'blur' }],
|
||||
pxcc: [{ required: true, message: '请输入培训层次', trigger: 'blur' }],
|
||||
pxlx: [{ required: true, message: '请输入培训类型', trigger: 'blur' }],
|
||||
pymb: [{ required: true, message: '请输入培养目标', trigger: 'blur' }]
|
||||
pxlx: [{ required: true, message: '请输入培训类型', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pxlxOptions() { return this.options.pxlx },
|
||||
pxccOptions() { return this.options.pxcc },
|
||||
zgzyOptions() { return this.options.zgzy },
|
||||
pxlx2Options() { return this.options.pxlx2 }
|
||||
},
|
||||
created() {
|
||||
// TODO: 待后端接口,拉取下拉选项与列表
|
||||
// this.loadOptions()
|
||||
// this.getList()
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
/** 查询 */
|
||||
handleSearch() {
|
||||
// TODO: 调用查询接口
|
||||
},
|
||||
/** 重置 */
|
||||
handleReset() {
|
||||
this.searchForm = {
|
||||
zymc: '', zyfx: '', pxlxEnabled: false, pxlx: '',
|
||||
pxccEnabled: false, pxcc: '', zdyfl: '', zgzyEnabled: false, zgzy: '',
|
||||
zydm: '', xnz: '', pxlx2Enabled: false, pxlx2: '',
|
||||
qyztEnabled: false, qyzt: '启用', zybb: '', pymb: ''
|
||||
/* ---------- 列表加载 ---------- */
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = {
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}
|
||||
Object.keys(this.searchForm).forEach(key => {
|
||||
const value = this.searchForm[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
params[key] = value
|
||||
}
|
||||
})
|
||||
listTraining(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 新建 */
|
||||
handleOpenAdd() {
|
||||
// TODO: 打开新建对话框
|
||||
this.dialogVisible = true
|
||||
this.dialogTitle = '新建人才培养方案'
|
||||
|
||||
/* ---------- 查询 / 重置 ---------- */
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
/** 下载 */
|
||||
handleReset() {
|
||||
this.searchForm = { zymc: '', zydm: '', pxlx: '', pxcc: '' }
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/* ---------- 分页 ---------- */
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/* ---------- 新增 / 编辑 ---------- */
|
||||
handleAdd() {
|
||||
this.dialog.title = '新建人才培养方案'
|
||||
this.dialog.isEdit = false
|
||||
this.dialog.form = this.createEmptyForm()
|
||||
this.dialog.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.trainingForm) this.$refs.trainingForm.clearValidate()
|
||||
})
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.dialog.title = '编辑人才培养方案'
|
||||
this.dialog.isEdit = true
|
||||
this.dialog.form = Object.assign({}, this.createEmptyForm(), row)
|
||||
this.dialog.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.trainingForm) this.$refs.trainingForm.clearValidate()
|
||||
})
|
||||
},
|
||||
submitDialog() {
|
||||
this.$refs.trainingForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.dialog.submitting = true
|
||||
const payload = this.cleanPayload(this.dialog.form)
|
||||
const isEdit = this.dialog.isEdit
|
||||
const req = isEdit ? updateTraining(payload) : addTraining(payload)
|
||||
req.then(() => {
|
||||
this.$message.success(isEdit ? '修改成功' : '新增成功')
|
||||
this.dialog.visible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.dialog.submitting = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 详情 ---------- */
|
||||
handleDetail(row) {
|
||||
this.detail.visible = true
|
||||
this.detail.loading = true
|
||||
this.detail.data = {}
|
||||
getTraining(row.zydh).then(response => {
|
||||
this.detail.data = response.data || {}
|
||||
}).catch(() => {
|
||||
this.detail.data = {}
|
||||
}).finally(() => {
|
||||
this.detail.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 停用(逻辑删除) ---------- */
|
||||
handleDisable(row) {
|
||||
this.$confirm('确定停用人才培养方案「' + (row.zymc || row.zydh) + '」吗?停用后列表不再展示。', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return disableTraining(row.zydh)
|
||||
}).then(() => {
|
||||
this.$message.success('停用成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 下载 / 模板下载 / 上传(后端未提供接口) ---------- */
|
||||
handleDownload() {
|
||||
// TODO: 列表数据下载
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
/** 模板下载 */
|
||||
handleTemplateDownload() {
|
||||
// TODO: 模板下载
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
/** 选择文件 */
|
||||
handleChooseFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
@@ -352,76 +448,78 @@ export default {
|
||||
const file = e.target.files && e.target.files[0]
|
||||
this.selectedFile = file || null
|
||||
this.fileName = file ? file.name : ''
|
||||
// TODO: 校验文件类型后保留
|
||||
},
|
||||
/** 上传数据 */
|
||||
handleUpload() {
|
||||
// TODO: 上传接口(上传 selectedFile)
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
/** 表格多选 */
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
|
||||
/* ---------- 工具 ---------- */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
zydh: '',
|
||||
zymc: '',
|
||||
zyfx: '',
|
||||
zydm: '',
|
||||
pxcc: '',
|
||||
pxlx: '',
|
||||
pxlx2: '',
|
||||
xylb: '',
|
||||
xnz: '',
|
||||
xqs: null,
|
||||
zybb: '',
|
||||
zdyfl: '',
|
||||
jxgljgbh: '',
|
||||
gfmc: '',
|
||||
zygf: '',
|
||||
jc: '',
|
||||
zgzy: false,
|
||||
zybz: '',
|
||||
pymb: ''
|
||||
}
|
||||
},
|
||||
/** 编辑 */
|
||||
handleEdit(row) {
|
||||
// TODO: 回填并打开编辑对话框
|
||||
this.dialogVisible = true
|
||||
this.dialogTitle = '编辑人才培养方案'
|
||||
},
|
||||
/** 停用 */
|
||||
handleDisable(row) {
|
||||
// TODO: 停用接口
|
||||
},
|
||||
/** 分页 */
|
||||
handlePageChange(val) {
|
||||
this.pageNum = val
|
||||
// TODO: 重新查询
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.pageSize = val
|
||||
// TODO: 重新查询
|
||||
},
|
||||
/** 取消 */
|
||||
handleCancel() {
|
||||
this.dialogVisible = false
|
||||
this.$refs.addFormRef && this.$refs.addFormRef.clearValidate()
|
||||
},
|
||||
/** 保存 */
|
||||
handleSubmit() {
|
||||
this.$refs.addFormRef.validate(valid => {
|
||||
if (!valid) return
|
||||
// TODO: 新增/编辑接口
|
||||
this.dialogVisible = false
|
||||
/** 移除空值(''/null/undefined),保留 0/false 等有效值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
isTrue(val) {
|
||||
return val === true || val === 1 || val === '1' || val === 'true'
|
||||
},
|
||||
fmtYesNo(val) {
|
||||
return this.isTrue(val) ? '是' : '否'
|
||||
},
|
||||
fmtDateTime(val) {
|
||||
return (val || '').substring(0, 19) || '-'
|
||||
},
|
||||
fmtVal(val) {
|
||||
return val === '' || val === null || val === undefined ? '-' : val
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.training-plan-page {
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
|
||||
.notice {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
.search-actions {
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -466,10 +564,35 @@ export default {
|
||||
}
|
||||
|
||||
.table-card {
|
||||
.pagination-wrapper {
|
||||
margin-top: 14px;
|
||||
.list-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.list-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-body {
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.danger-text-btn {
|
||||
color: #f56c6c;
|
||||
|
||||
&:hover {
|
||||
color: #f78989;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,444 @@
|
||||
<template>
|
||||
<placeholder-page title="教学场地" icon="build" description="维护教学楼、教室、实验室等教学场地资源,支持场地类型、容量与使用状态管理。" />
|
||||
<div class="app-container venue-page">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<el-form :model="searchForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="教室编号">
|
||||
<el-input v-model="searchForm.jsbh" placeholder="请输入教室编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="教室名称">
|
||||
<el-input v-model="searchForm.jsmc" placeholder="请输入教室名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="教学楼代号">
|
||||
<el-input v-model="searchForm.jxldh" placeholder="请输入教学楼代号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="教学场地类型">
|
||||
<el-select v-model="searchForm.jxcdlx" placeholder="请选择场地类型" clearable filterable allow-create
|
||||
default-first-option class="w-full">
|
||||
<el-option v-for="item in jxcdlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="停用">
|
||||
<el-select v-model="searchForm.ty" placeholder="全部" clearable class="w-full">
|
||||
<el-option :value="true" label="停用" />
|
||||
<el-option :value="false" label="正常" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 数据列表 -->
|
||||
<el-card shadow="never" class="table-card">
|
||||
<div class="list-header">
|
||||
<div class="list-title">教室列表</div>
|
||||
<div class="list-actions">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="tableData" border stripe highlight-current-row>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="jsbh" label="教室编号" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="jsmc" label="教室名称" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="jxldh" label="教学楼代号" min-width="110" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="jxcdlx" label="教学场地类型" min-width="120" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="jc" label="简称" min-width="90" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column prop="rnrs" label="容纳人数" width="90" align="center" />
|
||||
<el-table-column prop="mj" label="面积" width="90" align="center" />
|
||||
<el-table-column prop="ksrnrs" label="考试容纳人数" width="110" align="center" />
|
||||
<el-table-column prop="ewyxkbs" label="额外可开班数" width="100" align="center" />
|
||||
<el-table-column label="虚实类型" width="90" align="center">
|
||||
<template slot-scope="scope">{{ fmtXslx(scope.row.xslx) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="停用" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="isTrue(scope.row.ty) ? 'danger' : 'success'" size="mini">
|
||||
{{ isTrue(scope.row.ty) ? '停用' : '正常' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sssb" label="设施设备" min-width="140" show-overflow-tooltip header-align="center" />
|
||||
<el-table-column label="操作" width="140" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" icon="el-icon-delete" class="danger-text-btn" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
background
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:current-page="pageNum"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog :title="dialog.title" :visible.sync="dialog.visible" width="780px" append-to-body
|
||||
:close-on-click-modal="false">
|
||||
<el-form ref="classroomForm" :model="dialog.form" :rules="rules" label-width="110px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主键编号" prop="id">
|
||||
<el-input v-model="dialog.form.id" placeholder="请输入主键编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教室编号" prop="jsbh">
|
||||
<el-input v-model="dialog.form.jsbh" placeholder="请输入教室编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教室名称" prop="jsmc">
|
||||
<el-input v-model="dialog.form.jsmc" placeholder="请输入教室名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学楼代号">
|
||||
<el-input v-model="dialog.form.jxldh" placeholder="请输入教学楼代号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学场地类型">
|
||||
<el-select v-model="dialog.form.jxcdlx" placeholder="请选择场地类型" clearable filterable allow-create
|
||||
default-first-option class="w-full">
|
||||
<el-option v-for="item in jxcdlxOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="简称">
|
||||
<el-input v-model="dialog.form.jc" placeholder="请输入简称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="容纳人数">
|
||||
<el-input-number v-model="dialog.form.rnrs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="面积">
|
||||
<el-input-number v-model="dialog.form.mj" :min="0" :precision="1" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考试容纳人数">
|
||||
<el-input-number v-model="dialog.form.ksrnrs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="额外可开班数">
|
||||
<el-input-number v-model="dialog.form.ewyxkbs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="序号">
|
||||
<el-input v-model="dialog.form.xh" placeholder="请输入序号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="拼音">
|
||||
<el-input v-model="dialog.form.py" placeholder="请输入拼音" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="虚实类型">
|
||||
<el-radio-group v-model="dialog.form.xslx">
|
||||
<el-radio :label="true">实教</el-radio>
|
||||
<el-radio :label="false">非实教</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="停用">
|
||||
<el-radio-group v-model="dialog.form.ty">
|
||||
<el-radio :label="false">正常</el-radio>
|
||||
<el-radio :label="true">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设施设备">
|
||||
<el-input v-model="dialog.form.sssb" placeholder="请输入设施设备" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="dialog.form.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" :loading="dialog.submitting" @click="submitDialog">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlaceholderPage from '@/components/PlaceholderPage'
|
||||
import {
|
||||
addClassroom,
|
||||
deleteClassroom,
|
||||
updateClassroom,
|
||||
listClassroom
|
||||
} from '@/api/teachBusiness/classroom'
|
||||
|
||||
export default {
|
||||
name: 'Venue',
|
||||
components: { PlaceholderPage }
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
searchForm: {
|
||||
jsbh: '',
|
||||
jsmc: '',
|
||||
jxldh: '',
|
||||
jxcdlx: '',
|
||||
ty: ''
|
||||
},
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
dialog: {
|
||||
visible: false,
|
||||
title: '',
|
||||
submitting: false,
|
||||
form: this.createEmptyForm()
|
||||
},
|
||||
rules: {
|
||||
id: [{ required: true, message: '请输入主键编号', trigger: 'blur' }],
|
||||
jsbh: [{ required: true, message: '请输入教室编号', trigger: 'blur' }],
|
||||
jsmc: [{ required: true, message: '请输入教室名称', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 教学场地类型下拉:由已加载数据中的去重值动态生成,避免硬编码 */
|
||||
jxcdlxOptions() {
|
||||
const set = new Set()
|
||||
this.tableData.forEach(row => {
|
||||
if (row.jxcdlx) set.add(row.jxcdlx)
|
||||
})
|
||||
return Array.from(set)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 列表加载 ---------- */
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = {
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}
|
||||
Object.keys(this.searchForm).forEach(key => {
|
||||
const value = this.searchForm[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
params[key] = value
|
||||
}
|
||||
})
|
||||
listClassroom(params).then(response => {
|
||||
const data = response.data || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 查询 / 重置 ---------- */
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm = {
|
||||
jsbh: '',
|
||||
jsmc: '',
|
||||
jxldh: '',
|
||||
jxcdlx: '',
|
||||
ty: ''
|
||||
}
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/* ---------- 分页 ---------- */
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/* ---------- 新增 / 编辑 ---------- */
|
||||
handleAdd() {
|
||||
this.dialog.title = '新增教室'
|
||||
this.dialog.form = this.createEmptyForm()
|
||||
this.dialog.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.classroomForm) this.$refs.classroomForm.clearValidate()
|
||||
})
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.dialog.title = '编辑教室'
|
||||
this.dialog.form = Object.assign({}, this.createEmptyForm(), row)
|
||||
this.dialog.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.classroomForm) this.$refs.classroomForm.clearValidate()
|
||||
})
|
||||
},
|
||||
submitDialog() {
|
||||
this.$refs.classroomForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.dialog.submitting = true
|
||||
const payload = this.cleanPayload(this.dialog.form)
|
||||
const isEdit = !!payload.id
|
||||
const req = isEdit ? updateClassroom(payload) : addClassroom(payload)
|
||||
req.then(() => {
|
||||
this.$message.success(isEdit ? '修改成功' : '新增成功')
|
||||
this.dialog.visible = false
|
||||
this.fetchList()
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.dialog.submitting = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 删除(后端仅提供单条删除,参数为 id) ---------- */
|
||||
handleDelete(row) {
|
||||
this.$confirm('确定删除教室「' + (row.jsmc || row.jsbh) + '」吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return deleteClassroom(row.id)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
/* ---------- 工具 ---------- */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
id: '',
|
||||
jsbh: '',
|
||||
jsmc: '',
|
||||
jxldh: '',
|
||||
jxcdlx: '',
|
||||
jc: '',
|
||||
rnrs: null,
|
||||
mj: null,
|
||||
ksrnrs: null,
|
||||
ewyxkbs: null,
|
||||
xh: '',
|
||||
py: '',
|
||||
xslx: false,
|
||||
ty: false,
|
||||
sssb: '',
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
/** 移除空值(''/null/undefined),保留 0/false 等有效值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
isTrue(val) {
|
||||
return val === true || val === 1 || val === '1' || val === 'true'
|
||||
},
|
||||
fmtXslx(val) {
|
||||
return this.isTrue(val) ? '实教' : '非实教'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.venue-page {
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.search-form {
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-card {
|
||||
.list-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.list-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.danger-text-btn {
|
||||
color: #f56c6c;
|
||||
|
||||
&:hover {
|
||||
color: #f78989;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -44,7 +44,6 @@
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="notice">注意:勾选"选择框"表示启用该项对应的查询条件;文本输入框非空白表示启用对应的查询条件。</div>
|
||||
<div class="query-footer">
|
||||
<el-button class="gray-btn" @click="handleQuery">查询</el-button>
|
||||
</div>
|
||||
@@ -99,15 +98,7 @@
|
||||
<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 prop="teamClass" label="显示可选队别班次" min-width="150" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="计划学时/运行学时/学分" width="130" align="center">
|
||||
<template slot="header">
|
||||
<div class="triple-header">
|
||||
@@ -488,13 +479,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.checkable-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.triple-header,
|
||||
.triple-cell {
|
||||
display: flex;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,82 +1,79 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="教学班次学期信息明细"
|
||||
width="720px"
|
||||
:title="isEdit ? '编辑班次学期信息' : '教学班次学期信息明细'"
|
||||
width="620px"
|
||||
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-form ref="formRef" :model="form" :rules="rules" label-width="110px" class="detail-form">
|
||||
<!-- 班次信息(只读展示) -->
|
||||
<el-row :gutter="16">
|
||||
<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-input :value="form.xydmc || form.xydbh" readonly />
|
||||
</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-form-item label="班次编号">
|
||||
<el-input v-model="form.xydbh" :readonly="isEdit" :disabled="isEdit" placeholder="编辑模式不可修改" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="nd">
|
||||
<el-select v-model="form.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="学期层次">
|
||||
<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-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学期第次" prop="xqdc">
|
||||
<el-select v-model="form.xqdc" placeholder="请选择学期" style="width: 100%">
|
||||
<el-option v-for="opt in levelOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 备注 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开学日期" prop="kxrq">
|
||||
<el-date-picker v-model="form.kxrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束日期" prop="jsrq">
|
||||
<el-date-picker v-model="form.jsrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专用教室">
|
||||
<el-input v-model="form.zyjsbh" placeholder="请输入专用教室编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="教学任务">
|
||||
<el-select v-model="form.jxrwbh" clearable filterable placeholder="请选择教学任务" 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-col>
|
||||
</el-row>
|
||||
<el-form-item label="开放教员排课">
|
||||
<el-checkbox v-model="form.kfjypk">开放教员排课</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="" style="width: 100%" />
|
||||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入备注" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -86,35 +83,32 @@ export default {
|
||||
name: 'ClassSemesterDetailDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 选中的班次信息 */
|
||||
classInfo: { type: Object, default: null },
|
||||
/** 学期名称 */
|
||||
semesterName: { type: String, default: '2017年秋季学期' }
|
||||
/** 编辑模式:edit / add */
|
||||
mode: { type: String, default: 'add' },
|
||||
/** 编辑时的班次学期记录 */
|
||||
semester: { type: Object, default: null },
|
||||
/** 新增时选中的班次(学员队)信息 */
|
||||
teamInfo: { type: Object, default: null },
|
||||
/** 年度下拉 */
|
||||
yearOptions: { type: Array, default: () => [] },
|
||||
/** 教学任务下拉({ bh, rwmc }) */
|
||||
taskOptions: { type: Array, default: () => [] }
|
||||
},
|
||||
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', '学术报告厅']
|
||||
form: this.createEmptyForm(),
|
||||
levelOptions: [
|
||||
{ label: '第1学期', value: 1 },
|
||||
{ label: '第2学期', value: 2 },
|
||||
{ label: '第3学期', value: 3 }
|
||||
],
|
||||
saving: false,
|
||||
rules: {
|
||||
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||
xqdc: [{ required: true, message: '请选择学期第次', trigger: 'change' }],
|
||||
kxrq: [{ required: true, message: '请选择开学日期', trigger: 'change' }],
|
||||
jsrq: [{ required: true, message: '请选择结束日期', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -125,22 +119,93 @@ export default {
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
isEdit() {
|
||||
return this.mode === 'edit'
|
||||
}
|
||||
},
|
||||
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
|
||||
this.initForm()
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.formRef) this.$refs.formRef.clearValidate()
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleConfirm() {
|
||||
this.$emit('confirm')
|
||||
this.dialogVisible = false
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
xydbh: '',
|
||||
xydmc: '',
|
||||
nd: undefined,
|
||||
xqdc: undefined,
|
||||
kxrq: '',
|
||||
jsrq: '',
|
||||
zyjsbh: '',
|
||||
jxrwbh: undefined,
|
||||
kfjypk: false,
|
||||
bz: ''
|
||||
}
|
||||
},
|
||||
/** 打开时按编辑/新增模式初始化表单 */
|
||||
initForm() {
|
||||
const form = this.createEmptyForm()
|
||||
if (this.isEdit && this.semester) {
|
||||
const row = this.semester
|
||||
form.bh = row.bh || ''
|
||||
form.xydbh = row.xydbh || ''
|
||||
form.xydmc = row.xydmc || ''
|
||||
form.nd = row.nd
|
||||
form.xqdc = row.xqdc
|
||||
form.kxrq = row.kxrq ? String(row.kxrq).slice(0, 10) : ''
|
||||
form.jsrq = row.jsrq ? String(row.jsrq).slice(0, 10) : ''
|
||||
form.zyjsbh = row.zyjsbh || ''
|
||||
form.jxrwbh = row.jxrwbh || undefined
|
||||
form.kfjypk = Number(row.kfjypk) === 1
|
||||
form.bz = row.bz || ''
|
||||
} else if (this.teamInfo) {
|
||||
form.xydbh = this.teamInfo.xydbh || ''
|
||||
form.xydmc = this.teamInfo.xydmc || ''
|
||||
// 默认取当前选中年度的第一学期,日期可后续修改
|
||||
form.nd = this.yearOptions[0]
|
||||
form.xqdc = 1
|
||||
}
|
||||
this.form = form
|
||||
},
|
||||
/** 移除空值(保留 0 等有效值) */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) return
|
||||
if (!this.form.xydbh) {
|
||||
this.$message.warning('缺少班次编号,无法保存')
|
||||
return
|
||||
}
|
||||
const payload = this.cleanPayload({
|
||||
bh: this.form.bh,
|
||||
xydbh: this.form.xydbh,
|
||||
nd: this.form.nd,
|
||||
xqdc: this.form.xqdc,
|
||||
kxrq: this.form.kxrq,
|
||||
jsrq: this.form.jsrq,
|
||||
zyjsbh: this.form.zyjsbh,
|
||||
jxrwbh: this.form.jxrwbh,
|
||||
kfjypk: this.form.kfjypk ? 1 : 0,
|
||||
bz: this.form.bz
|
||||
})
|
||||
this.$emit('submit', payload)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,22 +218,6 @@ export default {
|
||||
::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>
|
||||
|
||||
@@ -1,148 +1,71 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="学员队选取"
|
||||
width="90%"
|
||||
top="5vh"
|
||||
:title="title"
|
||||
width="900px"
|
||||
top="8vh"
|
||||
:close-on-click-modal="false"
|
||||
class="team-select-dialog"
|
||||
@update:visible="val => dialogVisible = val"
|
||||
>
|
||||
<div class="team-select">
|
||||
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||
<!-- ==================== 操作说明 ==================== -->
|
||||
<div v-if="excludeNote" class="note-bar">
|
||||
<i class="el-icon-info"></i>
|
||||
<span>{{ excludeNote }}</span>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 查询条件区域 ==================== -->
|
||||
<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 :inline="true" class="query-form" @submit.native.prevent>
|
||||
<el-form-item label="班次编号">
|
||||
<el-input
|
||||
v-model="queryForm.xydbh"
|
||||
placeholder="请输入班次编号(模糊)"
|
||||
clearable
|
||||
style="width: 220px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button size="small" @click="handleResetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</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"
|
||||
ref="tableRef"
|
||||
v-loading="loading"
|
||||
:data="filteredList"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
max-height="360"
|
||||
class="team-table"
|
||||
@selection-change="handleBottomSelectionChange"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<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 type="selection" width="44" align="center" reserve-selection />
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<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="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-column prop="xydbh" label="班次编号" min-width="150" align="left" header-align="center" show-overflow-tooltip />
|
||||
<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="bz" label="备注" min-width="120" align="left" header-align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<el-empty v-if="!selectedList.length" description="暂无已选学员队,请从上方表格加入" :image-size="60" />
|
||||
<el-empty v-if="!filteredList.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>
|
||||
<span class="selected-count">已选择 {{ selection.length }} 个班次学期</span>
|
||||
<el-button size="small" @click="dialogVisible = false">取消</el-button>
|
||||
<el-button size="small" type="primary" :disabled="!selection.length" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -152,52 +75,21 @@
|
||||
export default {
|
||||
name: 'ClassTeamSelectDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, default: false }
|
||||
visible: { type: Boolean, default: false },
|
||||
/** 标题(可选) */
|
||||
title: { type: String, default: '目标班次学期选取' },
|
||||
/** 可选的目标班次学期列表(含 bh/nd/xqdc/xydbh/kxrq/jsrq 等) */
|
||||
semesterList: { type: Array, default: () => [] },
|
||||
/** 需要排除的班次学期编号(当前班次学期,不可复制给自己) */
|
||||
excludeBh: { type: String, default: '' },
|
||||
/** 顶部操作说明 */
|
||||
excludeNote: { type: String, default: '' }
|
||||
},
|
||||
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: []
|
||||
loading: false,
|
||||
queryForm: { xydbh: '' },
|
||||
selection: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -208,105 +100,54 @@ export default {
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
},
|
||||
/** 排除当前班次学期后的可选列表 */
|
||||
availableList() {
|
||||
const excludeBh = this.excludeBh || ''
|
||||
return (this.semesterList || []).filter(item => item.bh && String(item.bh) !== String(excludeBh))
|
||||
},
|
||||
/** 本地过滤后的列表 */
|
||||
filteredList() {
|
||||
const kw = (this.queryForm.xydbh || '').trim()
|
||||
if (!kw) return this.availableList
|
||||
return this.availableList.filter(item => item.xydbh && String(item.xydbh).includes(kw))
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.selection = []
|
||||
this.queryForm.xydbh = ''
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.tableRef) this.$refs.tableRef.clearSelection()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTopSelectionChange(rows) {
|
||||
this.topSelection = rows
|
||||
fmtDate(val) {
|
||||
if (!val) return '-'
|
||||
return String(val).slice(0, 10)
|
||||
},
|
||||
handleBottomSelectionChange(rows) {
|
||||
this.bottomSelection = rows
|
||||
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}学期` : '-'
|
||||
},
|
||||
|
||||
// ==================== 分页控制 ====================
|
||||
handleQuery() {
|
||||
this.$message.success('查询(前端演示)')
|
||||
handleSelectionChange(rows) {
|
||||
this.selection = rows
|
||||
},
|
||||
handleFirst() {
|
||||
this.currentPage = 1
|
||||
this.$message.success('已跳转首页')
|
||||
handleQuery() {},
|
||||
handleResetQuery() {
|
||||
this.queryForm.xydbh = ''
|
||||
},
|
||||
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('请先选择要应用的学员队')
|
||||
if (!this.selection.length) {
|
||||
this.$message.warning('请先勾选目标班次学期')
|
||||
return
|
||||
}
|
||||
this.$emit('confirm', this.selectedList.slice())
|
||||
this.dialogVisible = false
|
||||
this.$message.success(`选定区域设置已应用于 ${this.selectedList.length} 个班次`)
|
||||
},
|
||||
handleCancel() {
|
||||
this.$emit('confirm', this.selection.slice())
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
@@ -319,40 +160,34 @@ export default {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
|
||||
// ========== 1. 查询条件区域 ==========
|
||||
// ========== 操作说明 ==========
|
||||
.note-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
color: #1e6fff;
|
||||
background: #ecf5ff;
|
||||
border: 1px solid #d9ecff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
// ========== 查询条件区域 ==========
|
||||
.query-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 12px 16px 8px;
|
||||
padding: 10px 12px 2px;
|
||||
|
||||
.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;
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 2/4. 表格区域 ==========
|
||||
// ========== 表格区域 ==========
|
||||
.table-panel {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
@@ -370,69 +205,19 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 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;
|
||||
align-items: center;
|
||||
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;
|
||||
.selected-count {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,706 +0,0 @@
|
||||
<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>
|
||||
@@ -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" 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div class="app-container subject-page">
|
||||
<!-- ==================== 1. 顶部状态提示 ==================== -->
|
||||
<div class="status-tip">{{ statusTip }}</div>
|
||||
|
||||
<!-- ==================== 2. 查询条件区域 ==================== -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
@@ -10,152 +8,41 @@
|
||||
<!-- 左栏 -->
|
||||
<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" />
|
||||
<span class="q-label no-check">课名称</span>
|
||||
<el-input v-model="searchForm.kmc" 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" />
|
||||
<span class="q-label no-check">科目代码</span>
|
||||
<el-input v-model="searchForm.kmdm" 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>
|
||||
<span class="q-label no-check">培训层次</span>
|
||||
<el-input v-model="searchForm.pxcc" 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.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" />
|
||||
<span class="q-label no-check">课程类型</span>
|
||||
<el-input v-model="searchForm.kclx" 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>
|
||||
<span class="q-label no-check">简称</span>
|
||||
<el-input v-model="searchForm.jc" 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>
|
||||
<span class="q-label no-check">教研室代号</span>
|
||||
<el-input v-model="searchForm.jysdh" placeholder="请输入教研室代号" clearable class="q-control" />
|
||||
</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>
|
||||
<span class="q-label no-check">培训类型</span>
|
||||
<el-input v-model="searchForm.pxlx" placeholder="请输入培训类型" clearable class="q-control" />
|
||||
</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>
|
||||
@@ -189,27 +76,26 @@
|
||||
</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-column prop="kbh" label="课编号" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="kmc" label="课名称" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="jc" label="简称" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="jysdh" label="教研室代号" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="kclx" label="课程类型" width="150" align="center" />
|
||||
<el-table-column prop="pxlx" label="培训类型" width="150" align="center" />
|
||||
<el-table-column prop="pxcc" label="培训层次" width="200" align="center" />
|
||||
<el-table-column prop="xf" label="学分" align="center" />
|
||||
<el-table-column prop="xs" label="学时" width="160" align="center" />
|
||||
<el-table-column label="操作" width="150" 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" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
@@ -228,119 +114,178 @@
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="1100px"
|
||||
width="1000px"
|
||||
: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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课编号" prop="kbh">
|
||||
<el-input v-model="addForm.kbh" :disabled="isEdit" 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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课名称" prop="kmc">
|
||||
<el-input v-model="addForm.kmc" 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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="简称" prop="jc">
|
||||
<el-input v-model="addForm.jc" 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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="教研室代号" prop="jysdh">
|
||||
<el-input v-model="addForm.jysdh" 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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="学分" prop="xf">
|
||||
<el-input-number v-model="addForm.xf" :min="0" :precision="1" 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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="学时" prop="xs">
|
||||
<el-input-number v-model="addForm.xs" :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="录入时间">
|
||||
<el-input v-model="addForm.zxsj" placeholder="请输入录入时间" clearable />
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="培训层次" prop="pxcc">
|
||||
<el-input v-model="addForm.pxcc" 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-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="培训类型" prop="pxlx">
|
||||
<el-input v-model="addForm.pxlx" placeholder="请输入培训类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程类型" prop="kclx">
|
||||
<el-input v-model="addForm.kclx" placeholder="请输入课程类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="考试课时" prop="ksks">
|
||||
<el-input-number v-model="addForm.ksks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="成绩分制" prop="cjfz">
|
||||
<el-input v-model="addForm.cjfz" placeholder="请输入成绩分制" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="不计入学员平均分" prop="bjrxypjf">
|
||||
<el-select v-model="addForm.bjrxypjf" class="w-full">
|
||||
<el-option label="否" :value="0" />
|
||||
<el-option label="是" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="理论学时" prop="llxs">
|
||||
<el-input-number v-model="addForm.llxs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="实践学时" prop="sjxs">
|
||||
<el-input-number v-model="addForm.sjxs" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="周课时" prop="zks">
|
||||
<el-input-number v-model="addForm.zks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课类型" prop="klx">
|
||||
<el-input v-model="addForm.klx" placeholder="请输入课类型" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="考试课时不显示" prop="ksksbxs">
|
||||
<el-select v-model="addForm.ksksbxs" class="w-full">
|
||||
<el-option label="否" :value="0" />
|
||||
<el-option label="是" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程统一编号" prop="kctybh">
|
||||
<el-input v-model="addForm.kctybh" placeholder="请输入课程统一编号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="辅导答疑课时" prop="fddyks">
|
||||
<el-input-number v-model="addForm.fddyks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="自修课时" prop="zxks">
|
||||
<el-input-number v-model="addForm.zxks" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="修订日期" prop="xdrq">
|
||||
<el-input v-model="addForm.xdrq" placeholder="如 2026-08-24" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="节次优选级" prop="jcyxj">
|
||||
<el-input v-model="addForm.jcyxj" placeholder="请输入节次优选级" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程支持方式" prop="kczcfs">
|
||||
<el-input v-model="addForm.kczcfs" placeholder="请输入课程支持方式" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="课程建设方式" prop="kcjsfs">
|
||||
<el-input v-model="addForm.kcjsfs" placeholder="请输入课程建设方式" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="政治类课程" prop="zzlkc">
|
||||
<el-select v-model="addForm.zzlkc" class="w-full">
|
||||
<el-option label="否" :value="0" />
|
||||
<el-option label="是" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="考核方式" prop="khfs">
|
||||
<el-input v-model="addForm.khfs" placeholder="请输入考核方式" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="形成性成绩分值" prop="xcxcjfz">
|
||||
<el-input-number v-model="addForm.xcxcjfz" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="终结性成绩分值" prop="zjxcjfz">
|
||||
<el-input-number v-model="addForm.zjxcjfz" :min="0" controls-position="right" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="密级" prop="mj">
|
||||
<el-input v-model="addForm.mj" placeholder="请输入密级" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="评选情况" prop="pxqk">
|
||||
<el-input v-model="addForm.pxqk" placeholder="请输入评选情况" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="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">
|
||||
@@ -349,34 +294,12 @@
|
||||
</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>
|
||||
import { listSubject, addSubject, updateSubject, deleteSubject, getSubject } from '@/api/teachOffice/subject'
|
||||
|
||||
export default {
|
||||
name: 'SubjectIndex',
|
||||
data() {
|
||||
@@ -384,68 +307,18 @@ export default {
|
||||
// ==================== 1. 顶部状态提示 ====================
|
||||
statusTip: '请输入查询条件',
|
||||
|
||||
// ==================== 下拉选项 ====================
|
||||
zcfsOptions: ['其他', '讲授', '研讨', '实操'],
|
||||
khlxOptions: ['讲座', '考试', '考查', '实操'],
|
||||
mmdjOptions: ['公开', '内部', '秘密', '机密'],
|
||||
jysOptions: ['未确定教研室', '军事基础教研室', '政治工作教研室', '装备保障教研室'],
|
||||
pxccOptions: ['无', '本科', '硕士', '博士'],
|
||||
pxlxOptions: ['军官基础教育', '士兵职业教育', '研究生教育', '其他'],
|
||||
kclxOptions: ['其他类', '公共基础', '专业基础', '专业核心'],
|
||||
jsfsOptions: ['其他', '自建', '共建', '引进'],
|
||||
pjqkOptions: ['无', '国家级', '军队级', '院校级'],
|
||||
gljgOptions: ['教务处', '教研室1', '教研室2'],
|
||||
|
||||
// ==================== 2. 查询条件 ====================
|
||||
searchForm: {
|
||||
kcbh: '',
|
||||
kmc: '',
|
||||
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: '完全包含'
|
||||
kmdm: '',
|
||||
jysdh: '',
|
||||
kclx: '',
|
||||
pxlx: '',
|
||||
pxcc: ''
|
||||
},
|
||||
|
||||
// ==================== 列表数据 ====================
|
||||
/** 模拟列表数据(后端接口未提供) */
|
||||
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,
|
||||
@@ -460,22 +333,34 @@ export default {
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
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: '' }
|
||||
kmc: [{ required: true, message: '请输入课名称', trigger: 'blur' }],
|
||||
jysdh: [{ required: true, message: '请输入教研室代号', trigger: 'blur' }],
|
||||
xf: [{ required: true, message: '请输入学分', trigger: 'blur' }],
|
||||
pxcc: [{ required: true, message: '请输入培训层次', trigger: 'blur' }],
|
||||
pxlx: [{ required: true, message: '请输入培训类型', trigger: 'blur' }],
|
||||
kclx: [{ required: true, message: '请输入课程类型', trigger: 'blur' }],
|
||||
ksks: [{ required: true, message: '请输入考试课时', trigger: 'blur' }],
|
||||
cjfz: [{ required: true, message: '请输入成绩分制', trigger: 'blur' }],
|
||||
llxs: [{ required: true, message: '请输入理论学时', trigger: 'blur' }],
|
||||
sjxs: [{ required: true, message: '请输入实践学时', trigger: 'blur' }],
|
||||
zks: [{ required: true, message: '请输入周课时', trigger: 'blur' }],
|
||||
klx: [{ required: true, message: '请输入课类型', trigger: 'blur' }],
|
||||
kctybh: [{ required: true, message: '请输入课程统一编号', trigger: 'blur' }],
|
||||
fddyks: [{ required: true, message: '请输入辅导答疑课时', trigger: 'blur' }],
|
||||
zxks: [{ required: true, message: '请输入自修课时', trigger: 'blur' }],
|
||||
xdrq: [{ required: true, message: '请输入修订日期', trigger: 'blur' }],
|
||||
jcyxj: [{ required: true, message: '请输入节次优选级', trigger: 'blur' }],
|
||||
kczcfs: [{ required: true, message: '请输入课程支持方式', trigger: 'blur' }],
|
||||
kcjsfs: [{ required: true, message: '请输入课程建设方式', trigger: 'blur' }],
|
||||
khfs: [{ required: true, message: '请输入考核方式', trigger: 'blur' }],
|
||||
xcxcjfz: [{ required: true, message: '请输入形成性成绩分值', trigger: 'blur' }],
|
||||
zjxcjfz: [{ required: true, message: '请输入终结性成绩分值', trigger: 'blur' }],
|
||||
mj: [{ required: true, message: '请输入密级', trigger: 'blur' }],
|
||||
pxqk: [{ required: true, message: '请输入评选情况', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -486,54 +371,69 @@ export default {
|
||||
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, '-')
|
||||
/** 移除空值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
return payload
|
||||
},
|
||||
|
||||
/** 创建空白课程表单(含一条空课堂记录) */
|
||||
/** 创建空白课程科目表单 */
|
||||
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()]
|
||||
kbh: '', kmc: '', jysdh: '', bz: '', xh: '', xf: 0, jc: '', xs: 0,
|
||||
pxcc: '', pxlx: '', kclx: '', ksks: 0, py: '', gfmc: '', cjfz: '',
|
||||
bjrxypjf: 0, jxglbmbh: '', llxs: 0, sjxs: 0, kmdm: '', zks: 0, klx: '',
|
||||
ksksbxs: 0, kctybh: '', sydx: '', fddyks: 0, zxks: 0, bb: '', xdrq: '',
|
||||
jcyxj: '', kczcfs: '', kcjsfs: '', jsonzd: '', zzlkc: 0, khfs: '',
|
||||
xcxcjfz: 0, zjxcjfz: 0, mj: '', pxqk: ''
|
||||
}
|
||||
},
|
||||
|
||||
/** 默认课堂项 */
|
||||
defaultClassroom() {
|
||||
return { bh: '', ktjc: 1, jxnr: '', jxyd: '', jxff: '', zjjys: 0, fjjys: 0, bz: '', jxmd: '', jxyq: '' }
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.addForm = this.createEmptyForm()
|
||||
},
|
||||
|
||||
// ==================== 列表加载 ====================
|
||||
// TODO: 后端接口未提供,暂用模拟数据;接口就绪后替换为 getCourseTeachingList
|
||||
buildQuery() {
|
||||
return this.cleanPayload({
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize,
|
||||
kmc: this.searchForm.kmc,
|
||||
jc: this.searchForm.jc,
|
||||
kmdm: this.searchForm.kmdm,
|
||||
jysdh: this.searchForm.jysdh,
|
||||
kclx: this.searchForm.kclx,
|
||||
pxlx: this.searchForm.pxlx,
|
||||
pxcc: this.searchForm.pxcc
|
||||
})
|
||||
},
|
||||
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
setTimeout(() => {
|
||||
this.tableData = [...this.mockTableData]
|
||||
this.total = this.mockTableData.length
|
||||
this.loading = false
|
||||
}, 200)
|
||||
listSubject(this.buildQuery())
|
||||
.then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.statusTip = `共检索到 ${this.total} 条记录`
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 查询 ====================
|
||||
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()
|
||||
},
|
||||
@@ -557,36 +457,54 @@ export default {
|
||||
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} 条记录(前端模拟)`)
|
||||
const kbhList = this.selectedRows.map(r => r.kbh)
|
||||
this.$confirm(`确定删除所选 ${kbhList.length} 条课程科目吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const tasks = kbhList.map(kbh => deleteSubject(kbh))
|
||||
Promise.all(tasks)
|
||||
.then(() => {
|
||||
this.$message.success(`已删除 ${kbhList.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('删除失败')
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 下载 ====================
|
||||
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)
|
||||
/** 单条删除 */
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定删除课程科目「${row.kmc || row.kbh}」吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return deleteSubject(row.kbh)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch((err) => {
|
||||
if (err && err !== 'cancel') {
|
||||
this.$message.error('删除失败')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// ==================== 下载(后端暂未提供) ====================
|
||||
handleDownloadCourse() {
|
||||
this.downloadBlob('编码,课程名称,分类,考核类型方式,课内学时,课外学时\n', '课程科目基本信息.txt')
|
||||
this.$message.success('课程科目基本信息已下载(前端模拟)')
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
handleDownloadTextbook() {
|
||||
this.downloadBlob('课程名称,教材,在职主讲教员\n', '课程教材基本信息.txt')
|
||||
this.$message.success('课程教材基本信息已下载(前端模拟)')
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
handleDownloadTemplate() {
|
||||
this.downloadBlob('编码,课程名称,分类,考核类型方式,课内学时,课外学时,教材,开设课程专业名称,在职主讲教员\n', '课程科目数据文件模板.txt')
|
||||
this.$message.success('【课程科目数据文件模板】已下载(前端模拟)')
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
// ==================== 文件上传 ====================
|
||||
// ==================== 文件上传(后端暂未提供) ====================
|
||||
handleSelectFile() {
|
||||
this.$refs.fileInputRef && this.$refs.fileInputRef.click()
|
||||
},
|
||||
@@ -597,11 +515,7 @@ export default {
|
||||
},
|
||||
|
||||
handleUpload() {
|
||||
if (!this.selectedFile) {
|
||||
this.$message.warning('请先选择文件')
|
||||
return
|
||||
}
|
||||
this.$message.success(`文件「${this.selectedFile.name}」上传成功(前端模拟)`)
|
||||
this.$message.warning('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
@@ -611,49 +525,40 @@ export default {
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleAddClassroom() {
|
||||
this.addForm.ktList.push(this.defaultClassroom())
|
||||
},
|
||||
handleDeleteClassroom(index) {
|
||||
this.addForm.ktList.splice(index, 1)
|
||||
handleEdit(row) {
|
||||
this.addLoading = true
|
||||
getKb(row.kbh)
|
||||
.then(res => {
|
||||
const data = (res && res.data) || row
|
||||
this.isEdit = true
|
||||
this.addForm = Object.assign(this.createEmptyForm(), data)
|
||||
this.dialogVisible = true
|
||||
})
|
||||
.finally(() => {
|
||||
this.addLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
// 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)
|
||||
const payload = this.cleanPayload({ ...this.addForm })
|
||||
const requestFn = this.isEdit ? updateSubject : addSubject
|
||||
requestFn(payload)
|
||||
.then(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '保存成功')
|
||||
this.dialogVisible = false
|
||||
this.fetchList()
|
||||
})
|
||||
.finally(() => {
|
||||
this.addLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -708,22 +613,6 @@ export default {
|
||||
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 {
|
||||
@@ -811,6 +700,10 @@ export default {
|
||||
::v-deep(.el-table .cell) {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 新增/编辑弹窗 ====================
|
||||
@@ -825,29 +718,6 @@ export default {
|
||||
.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 {
|
||||
|
||||
@@ -1,376 +1,440 @@
|
||||
<template>
|
||||
<div class="app-container task-plan-page">
|
||||
<!-- ==================== 1. 学期信息区域 ==================== -->
|
||||
<!-- ==================== 页面标题 ==================== -->
|
||||
<div class="page-title">教学任务计划管理</div>
|
||||
|
||||
<!-- ==================== 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 :inline="true" :model="searchForm" class="search-form">
|
||||
<el-form-item label="任务名称">
|
||||
<el-input
|
||||
v-model="searchForm.rwmc"
|
||||
placeholder="请输入任务名称"
|
||||
clearable
|
||||
style="width: 180px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</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 label="年度">
|
||||
<el-select v-model="searchForm.nd" placeholder="请选择年度" clearable style="width: 140px">
|
||||
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学期周数">
|
||||
<el-input v-model="semester.weeks" style="width: 90px" />
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="searchForm.zt" placeholder="请选择状态" clearable style="width: 140px">
|
||||
<el-option
|
||||
v-for="opt in statusOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 2. 数据表格区域 ==================== -->
|
||||
<div class="list-title">教学任务列表:</div>
|
||||
<!-- ==================== 2. 操作区域 ==================== -->
|
||||
<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>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新建教学任务</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 3. 数据表格 ==================== -->
|
||||
<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">
|
||||
<el-table v-loading="loading" :data="tableData" border stripe class="task-table">
|
||||
<template slot="empty">
|
||||
<span>无数据!</span>
|
||||
</template>
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column prop="rwmc" label="任务名称" min-width="180" align="left" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nd" label="年度" width="90" align="center" />
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<span class="status-text">{{ row.zt }}</span>
|
||||
<el-tag :type="row.zt === '发布' ? 'success' : 'info'" size="small">
|
||||
{{ row.zt || '-' }}
|
||||
</el-tag>
|
||||
</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">
|
||||
<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="200" align="center" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
{{ row.jssj || '' }}
|
||||
<el-button type="text" size="small" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
:disabled="row.zt === '发布'"
|
||||
@click="handlePublish(row)"
|
||||
>发布</el-button>
|
||||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||||
</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-pagination
|
||||
:current-page="pageNum"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
class="pagination"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- ==================== 教学任务信息弹窗 ==================== -->
|
||||
<!-- ==================== 4. 新增/修改对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
title="教学任务信息"
|
||||
width="900px"
|
||||
class="teaching-task-dialog"
|
||||
:title="dialogTitle"
|
||||
width="560px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => (dialogVisible = val)"
|
||||
@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 ref="formRef" :model="form" :rules="rules" label-width="140px" class="add-form">
|
||||
<el-form-item v-if="isEdit" label="编号" prop="bh">
|
||||
<el-input v-model="form.bh" disabled placeholder="编号不可修改" />
|
||||
</el-form-item>
|
||||
<el-form-item v-else label="编号">
|
||||
<el-input disabled placeholder="新增后由系统自动生成" />
|
||||
</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-select v-model="form.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="zt">
|
||||
<el-select v-model="form.zt" placeholder="请选择状态" 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-form-item label="发布时间">
|
||||
<el-date-picker
|
||||
v-model="form.fbsj"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="请选择发布时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间">
|
||||
<el-date-picker
|
||||
v-model="form.jssj"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="请选择结束时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="教材需求生成时间">
|
||||
<el-date-picker
|
||||
v-model="form.jcxqscsj"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-ddTHH:mm:ss"
|
||||
placeholder="请选择教材需求生成时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</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>
|
||||
<el-button type="primary" :loading="saving" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- ==================== 5. 详情对话框 ==================== -->
|
||||
<el-dialog
|
||||
:visible="detailVisible"
|
||||
title="教学任务详情"
|
||||
width="620px"
|
||||
:close-on-click-modal="false"
|
||||
@update:visible="val => detailVisible = val"
|
||||
>
|
||||
<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 type="primary" @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 教学任务计划管理(完整管理页)
|
||||
* 对应菜单:teachOffice/taskPlan
|
||||
* 提供 teachingTask 全套真实接口操作:分页查询 list、详情 get?bh=、新增 add、编辑 update、
|
||||
* 发布 batchPublish?bh=(需先填写教研室任务书)、删除 delete?bh=(级联删除教研室任务书)
|
||||
* 只读查询视图在 src/views/teachBusiness/teachingTask/index.vue(教学任务列表)提供,避免重复操作同一实体
|
||||
*/
|
||||
import {
|
||||
listTeachingTask,
|
||||
getTeachingTask,
|
||||
addTeachingTask,
|
||||
updateTeachingTask,
|
||||
deleteTeachingTask,
|
||||
publishTeachingTask
|
||||
} from '@/api/teachBusiness/teachingTask'
|
||||
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||
|
||||
export default {
|
||||
name: 'TaskPlan',
|
||||
data() {
|
||||
return {
|
||||
// ==================== 1. 学期信息区域 ====================
|
||||
semester: {
|
||||
name: '2017年秋季学期', // 学期名称
|
||||
kxrq: '2017-07-08', // 校历开学日期
|
||||
jsrq: '2018-02-11', // 结束日期
|
||||
weeks: 32 // 学期周数
|
||||
// ==================== 1. 查询条件 ====================
|
||||
searchForm: {
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: ''
|
||||
},
|
||||
|
||||
// ==================== 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
|
||||
}
|
||||
yearOptions: [],
|
||||
statusOptions: [
|
||||
{ label: '未发布', value: '未发布' },
|
||||
{ label: '发布', value: '发布' }
|
||||
],
|
||||
selectedRows: [],
|
||||
currentRow: null,
|
||||
|
||||
// ==================== 操作按钮 ====================
|
||||
/** 教学任务信息弹窗 */
|
||||
// ==================== 2. 表格数据 ====================
|
||||
loading: false,
|
||||
tableData: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
|
||||
// ==================== 3. 新增/修改表单 ====================
|
||||
dialogVisible: false,
|
||||
/** 弹窗模式:新建 / 编辑 */
|
||||
dialogMode: 'create',
|
||||
/** 编辑模式选中的任务行 */
|
||||
editRow: null,
|
||||
|
||||
// ==================== 弹窗:基本信息 ====================
|
||||
form: {
|
||||
xq: '2017年秋季学期', // 学期(只读)
|
||||
rwmc: '', // 任务名称(可编辑)
|
||||
cjsj: '', // 创建时间(只读)
|
||||
fbsj: '', // 发布时间(只读)
|
||||
jssj: '' // 结束时间(只读)
|
||||
dialogTitle: '新建教学任务',
|
||||
isEdit: false,
|
||||
saving: false,
|
||||
form: this.createEmptyForm(),
|
||||
rules: {
|
||||
rwmc: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
||||
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||
zt: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
||||
},
|
||||
|
||||
// ==================== 弹窗: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 }
|
||||
]
|
||||
// ==================== 4. 详情 ====================
|
||||
detailVisible: false,
|
||||
detailLoading: false,
|
||||
detailData: {}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// 默认选中第一行(高亮)
|
||||
this.$nextTick(() => {
|
||||
if (this.tableData.length) {
|
||||
this.$refs.tableRef.setCurrentRow(this.tableData[0])
|
||||
}
|
||||
})
|
||||
created() {
|
||||
this.loadYearOptions().then(() => this.fetchList())
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 年度下拉(数据来自 /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 []
|
||||
})
|
||||
},
|
||||
|
||||
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])
|
||||
/* ---------- 通用格式化 ---------- */
|
||||
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)
|
||||
},
|
||||
/** 移除空值(''/null/undefined),保留 0 等有效值 */
|
||||
cleanPayload(obj) {
|
||||
const payload = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
payload[key] = value
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
return payload
|
||||
},
|
||||
|
||||
methods: {
|
||||
// ==================== 表格 ====================
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedRows = rows
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
this.currentRow = row
|
||||
},
|
||||
/** 获取当前选中行,未选中时提示 */
|
||||
getSelected() {
|
||||
if (!this.currentRow) {
|
||||
this.$message.warning('请先选择一条教学任务')
|
||||
return null
|
||||
/* ---------- 列表加载 ---------- */
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
const params = { pageNum: this.pageNum, pageSize: this.pageSize }
|
||||
if (this.searchForm.rwmc && this.searchForm.rwmc.trim()) params.rwmc = this.searchForm.rwmc.trim()
|
||||
if (this.searchForm.nd !== undefined && this.searchForm.nd !== null && this.searchForm.nd !== '') {
|
||||
params.nd = this.searchForm.nd
|
||||
}
|
||||
if (this.searchForm.zt && this.searchForm.zt.trim()) params.zt = this.searchForm.zt.trim()
|
||||
listTeachingTask(params).then(res => {
|
||||
const data = (res && res.data) || {}
|
||||
this.tableData = data.records || []
|
||||
this.total = data.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.tableData = []
|
||||
this.total = 0
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handlePageChange(page) {
|
||||
this.pageNum = page
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size
|
||||
this.pageNum = 1
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
/* ---------- 新增 / 修改 ---------- */
|
||||
createEmptyForm() {
|
||||
return {
|
||||
bh: '',
|
||||
rwmc: '',
|
||||
nd: undefined,
|
||||
zt: '未发布',
|
||||
fbsj: '',
|
||||
jssj: '',
|
||||
jcxqscsj: ''
|
||||
}
|
||||
return this.currentRow
|
||||
},
|
||||
|
||||
// ==================== 操作按钮 ====================
|
||||
/** 新建教学任务 */
|
||||
handleAdd() {
|
||||
this.dialogMode = 'create'
|
||||
this.editRow = null
|
||||
this.form = this.createEmptyForm()
|
||||
if (!this.form.nd && this.searchForm.nd) this.form.nd = this.searchForm.nd
|
||||
this.isEdit = false
|
||||
this.dialogTitle = '新建教学任务'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
/** 编辑教学任务 */
|
||||
handleEdit() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
this.dialogMode = 'edit'
|
||||
this.editRow = row
|
||||
|
||||
handleEdit(row) {
|
||||
this.form = {
|
||||
bh: row.bh || '',
|
||||
rwmc: row.rwmc || '',
|
||||
nd: row.nd,
|
||||
zt: row.zt || '未发布',
|
||||
fbsj: row.fbsj || '',
|
||||
jssj: row.jssj || '',
|
||||
jcxqscsj: row.jcxqscsj || ''
|
||||
}
|
||||
this.isEdit = true
|
||||
this.dialogTitle = '修改教学任务'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||
})
|
||||
},
|
||||
/** 弹窗确认保存 */
|
||||
handleDialogConfirm() {
|
||||
// TODO: 调用保存接口
|
||||
this.$message.success('已保存教学任务信息(前端演示)')
|
||||
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(valid => {
|
||||
if (!valid) {
|
||||
this.$message.warning('请完善必填项后再提交')
|
||||
return
|
||||
}
|
||||
const payload = this.cleanPayload(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
|
||||
})
|
||||
})
|
||||
},
|
||||
/** 删除教学任务 */
|
||||
handleDelete() {
|
||||
const row = this.getSelected()
|
||||
if (!row) return
|
||||
this.$confirm(`确定删除教学任务"${row.rwmc}"吗?删除后不可恢复。`, '删除确认', {
|
||||
confirmButtonText: '确定删除',
|
||||
|
||||
/** 构建请求体:年度转数字以匹配后端 Integer,时间字段有值才传 */
|
||||
buildPayload() {
|
||||
const f = this.form
|
||||
const payload = {}
|
||||
if (this.isEdit && 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 = Number(f.nd)
|
||||
if (f.zt && String(f.zt).trim()) payload.zt = String(f.zt).trim()
|
||||
if (f.fbsj) payload.fbsj = f.fbsj
|
||||
if (f.jssj) payload.jssj = f.jssj
|
||||
if (f.jcxqscsj) payload.jcxqscsj = f.jcxqscsj
|
||||
return payload
|
||||
},
|
||||
|
||||
/* ---------- 详情 ---------- */
|
||||
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
|
||||
})
|
||||
},
|
||||
|
||||
/* ---------- 删除 ---------- */
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除「${row.rwmc || row.bh || '该记录'}」吗?删除将级联删除关联的教研室任务书。`, '系统提示', {
|
||||
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}`)
|
||||
}).then(() => deleteTeachingTask(row.bh)).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ==================== 弹窗 ====================
|
||||
handleTaskBookSelection(rows) {
|
||||
this.selectedTaskBookRows = rows
|
||||
},
|
||||
/** 打开教研室任务书详细(前端演示) */
|
||||
handleTaskBookDetail() {
|
||||
// TODO: 教研室任务书详细弹窗,待接口接入
|
||||
},
|
||||
/** 弹窗确定 */
|
||||
handleConfirm() {
|
||||
this.handleDialogConfirm()
|
||||
this.dialogVisible = false
|
||||
/* ---------- 发布 ---------- */
|
||||
handlePublish(row) {
|
||||
this.$confirm(`确定要发布教学任务「${row.rwmc || row.bh || '该记录'}」吗?发布前请先填写关联的教研室任务书。`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => publishTeachingTask(row.bh)).then(() => {
|
||||
this.$message.success('发布成功')
|
||||
this.fetchList()
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -382,7 +446,15 @@ export default {
|
||||
}
|
||||
|
||||
.task-plan-page {
|
||||
// ========== 1. 学期信息区域 ==========
|
||||
.page-title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
// ========== 1. 查询条件区域 ==========
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
@@ -394,17 +466,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 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. 工具栏 ==========
|
||||
// ========== 2. 工具栏 ==========
|
||||
.list-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -422,66 +484,30 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 4. 数据表格区域 ==========
|
||||
// ========== 3. 数据表格区域 ==========
|
||||
.table-card {
|
||||
.task-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
color: var(--edu-green-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
// 当前行高亮
|
||||
::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;
|
||||
}
|
||||
.text-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 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;
|
||||
}
|
||||
}
|
||||
// ========== 4. 详情 ==========
|
||||
.detail-empty {
|
||||
min-height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
<div class="page-container">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<div class="search-tip">勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
<el-form :model="searchForm" label-width="110px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<div class="page-container">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<div class="search-tip">勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
<el-form :model="searchForm" label-width="110px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
@@ -221,9 +220,7 @@
|
||||
import { formatDate } from '@/utils/index'
|
||||
import {
|
||||
getTeachingLogList,
|
||||
deleteTeachingLog,
|
||||
batchReportTeachingLog,
|
||||
recheckTeachingLog,
|
||||
submitTeachingLog,
|
||||
exportTeachingLog,
|
||||
importTeachingLogExcel,
|
||||
downloadTeachingLogTemplate,
|
||||
@@ -380,43 +377,36 @@ export default {
|
||||
},
|
||||
|
||||
handleDeleteSelected() {
|
||||
const ids = this.getSelectedBhs()
|
||||
if (ids.length === 0) return
|
||||
this.$confirm(`确定要删除选中的 ${ids.length} 条记录吗?`, '删除确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => deleteTeachingLog(ids))
|
||||
.then(() => {
|
||||
this.$message.success(`已删除 ${ids.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
// 后端暂未提供删除接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleBatchReport() {
|
||||
const ids = this.getSelectedBhs()
|
||||
if (ids.length === 0) return
|
||||
this.$confirm(`确定要批量上报选中的 ${ids.length} 条记录吗?`, '上报确认', {
|
||||
this.$confirm(`确定要上报选中的 ${ids.length} 条记录吗?`, '上报确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => batchReportTeachingLog(ids))
|
||||
.then(() => {
|
||||
this.$message.success(`已批量上报 ${ids.length} 条记录`)
|
||||
// 提交教学日志审核,逐条上报至「已上报」状态
|
||||
let settled = Promise.resolve()
|
||||
ids.forEach((bh) => {
|
||||
settled = settled.then(() => submitTeachingLog(bh, '已上报'))
|
||||
})
|
||||
return settled
|
||||
})
|
||||
.then(() => {
|
||||
this.$message.success(`已上报 ${ids.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
handleRecheck() {
|
||||
recheckTeachingLog()
|
||||
.then(() => {
|
||||
this.$message.success('重新检查完成')
|
||||
})
|
||||
.catch(() => {})
|
||||
// 后端暂未提供重新检查接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
downloadBlob(blob, fileName) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<div class="page-container">
|
||||
<!-- 查询条件 -->
|
||||
<el-card shadow="never" class="search-card">
|
||||
<div class="search-tip">勾选"选择框"表示启用该项对应的查询条件。</div>
|
||||
<el-form :model="searchForm" label-width="110px" class="search-form">
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="12">
|
||||
@@ -208,10 +207,8 @@
|
||||
import { formatDate } from '@/utils/index'
|
||||
import {
|
||||
getReportedTeachingLogList,
|
||||
deleteTeachingLog,
|
||||
batchAuditTeachingLog,
|
||||
approveTeachingLog,
|
||||
rejectTeachingLog,
|
||||
recheckTeachingLog,
|
||||
exportTeachingLog,
|
||||
getTeachingLogByBh
|
||||
} from '@/api/log'
|
||||
@@ -375,19 +372,8 @@ export default {
|
||||
},
|
||||
|
||||
handleDelete() {
|
||||
const ids = this.getSelectedBhs()
|
||||
if (ids.length === 0) return
|
||||
this.$confirm(`确定要删除选中的 ${ids.length} 条记录吗?`, '删除确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => deleteTeachingLog(ids))
|
||||
.then(() => {
|
||||
this.$message.success(`已删除 ${ids.length} 条记录`)
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(() => {})
|
||||
// 后端暂未提供删除接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
handleAudit() {
|
||||
@@ -398,7 +384,14 @@ export default {
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => batchAuditTeachingLog(ids))
|
||||
.then(() => {
|
||||
// 审核通过教学日志,逐条审核
|
||||
let settled = Promise.resolve()
|
||||
ids.forEach((bh) => {
|
||||
settled = settled.then(() => approveTeachingLog(bh, ''))
|
||||
})
|
||||
return settled
|
||||
})
|
||||
.then(() => {
|
||||
this.$message.success(`已审核通过 ${ids.length} 条记录`)
|
||||
this.fetchList()
|
||||
@@ -432,11 +425,8 @@ export default {
|
||||
},
|
||||
|
||||
handleRecheck() {
|
||||
recheckTeachingLog()
|
||||
.then(() => {
|
||||
this.$message.success('重新检查变更情况完成')
|
||||
})
|
||||
.catch(() => {})
|
||||
// 后端暂未提供重新检查接口,仅作提示
|
||||
this.$message.info('后端暂未提供该接口')
|
||||
},
|
||||
|
||||
downloadBlob(blob, fileName) {
|
||||
|
||||
+1122
-369
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user