forked from liweijie/education
1、校历的78、晚上、夜间等直接落库,
2、配当、任务书完善、排课窗完善; 3、任务书批量发布、删除等; 4、班历同步校历
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
<el-input v-model="toolbar.eventName" size="small" class="sce-event-input" :placeholder="mode === 'class' ? '请输入班历事件名称' : (mode === 'venue' ? '请输入场地事件名称' : '请输入校历事件名称')" />
|
||||
<el-checkbox v-if="mode !== 'venue'" v-model="toolbar.bold" class="sce-cb">加粗显示</el-checkbox>
|
||||
<el-checkbox v-model="toolbar.schedulable" class="sce-cb">可排课</el-checkbox>
|
||||
<el-checkbox v-if="mode !== 'venue'" v-model="toolbar.autoSchedule" class="sce-cb">自动排课</el-checkbox>
|
||||
<el-checkbox v-if="mode !== 'venue'" v-model="toolbar.mainCourse" class="sce-cb">正课</el-checkbox>
|
||||
<el-checkbox v-if="mode !== 'venue'" v-model="toolbar.remarkShow" class="sce-cb">备注显示</el-checkbox>
|
||||
<span class="sce-label">备注:</span>
|
||||
@@ -148,25 +149,47 @@ import {
|
||||
listVenueLessons,
|
||||
listVenueDesignatedTeams
|
||||
} from '@/api/teachBusiness/venueCalendar'
|
||||
import { getSystemSettings, updateSystemSettings, getPeriodSlots } from '@/api/teachBusiness/systemSettings'
|
||||
|
||||
// 节次定义:12/34/56 常显,78/晚上/夜间由开关控制可见
|
||||
const SLOT_DEFS = [
|
||||
{ key: '12', label: '1-2', ctrl: null },
|
||||
{ key: '34', label: '3-4', ctrl: null },
|
||||
{ key: '56', label: '5-6', ctrl: null },
|
||||
{ key: '78', label: '7-8', ctrl: 'show78' },
|
||||
{ key: 'night', label: '晚上', ctrl: 'showNight' },
|
||||
{ key: 'late', label: '夜间', ctrl: 'showLateNight' }
|
||||
// 节次定义回退值:节次时间表为空时使用,12/34/56 常显,78/晚上/夜间由开关控制可见
|
||||
const DEFAULT_SLOT_DEFS = [
|
||||
{ key: '12', label: '1-2', courseClass: '1-2', ctrl: null },
|
||||
{ key: '34', label: '3-4', courseClass: '3-4', ctrl: null },
|
||||
{ key: '56', label: '5-6', courseClass: '5-6', ctrl: null },
|
||||
{ key: '78', label: '7-8', courseClass: '7-8', ctrl: 'show78' },
|
||||
{ key: 'night', label: '晚上', courseClass: '9-10', ctrl: 'showNight' },
|
||||
{ key: 'late', label: '夜间', courseClass: '11-12', ctrl: 'showLateNight' }
|
||||
]
|
||||
|
||||
// 前端节次 key -> 后端 xqxlb.courseClass 节次范围(如 12 节 -> "1-2"、夜间 -> "11-12")
|
||||
const SLOT_COURSE_MAP = {
|
||||
'12': '1-2',
|
||||
'34': '3-4',
|
||||
'56': '5-6',
|
||||
'78': '7-8',
|
||||
night: '9-10',
|
||||
late: '11-12'
|
||||
const SLOT_COURSE_MAP = {}
|
||||
DEFAULT_SLOT_DEFS.forEach(s => { SLOT_COURSE_MAP[s.key] = s.courseClass })
|
||||
|
||||
// 节次范围解析:"1-2"/"7~8" -> [1,2];单数字 -> [n,n];非数字返回 null
|
||||
function parseSlotRange(label) {
|
||||
if (label == null) return null
|
||||
const s = String(label).trim()
|
||||
const m = s.match(/(\d+)\s*[-~—–]\s*(\d+)/)
|
||||
if (m) return [+m[1], +m[2]]
|
||||
if (/^\d+$/.test(s)) return [+s, +s]
|
||||
return null
|
||||
}
|
||||
|
||||
// 节次段受哪个显示开关控制:前 6 节常显,7-8 -> show78,9-10 -> showNight,11+ -> showLateNight;
|
||||
// 非数字标签按名称/时段推断(晚->晚上,夜->夜间)
|
||||
function ctrlOfSlot(label, sd) {
|
||||
const range = parseSlotRange(label)
|
||||
if (range) {
|
||||
const first = range[0]
|
||||
if (first <= 6) return null
|
||||
if (first <= 8) return 'show78'
|
||||
if (first <= 10) return 'showNight'
|
||||
return 'showLateNight'
|
||||
}
|
||||
const s = String(label || '') + String(sd || '')
|
||||
if (s.indexOf('夜') >= 0) return 'showLateNight'
|
||||
if (s.indexOf('晚') >= 0) return 'showNight'
|
||||
return null
|
||||
}
|
||||
|
||||
const WEEK_DAYS = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
@@ -215,15 +238,20 @@ export default {
|
||||
totalWeeks: 0,
|
||||
dateRangeText: '',
|
||||
weeks: [],
|
||||
// 显示开关(默认不勾选,每天仅显示 1-2/3-4/5-6 三个节次)
|
||||
// 显示开关(默认不勾选,挂载时从系统参数 DBVersion 恢复)
|
||||
show78: false,
|
||||
showNight: false,
|
||||
showLateNight: false,
|
||||
// 系统参数是否已加载(加载完成前的开关赋值不回写)
|
||||
settingsReady: false,
|
||||
// 节次列定义:由节次时间表驱动,空表时回退默认六段
|
||||
slotDefs: DEFAULT_SLOT_DEFS.slice(),
|
||||
// 工具栏表单
|
||||
toolbar: {
|
||||
eventName: '',
|
||||
bold: false,
|
||||
schedulable: false,
|
||||
autoSchedule: false,
|
||||
mainCourse: false,
|
||||
remarkShow: false,
|
||||
remark: ''
|
||||
@@ -250,7 +278,6 @@ export default {
|
||||
// 指定本场地为专用教室的班次(顶部横幅)
|
||||
designatedTeams: [],
|
||||
weekDayOptions: WEEK_DAYS,
|
||||
slotOptions: SLOT_DEFS,
|
||||
ruleDialog: {
|
||||
visible: false,
|
||||
submitting: false,
|
||||
@@ -262,12 +289,16 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 规律生成弹窗的节次选项(同节次时间表口径)
|
||||
slotOptions() {
|
||||
return this.slotDefs
|
||||
},
|
||||
// 当前可见列(由开关过滤,默认每天三个节次)
|
||||
visibleColumns() {
|
||||
const cols = []
|
||||
let colIndex = 0
|
||||
WEEK_DAYS.forEach((dayLabel, dayIndex) => {
|
||||
SLOT_DEFS.forEach(slot => {
|
||||
this.slotDefs.forEach(slot => {
|
||||
if (slot.ctrl && !this[slot.ctrl]) return
|
||||
cols.push({ colIndex: colIndex, dayIndex: dayIndex, slotKey: slot.key, slotLabel: slot.label, dayLabel: dayLabel })
|
||||
colIndex++
|
||||
@@ -312,6 +343,10 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 显示开关变更即写回系统参数(防抖合并连续变更)
|
||||
show78() { this.persistDisplaySettings() },
|
||||
showNight() { this.persistDisplaySettings() },
|
||||
showLateNight() { this.persistDisplaySettings() },
|
||||
nd: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
@@ -371,10 +406,72 @@ export default {
|
||||
this.selectedKeys = []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadDisplaySettings()
|
||||
this.loadPeriodSlots()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.removeGlobalListeners()
|
||||
if (this._settingsTimer) clearTimeout(this._settingsTimer)
|
||||
},
|
||||
methods: {
|
||||
/* ---------- 系统参数 / 节次字典 ---------- */
|
||||
// 显示开关从 DBVersion 恢复,刷新不丢配置
|
||||
loadDisplaySettings() {
|
||||
getSystemSettings().then(res => {
|
||||
const d = (res && res.data) || {}
|
||||
const pick = (a, b) => (d[a] !== undefined ? d[a] : d[b])
|
||||
this.show78 = !!pick('xs78J', 'xs78j')
|
||||
this.showNight = !!pick('xsws', 'xsws')
|
||||
this.showLateNight = !!pick('xsyj', 'xsyj')
|
||||
this.$nextTick(() => { this.settingsReady = true })
|
||||
}).catch(() => {
|
||||
this.settingsReady = true
|
||||
})
|
||||
},
|
||||
// 开关变更回写 DBVersion(只提交三个字段,后端只写非空字段不影响其它参数)
|
||||
persistDisplaySettings() {
|
||||
if (!this.settingsReady) return
|
||||
if (this._settingsTimer) clearTimeout(this._settingsTimer)
|
||||
this._settingsTimer = setTimeout(() => {
|
||||
updateSystemSettings({
|
||||
xs78J: this.show78,
|
||||
xsws: this.showNight,
|
||||
xsyj: this.showLateNight
|
||||
}).catch(() => {})
|
||||
}, 400)
|
||||
},
|
||||
// 节次列由节次时间表驱动;空表或拉取失败保留默认六段
|
||||
loadPeriodSlots() {
|
||||
getPeriodSlots().then(res => {
|
||||
const rows = (res && res.data) || []
|
||||
const defs = rows
|
||||
.filter(r => r && r.jcsy)
|
||||
.map(r => ({
|
||||
key: String(r.jcsy),
|
||||
label: String(r.jcsy),
|
||||
courseClass: String(r.jcsy),
|
||||
ctrl: ctrlOfSlot(r.jcsy, r.sd)
|
||||
}))
|
||||
if (defs.length) this.slotDefs = defs
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 节次格 key -> 后端 courseClass 值(动态节次表优先)
|
||||
courseClassOfSlot(slotKey) {
|
||||
const s = this.slotDefs.find(x => x.key === slotKey)
|
||||
return s ? s.courseClass : (SLOT_COURSE_MAP[slotKey] || null)
|
||||
},
|
||||
// 单节次 -> 节次格 key(动态范围优先,回退固定 1-12 映射)
|
||||
jcToSlotKey(jc) {
|
||||
const n = Number(jc)
|
||||
if (!n) return null
|
||||
for (const s of this.slotDefs) {
|
||||
const r = parseSlotRange(s.courseClass)
|
||||
if (r && n >= r[0] && n <= r[1]) return s.key
|
||||
}
|
||||
const fallback = JC_SLOT_MAP[n]
|
||||
return this.slotDefs.some(x => x.key === fallback) ? fallback : null
|
||||
},
|
||||
/* ---------- 数据加载 ---------- */
|
||||
loadClassCalendar() {
|
||||
const start = (this.rangeStart || '').slice(0, 10)
|
||||
@@ -504,7 +601,7 @@ export default {
|
||||
const lessons = {}
|
||||
lsList.forEach(item => {
|
||||
const dateStr = String(item.rq || '').slice(0, 10)
|
||||
const slotKey = JC_SLOT_MAP[item.jc]
|
||||
const slotKey = this.jcToSlotKey(item.jc)
|
||||
if (!dateStr || !slotKey) return
|
||||
const key = dateStr + '#' + slotKey
|
||||
if (!lessons[key]) lessons[key] = []
|
||||
@@ -519,7 +616,7 @@ export default {
|
||||
const merged = {}
|
||||
list.forEach(row => {
|
||||
const dateStr = String(row.rq || '').slice(0, 10)
|
||||
const slotKey = JC_SLOT_MAP[row.jc]
|
||||
const slotKey = this.jcToSlotKey(row.jc)
|
||||
if (!dateStr || !slotKey) return
|
||||
const pos = this.locateDateSlot(dateStr, slotKey)
|
||||
if (!pos) return
|
||||
@@ -610,9 +707,11 @@ export default {
|
||||
return { ok, skipped }
|
||||
},
|
||||
periodsOfSlot(slotKey) {
|
||||
const seg = SLOT_COURSE_MAP[slotKey]
|
||||
if (!seg) return []
|
||||
return seg.split('-').map(Number).filter(n => !isNaN(n))
|
||||
const range = parseSlotRange(this.courseClassOfSlot(slotKey))
|
||||
if (!range) return []
|
||||
const list = []
|
||||
for (let n = range[0]; n <= range[1]; n++) list.push(n)
|
||||
return list
|
||||
},
|
||||
/* ---------- 规律生成 ---------- */
|
||||
openRuleDialog() {
|
||||
@@ -676,17 +775,18 @@ export default {
|
||||
if (slotKey === null) return null
|
||||
return { wIdx, dayIndex, slotKey }
|
||||
},
|
||||
// 后端 courseClass 节次范围 -> 前端节次 key
|
||||
// 后端 courseClass 节次范围 -> 前端节次 key(动态节次表 + 紧凑写法兼容)
|
||||
courseClassToSlotKey(courseClass) {
|
||||
if (!courseClass) return null
|
||||
const s = String(courseClass).trim()
|
||||
for (const key in SLOT_COURSE_MAP) {
|
||||
if (s === SLOT_COURSE_MAP[key]) return key
|
||||
const direct = this.slotDefs.find(x => x.courseClass === s)
|
||||
if (direct) return direct.key
|
||||
// 兼容 "910"/"1112"/"12" 等紧凑写法:按单节次归并到所属段
|
||||
if (/^\d+$/.test(s) && s.length > 1) {
|
||||
const first = this.jcToSlotKey(Number(s.slice(0, s.length - 1)))
|
||||
if (first) return first
|
||||
}
|
||||
// 兼容 "910"/"1112" 等紧凑写法
|
||||
if (s === '910') return 'night'
|
||||
if (s === '1112') return 'late'
|
||||
return null
|
||||
return this.jcToSlotKey(s)
|
||||
},
|
||||
// 获取日期所在周的周一(周一为一周起点)
|
||||
getMonday(d) {
|
||||
@@ -914,7 +1014,7 @@ export default {
|
||||
name: name,
|
||||
bold: this.toolbar.bold,
|
||||
schedulable: this.toolbar.schedulable,
|
||||
autoSchedule: !!(prev && prev.autoSchedule),
|
||||
autoSchedule: !!this.toolbar.autoSchedule,
|
||||
mainCourse: this.toolbar.mainCourse,
|
||||
remarkShow: this.toolbar.remarkShow,
|
||||
remark: this.toolbar.remark
|
||||
@@ -975,6 +1075,7 @@ export default {
|
||||
this.toolbar.eventName = target.name
|
||||
this.toolbar.bold = !!target.bold
|
||||
this.toolbar.schedulable = !!target.schedulable
|
||||
this.toolbar.autoSchedule = !!target.autoSchedule
|
||||
this.toolbar.mainCourse = !!target.mainCourse
|
||||
this.toolbar.remarkShow = !!target.remarkShow
|
||||
this.toolbar.remark = target.remark || ''
|
||||
@@ -997,6 +1098,7 @@ export default {
|
||||
this.toolbar.eventName = ev.name
|
||||
this.toolbar.bold = !!ev.bold
|
||||
this.toolbar.schedulable = !!ev.schedulable
|
||||
this.toolbar.autoSchedule = !!ev.autoSchedule
|
||||
this.toolbar.mainCourse = !!ev.mainCourse
|
||||
this.toolbar.remarkShow = !!ev.remarkShow
|
||||
this.toolbar.remark = ev.remark || ''
|
||||
@@ -1132,7 +1234,7 @@ export default {
|
||||
bzxs: !!ev.remarkShow,
|
||||
zdpk: !!ev.autoSchedule,
|
||||
zk: !!ev.mainCourse,
|
||||
courseClass: SLOT_COURSE_MAP[pos.slotKey] || null,
|
||||
courseClass: this.courseClassOfSlot(pos.slotKey),
|
||||
xydxqbh: this.mode === 'class' ? this.xydxqbh : undefined,
|
||||
xydbh: this.mode === 'class' ? this.xydbh : undefined
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user