forked from liweijie/education
1、正课与学期关系关联;
2、天假删除保护; 3、教学任务计划增加了「结束发布」。已发布或库里的「已发布」都可以结束;结束后写入结束时间,任务书和班次课程任务只读 4、班次学期操作内容调整修改;
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
<div class="sce-panel">
|
||||
<div class="sce-panel-row">
|
||||
<span class="sce-label">事件名称:</span>
|
||||
<el-input v-model="toolbar.eventName" size="small" class="sce-event-input" placeholder="请输入校历事件名称" />
|
||||
<el-input v-model="toolbar.eventName" size="small" class="sce-event-input" :placeholder="mode === 'class' ? '请输入班历事件名称' : '请输入校历事件名称'" />
|
||||
<el-checkbox v-model="toolbar.bold" class="sce-cb">加粗显示</el-checkbox>
|
||||
<el-checkbox v-model="toolbar.schedulable" class="sce-cb">可排课</el-checkbox>
|
||||
<el-checkbox v-model="toolbar.mainCourse" class="sce-cb">正课</el-checkbox>
|
||||
@@ -92,6 +92,7 @@
|
||||
<script>
|
||||
import { getSemester } from '@/api/teachBusiness/semester'
|
||||
import { listXqxlb, addXqxlb, updateXqxlb } from '@/api/teachBusiness/xqxlb'
|
||||
import { listClassCalendarEvent, updateClassCalendarEvent } from '@/api/teachOffice/classCalendarEvent'
|
||||
|
||||
// 节次定义:12/34/56 常显,78/晚上/夜间由开关控制可见
|
||||
const SLOT_DEFS = [
|
||||
@@ -137,7 +138,12 @@ export default {
|
||||
name: 'SchoolCalendarEditor',
|
||||
props: {
|
||||
nd: { type: [String, Number], default: '' },
|
||||
semesterName: { type: String, default: '' }
|
||||
semesterName: { type: String, default: '' },
|
||||
mode: { type: String, default: 'school' },
|
||||
xydxqbh: { type: String, default: '' },
|
||||
xydbh: { type: String, default: '' },
|
||||
rangeStart: { type: String, default: '' },
|
||||
rangeEnd: { type: String, default: '' }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -202,7 +208,13 @@ export default {
|
||||
nd: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val) this.loadSemester()
|
||||
if (this.mode !== 'class' && val) this.loadSemester()
|
||||
}
|
||||
},
|
||||
xydxqbh: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (this.mode === 'class' && val) this.loadClassCalendar()
|
||||
}
|
||||
},
|
||||
visibleColumns(newCols, oldCols) {
|
||||
@@ -251,6 +263,28 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 数据加载 ---------- */
|
||||
loadClassCalendar() {
|
||||
const start = (this.rangeStart || '').slice(0, 10)
|
||||
const end = (this.rangeEnd || '').slice(0, 10)
|
||||
if (!start || !end) {
|
||||
this.$message.warning('班次学期缺少开学或结束日期')
|
||||
return
|
||||
}
|
||||
this.startDate = new Date(start.replace(/-/g, '/'))
|
||||
this.endDate = new Date(end.replace(/-/g, '/'))
|
||||
this.calendarStart = null
|
||||
this.buildWeeks()
|
||||
this.loadClassEvents()
|
||||
},
|
||||
loadClassEvents() {
|
||||
listClassCalendarEvent(this.xydxqbh).then(res => {
|
||||
const data = res.data
|
||||
const list = Array.isArray(data) ? data : (data && data.records) || []
|
||||
this.renderEventList(list)
|
||||
}).catch(() => {
|
||||
this.$message.warning('班历加载失败')
|
||||
})
|
||||
},
|
||||
loadSemester() {
|
||||
if (!this.nd) return
|
||||
getSemester(this.nd)
|
||||
@@ -281,57 +315,53 @@ export default {
|
||||
const data = res.data
|
||||
return Array.isArray(data) ? data : (data && data.records) || []
|
||||
})
|
||||
const render = (list) => {
|
||||
// 后端 add() 的按「月日」去重对已存的全量日期不生效,同一年度多次打开/刷新会
|
||||
// 积累同一格的重复占位记录(各带不同 bh)。updateById 只改其中一行,其余空记录
|
||||
// 会在重新拉取时把刚保存的事件名覆盖掉。故这里按「周-星期-节次」先去重:
|
||||
// 同一格保留有事件名(jqmc非空)的一条;都没有则保留最后一条兜底(保证有 bh)。
|
||||
const unique = {}
|
||||
list.forEach(item => {
|
||||
const pos = this.locateXqxlb(item)
|
||||
if (!pos) return
|
||||
const stable = this.cellStableKey(pos.wIdx, pos.dayIndex, pos.slotKey)
|
||||
const prev = unique[stable]
|
||||
if (!prev || (item.jqmc && !prev.item.jqmc)) {
|
||||
unique[stable] = { item: item, pos: pos }
|
||||
}
|
||||
})
|
||||
const loaded = {}
|
||||
Object.keys(unique).forEach(stable => {
|
||||
const { item, pos } = unique[stable]
|
||||
const ev = {
|
||||
bh: item.bh,
|
||||
name: item.jqmc || '',
|
||||
bold: !!item.jc,
|
||||
schedulable: !!item.kpk,
|
||||
mainCourse: !!item.zdpk,
|
||||
remarkShow: !!item.bzxs,
|
||||
remark: item.bz || ''
|
||||
}
|
||||
const colIndex = this.colIndexOf(pos.dayIndex, pos.slotKey)
|
||||
if (colIndex >= 0) {
|
||||
loaded[this.cellKey(pos.wIdx, colIndex)] = ev
|
||||
} else {
|
||||
// 该节次列当前隐藏:暂存(含 bh),待列显示时由 visibleColumns 监听恢复
|
||||
this.hiddenEvents[this.cellStableKey(pos.wIdx, pos.dayIndex, pos.slotKey)] = ev
|
||||
}
|
||||
})
|
||||
// 合并到现有格子(后端数据覆盖已有状态)
|
||||
this.events = Object.assign({}, this.events, loaded)
|
||||
}
|
||||
fetchList().then(list => {
|
||||
const hasCoverage = list.some(item => this.isInRange(item.jqsj))
|
||||
if (!hasCoverage && this.startDate && this.endDate) {
|
||||
// 本学期区间尚无占位记录:仅用本期 kxrq/jsrq 预生成整张网格
|
||||
const startStr = fmtDate(this.startDate)
|
||||
const endStr = fmtDate(this.endDate)
|
||||
return addXqxlb(startStr, endStr).then(() => fetchList())
|
||||
}
|
||||
return list
|
||||
}).then(render).catch(() => {
|
||||
}).then(list => {
|
||||
this.renderEventList(list)
|
||||
}).catch(() => {
|
||||
this.$message.warning('校历事件加载失败')
|
||||
})
|
||||
},
|
||||
renderEventList(list) {
|
||||
const unique = {}
|
||||
list.forEach(item => {
|
||||
const pos = this.locateXqxlb(item)
|
||||
if (!pos) return
|
||||
const stable = this.cellStableKey(pos.wIdx, pos.dayIndex, pos.slotKey)
|
||||
const prev = unique[stable]
|
||||
if (!prev || (item.jqmc && !prev.item.jqmc)) {
|
||||
unique[stable] = { item: item, pos: pos }
|
||||
}
|
||||
})
|
||||
const loaded = {}
|
||||
Object.keys(unique).forEach(stable => {
|
||||
const { item, pos } = unique[stable]
|
||||
const ev = {
|
||||
bh: item.bh,
|
||||
name: item.jqmc || '',
|
||||
bold: !!item.jc,
|
||||
schedulable: !!item.kpk,
|
||||
autoSchedule: !!item.zdpk,
|
||||
mainCourse: !!item.zk,
|
||||
remarkShow: !!item.bzxs,
|
||||
remark: item.bz || ''
|
||||
}
|
||||
const colIndex = this.colIndexOf(pos.dayIndex, pos.slotKey)
|
||||
if (colIndex >= 0) {
|
||||
loaded[this.cellKey(pos.wIdx, colIndex)] = ev
|
||||
} else {
|
||||
this.hiddenEvents[this.cellStableKey(pos.wIdx, pos.dayIndex, pos.slotKey)] = ev
|
||||
}
|
||||
})
|
||||
this.events = loaded
|
||||
},
|
||||
// 判断某条记录(jqsj 日期)是否落在本学期 [startDate, endDate] 区间内
|
||||
isInRange(jqsj) {
|
||||
if (!this.startDate || !this.endDate || !jqsj) return false
|
||||
@@ -537,6 +567,7 @@ export default {
|
||||
name: name,
|
||||
bold: this.toolbar.bold,
|
||||
schedulable: this.toolbar.schedulable,
|
||||
autoSchedule: !!(prev && prev.autoSchedule),
|
||||
mainCourse: this.toolbar.mainCourse,
|
||||
remarkShow: this.toolbar.remarkShow,
|
||||
remark: this.toolbar.remark
|
||||
@@ -601,9 +632,19 @@ export default {
|
||||
this.absorbPreview = ''
|
||||
this.events = {}
|
||||
this.hiddenEvents = {}
|
||||
this.loadXqxlbEvents()
|
||||
if (this.mode === 'class') this.loadClassEvents()
|
||||
else this.loadXqxlbEvents()
|
||||
this.$message.info('已刷新')
|
||||
},
|
||||
reloadEvents() {
|
||||
this.events = {}
|
||||
this.hiddenEvents = {}
|
||||
if (this.mode === 'class') this.loadClassEvents()
|
||||
else this.loadXqxlbEvents()
|
||||
},
|
||||
savePayload(payload) {
|
||||
return this.mode === 'class' ? updateClassCalendarEvent(payload) : updateXqxlb(payload)
|
||||
},
|
||||
/* ---------- 后端持久化(xqxlb 接口) ---------- */
|
||||
// 批量保存选中格事件,返回各格子保存成功/失败的个数
|
||||
persistEvents(keys) {
|
||||
@@ -612,11 +653,8 @@ export default {
|
||||
.map(key => {
|
||||
const payload = this.buildXqxlbPayload(key, this.events[key])
|
||||
if (!payload) return Promise.resolve(false)
|
||||
return updateXqxlb(payload)
|
||||
.then(() => {
|
||||
console.warn('[设定] key=', key, 'bh来源=', this.events[key] && this.events[key].bh ? '已有' : '生成', 'bh=', payload.bh, 'nd=', payload.nd, 'name=', payload.jqmc)
|
||||
return true
|
||||
})
|
||||
return this.savePayload(payload)
|
||||
.then(() => true)
|
||||
.catch(err => {
|
||||
console.warn('[设定] key=', key, '保存失败', err && (err.message || err))
|
||||
return false
|
||||
@@ -630,8 +668,7 @@ export default {
|
||||
} else if (ok > 0) {
|
||||
this.$message.success('已设定 ' + ok + ' 个时间格')
|
||||
}
|
||||
// 保存成功后重新拉取,回写各记录主键,避免重复新增
|
||||
this.loadXqxlbEvents()
|
||||
this.reloadEvents()
|
||||
return { ok: ok, fail: fail }
|
||||
})
|
||||
},
|
||||
@@ -643,7 +680,7 @@ export default {
|
||||
const payload = this.buildXqxlbPayload(key, this.events[key])
|
||||
if (!payload) return Promise.resolve(false)
|
||||
payload.jqmc = ''
|
||||
return updateXqxlb(payload)
|
||||
return this.savePayload(payload)
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
})
|
||||
@@ -655,8 +692,7 @@ export default {
|
||||
} else if (ok > 0) {
|
||||
this.$message.success('已删除 ' + ok + ' 个时间格事件')
|
||||
}
|
||||
// 删除成功后重新拉取,同步后端状态
|
||||
this.loadXqxlbEvents()
|
||||
this.reloadEvents()
|
||||
return { ok: ok, fail: fail }
|
||||
})
|
||||
},
|
||||
@@ -678,10 +714,18 @@ export default {
|
||||
bz: ev.remark || null,
|
||||
kpk: !!ev.schedulable,
|
||||
bzxs: !!ev.remarkShow,
|
||||
zdpk: !!ev.mainCourse,
|
||||
courseClass: SLOT_COURSE_MAP[pos.slotKey] || null
|
||||
zdpk: !!ev.autoSchedule,
|
||||
zk: !!ev.mainCourse,
|
||||
courseClass: SLOT_COURSE_MAP[pos.slotKey] || null,
|
||||
xydxqbh: this.mode === 'class' ? this.xydxqbh : undefined,
|
||||
xydbh: this.mode === 'class' ? this.xydbh : undefined
|
||||
}
|
||||
},
|
||||
selectedEventBhs() {
|
||||
return this.selectedKeys
|
||||
.map(key => this.events[key] && this.events[key].bh)
|
||||
.filter(Boolean)
|
||||
},
|
||||
// 时间格 key -> { wIdx, dayIndex, slotKey }
|
||||
parseCellKey(key) {
|
||||
const m = key.match(/^w(\d+)-c(\d+)$/)
|
||||
@@ -694,7 +738,9 @@ export default {
|
||||
/* ---------- 返回学期管理 ---------- */
|
||||
handleClose() {
|
||||
this.$emit('close')
|
||||
this.$router.replace({ path: '/teachBusiness/semester' })
|
||||
if (this.mode !== 'class') {
|
||||
this.$router.replace({ path: '/teachBusiness/semester' })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user