forked from liweijie/education
校历
This commit is contained in:
@@ -123,6 +123,16 @@ function fmtDate(d) {
|
||||
return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate())
|
||||
}
|
||||
|
||||
// 生成 32 位小写 UUID(去横线),与后端 UuidUtil.getUUID 一致,用于 bh 缺失时兜底
|
||||
function genUUID() {
|
||||
let s = ''
|
||||
const chars = '0123456789abcdef'
|
||||
for (let i = 0; i < 32; i++) {
|
||||
s += chars[Math.floor(Math.random() * 16)]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'SchoolCalendarEditor',
|
||||
props: {
|
||||
@@ -182,12 +192,10 @@ export default {
|
||||
})
|
||||
return cols
|
||||
},
|
||||
// xqxlb 的 nd 存的是「年份」,必须与某条记录的 jqsj 实际日期同一年,
|
||||
// 按「学期代号前4位」取会与格子真实年月脱节(如 2027 春学期首周落在 2026 年)。
|
||||
// 这里统一以「日历起点 calendarStart 所在年」作为年度口径。
|
||||
// xqxlb 的 nd 后端已统一为「6 位学期代号」(如 202701),与 this.nd 一致。
|
||||
// 不再按日历起点/季度取年份,避免跨年度学期解析出错。
|
||||
xqxlbNd() {
|
||||
if (this.calendarStart) return this.calendarStart.getFullYear()
|
||||
return Number(String(this.nd).slice(0, 4))
|
||||
return Number(String(this.nd).slice(0, 6)) || Number(this.nd) || 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -269,15 +277,10 @@ export default {
|
||||
// 调用 /xqxlb/add 只按本学期 kxrq/jsrq 预生成这一张网格,再重新拉取,
|
||||
// 这样后续 /xqxlb/update 的 updateById 才能命中每一格。(区间有覆盖则跳过,幂等)
|
||||
loadXqxlbEvents() {
|
||||
const fetchList = () => {
|
||||
console.warn('[校历编辑] 查询nd=', this.xqxlbNd, '学期nd=', this.nd)
|
||||
return listXqxlb({ nd: this.xqxlbNd }).then(res => {
|
||||
const fetchList = () => listXqxlb({ nd: this.xqxlbNd }).then(res => {
|
||||
const data = res.data
|
||||
const arr = Array.isArray(data) ? data : (data && data.records) || []
|
||||
console.warn('[校历编辑] 返回条数=', arr.length, '含事件名=', arr.filter(it => it.jqmc).map(it => ({ nd: it.nd, jqsj: it.jqsj, jqmc: it.jqmc, courseClass: it.courseClass })).slice(0, 10))
|
||||
return arr
|
||||
return Array.isArray(data) ? data : (data && data.records) || []
|
||||
})
|
||||
}
|
||||
const render = (list) => {
|
||||
// 后端 add() 的按「月日」去重对已存的全量日期不生效,同一年度多次打开/刷新会
|
||||
// 积累同一格的重复占位记录(各带不同 bh)。updateById 只改其中一行,其余空记录
|
||||
@@ -519,9 +522,9 @@ export default {
|
||||
return
|
||||
}
|
||||
const name = this.toolbar.eventName.trim()
|
||||
// 空名称时按清除处理
|
||||
// 设定时未填写事件名:提示,不触发清除
|
||||
if (!name) {
|
||||
this.deleteEvent()
|
||||
this.$message.warning('请输入事件名')
|
||||
return
|
||||
}
|
||||
const keys = [...this.selectedKeys]
|
||||
@@ -610,8 +613,14 @@ export default {
|
||||
const payload = this.buildXqxlbPayload(key, this.events[key])
|
||||
if (!payload) return Promise.resolve(false)
|
||||
return updateXqxlb(payload)
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
.then(() => {
|
||||
console.warn('[设定] key=', key, 'bh来源=', this.events[key] && this.events[key].bh ? '已有' : '生成', 'bh=', payload.bh, 'nd=', payload.nd, 'name=', payload.jqmc)
|
||||
return true
|
||||
})
|
||||
.catch(err => {
|
||||
console.warn('[设定] key=', key, '保存失败', err && (err.message || err))
|
||||
return false
|
||||
})
|
||||
})
|
||||
return Promise.all(tasks).then(results => {
|
||||
const ok = results.filter(r => r === true).length
|
||||
@@ -659,10 +668,10 @@ export default {
|
||||
d.setDate(this.calendarStart.getDate() + pos.wIdx * 7 + pos.dayIndex)
|
||||
return {
|
||||
delFlag: 0,
|
||||
bh: ev.bh || undefined,
|
||||
// nd 必须与 jqsj 同一年:取本条记录真实日期的年份,
|
||||
// 不能沿用学派代号前4位(如 2027 春学期首周可能落在 2026 年,会存错年度、查不到)。
|
||||
nd: d.getFullYear(),
|
||||
// bh 编号必须传:有后端记录则沿用其 bh,否则前端生成 UUID 兜底(避免 payload 缺主键导致 updateById 失效)
|
||||
bh: ev.bh || genUUID(),
|
||||
// nd 后端已统一为 6 位学期代号(如 202701),与查询口径一致,不再取记录日期的年份
|
||||
nd: this.xqxlbNd,
|
||||
jqsj: fmtDate(d),
|
||||
jqmc: ev.name || '',
|
||||
jc: !!ev.bold,
|
||||
|
||||
@@ -193,31 +193,14 @@ export default {
|
||||
})
|
||||
},
|
||||
// 从后端拉取校历事件,渲染到对应时间格
|
||||
// xqxlb.nd 存的是记录真实日期的年份,不是学期代号前4位(避免跨年度学期查询出错)
|
||||
// xqxlb.nd 后端已统一为 6 位学期代号(如 202701),与 this.nd 一致,一次查询即可
|
||||
loadXqxlbEvents() {
|
||||
if (!this.calendarStart) return
|
||||
// 学期校历从 calendarStart 到 endDate,查询覆盖整个跨度的全部年份
|
||||
const startYear = this.calendarStart.getFullYear()
|
||||
const endYear = (this.endDate || this.calendarStart).getFullYear()
|
||||
// 一次性拉取覆盖起止年份的所有记录,由前端过滤
|
||||
const requests = []
|
||||
const range = []
|
||||
for (let y = startYear; y <= endYear; y++) {
|
||||
range.push(y)
|
||||
requests.push(listXqxlb({ nd: y }))
|
||||
}
|
||||
console.warn('[校历只读] 查询nd范围=', range, 'calendarStart=', fmtDate(this.calendarStart), 'endDate=', this.endDate ? fmtDate(this.endDate) : null)
|
||||
Promise.all(requests).then(responses => {
|
||||
const list = []
|
||||
responses.forEach(res => {
|
||||
if (!this.calendarStart || !this.nd) return
|
||||
listXqxlb({ nd: Number(String(this.nd).slice(0, 6)) || Number(this.nd) }).then(res => {
|
||||
const data = res.data
|
||||
const part = Array.isArray(data) ? data : (data && data.records) || []
|
||||
list.push(...part)
|
||||
})
|
||||
console.warn('[校历只读] listXqxlb 返回记录条数=', list.length, 'nd字段分布=', list.reduce((m, it) => { const k = String(it.nd); m[k] = (m[k] || 0) + 1; return m }, {}), '样例=', list.slice(0, 3).map(it => ({ nd: it.nd, jqsj: it.jqsj, jqmc: it.jqmc, courseClass: it.courseClass })))
|
||||
const list = Array.isArray(data) ? data : (data && data.records) || []
|
||||
const loaded = {}
|
||||
let matched = 0
|
||||
// 23694 条里同一格可能有多条(add() 去重失效累积的重复占位)。
|
||||
// 同一格可能有多条(后端 add() 去重失效累积的重复占位)。
|
||||
// 按格子去重:同一格优先保留「有事件名(jqmc非空)」的那条,避免空占位把事件盖成空白。
|
||||
const unique = {}
|
||||
list.forEach(item => {
|
||||
@@ -239,11 +222,11 @@ export default {
|
||||
remarkShow: !!item.bzxs,
|
||||
remark: item.bz || ''
|
||||
}
|
||||
if (item.jqmc) matched++
|
||||
})
|
||||
console.warn('[校历只读] 定位到的事件条数=', matched, 'events=', Object.keys(loaded).length, loaded)
|
||||
this.events = loaded
|
||||
}).catch(e => { console.error('[校历只读] 拉取失败', e) })
|
||||
}).catch(() => {
|
||||
this.$message.warning('校历事件加载失败')
|
||||
})
|
||||
},
|
||||
// 根据假期记录反推时间格 key(jqsj 日期 + courseClass 节次)
|
||||
locateXqxlb(item) {
|
||||
|
||||
@@ -6,22 +6,16 @@
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新添</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.8">
|
||||
<el-button type="success" plain icon="el-icon-date" size="mini" :disabled="!currentSemester"
|
||||
<el-button type="success" plain icon="el-icon-date" size="mini"
|
||||
@click="handleEditCalendar">
|
||||
编辑校历
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">
|
||||
批量删除
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="semesterList" border :height="tableHeight" highlight-current-row
|
||||
@current-change="handleCurrentChange" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" align="center" width="50" />
|
||||
@current-change="handleCurrentChange">
|
||||
<el-table-column label="学期名称" align="center" width="250">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getSemesterName(scope.row.nd) }}</span>
|
||||
@@ -214,14 +208,8 @@ export default {
|
||||
total: 0,
|
||||
// 学期列表数据
|
||||
semesterList: [],
|
||||
// 选中的学期数组
|
||||
ids: [],
|
||||
// 当前点击选中的学期
|
||||
currentSemester: null,
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
@@ -365,12 +353,6 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 多选变化 */
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.nd)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 单击行选中变化:记录当前选中的学期,用于启用「编辑校历」 */
|
||||
handleCurrentChange(currentRow) {
|
||||
this.currentSemester = currentRow || null
|
||||
@@ -405,7 +387,7 @@ export default {
|
||||
},
|
||||
/** 编辑按钮 */
|
||||
handleUpdate(row) {
|
||||
const semesterId = row && row.nd ? row.nd : this.ids[0]
|
||||
const semesterId = row && row.nd ? row.nd : ''
|
||||
if (!semesterId) return
|
||||
this.reset()
|
||||
this.isAdd = false
|
||||
@@ -443,21 +425,21 @@ export default {
|
||||
/** 编辑校历按钮:对当前选中的学期编辑校历 */
|
||||
handleEditCalendar() {
|
||||
const row = this.currentSemester
|
||||
if (!row || !row.nd) return
|
||||
if (!row || !row.nd) {
|
||||
this.$modal.msgWarning('请选择学期')
|
||||
return
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/teachBusiness/semester/semesterCalendar',
|
||||
query: { nd: row.nd, name: this.getSemesterName(row.nd) }
|
||||
})
|
||||
},
|
||||
/** 删除按钮 */
|
||||
/** 删除按钮:单行删除 */
|
||||
handleDelete(row) {
|
||||
const semesterIds = row && row.nd ? [row.nd] : this.ids
|
||||
if (!semesterIds.length) return
|
||||
const names = semesterIds.map(nd => this.getSemesterName(nd)).join('、')
|
||||
this.$modal.confirm('确认删除学期【' + names + '】吗?').then(() => {
|
||||
// 批量删除:逐个调用
|
||||
const delList = semesterIds.map(nd => delSemester(nd))
|
||||
return Promise.all(delList)
|
||||
if (!row || !row.nd) return
|
||||
const name = this.getSemesterName(row.nd)
|
||||
this.$modal.confirm('确认删除学期【' + name + '】吗?').then(() => {
|
||||
return delSemester(row.nd)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess("删除成功")
|
||||
|
||||
Reference in New Issue
Block a user