forked from liweijie/education
1、添加教学场地历;
2、很多表继承了基础类,但是没有添加对应字段导致报错,把继承去掉
This commit is contained in:
@@ -17,11 +17,11 @@
|
||||
<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="mode === 'class' ? '请输入班历事件名称' : '请输入校历事件名称'" />
|
||||
<el-checkbox v-model="toolbar.bold" class="sce-cb">加粗显示</el-checkbox>
|
||||
<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-model="toolbar.mainCourse" class="sce-cb">正课</el-checkbox>
|
||||
<el-checkbox v-model="toolbar.remarkShow" 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>
|
||||
<el-input
|
||||
v-model="toolbar.remark"
|
||||
@@ -37,6 +37,7 @@
|
||||
<el-button type="primary" size="small" icon="el-icon-check" @click="applyEvent">设定</el-button>
|
||||
<el-button type="danger" size="small" icon="el-icon-delete" @click="deleteEvent">删除</el-button>
|
||||
<el-button size="small" icon="el-icon-brush" @click="absorbEvent">吸取</el-button>
|
||||
<el-button v-if="mode === 'venue'" size="small" icon="el-icon-magic-stick" @click="openRuleDialog">规律生成</el-button>
|
||||
<el-button size="small" icon="el-icon-refresh" @click="refreshGrid">刷新</el-button>
|
||||
<span class="sce-divider" />
|
||||
<el-checkbox v-model="show78" class="sce-cb">显示78节</el-checkbox>
|
||||
@@ -45,6 +46,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 场地历:专用教室横幅 -->
|
||||
<div v-if="mode === 'venue' && designatedTeams.length" class="sce-venue-banner">
|
||||
指定本场地为专用教室的班次:{{ designatedTeams.join('、') }}
|
||||
</div>
|
||||
|
||||
<!-- 时间编排区域 -->
|
||||
<div ref="gridWrap" class="sce-grid-wrap" @mousedown="onGridMouseDown">
|
||||
<table class="sce-grid" :class="{ 'is-selecting': selecting }">
|
||||
@@ -72,9 +78,11 @@
|
||||
class="sce-cell"
|
||||
:class="cellClass(wIdx, col)"
|
||||
:data-key="cellKey(wIdx, col.colIndex)"
|
||||
:title="cellTitle(wIdx, col)"
|
||||
@dblclick="onCellDblClick(wIdx, col)"
|
||||
>
|
||||
<span v-if="getEvent(wIdx, col.colIndex) && getEvent(wIdx, col.colIndex).name" class="sce-event-name" :class="{ 'is-bold': getEvent(wIdx, col.colIndex).bold }">{{ getEvent(wIdx, col.colIndex).name }}</span>
|
||||
<span v-else-if="mode === 'venue' && getLessons(wIdx, col.colIndex)" class="sce-lesson-name">{{ lessonTextOf(wIdx, col.colIndex) }}</span>
|
||||
<span v-else class="sce-date-num">{{ dateNumberOf(wIdx, col.dayIndex) }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -85,7 +93,47 @@
|
||||
<div class="sce-status">
|
||||
已选 {{ selectedKeys.length }} 个时间格
|
||||
<span v-if="absorbPreview" class="sce-absorb-tip">已吸取:{{ absorbPreview }}</span>
|
||||
<span v-if="mode === 'venue'" class="sce-legend">
|
||||
<i class="lg lg-red" />不可用
|
||||
<i class="lg lg-yellow" />场地备注
|
||||
<i class="lg lg-blue" />已排课次
|
||||
<i class="lg lg-gray" />校历不可排
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 场地历:按星期规律生成 -->
|
||||
<el-dialog title="按星期规律生成场地事件" :visible.sync="ruleDialog.visible" width="540px" append-to-body
|
||||
:close-on-click-modal="false">
|
||||
<el-form label-width="90px" size="small">
|
||||
<el-form-item label="星期">
|
||||
<el-checkbox-group v-model="ruleDialog.weekdays">
|
||||
<el-checkbox v-for="(d, i) in weekDayOptions" :key="i" :label="i">{{ d }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="节次">
|
||||
<el-checkbox-group v-model="ruleDialog.slots">
|
||||
<el-checkbox v-for="s in slotOptions" :key="s.key" :label="s.key">{{ s.label }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="周次范围">
|
||||
<el-input-number v-model="ruleDialog.weekStart" :min="1" :max="totalWeeks || 1" size="small" class="rule-week" />
|
||||
<span class="rule-sep">至</span>
|
||||
<el-input-number v-model="ruleDialog.weekEnd" :min="1" :max="totalWeeks || 1" size="small" class="rule-week" />
|
||||
<span class="rule-unit">周</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="事件内容">
|
||||
<span class="rule-hint">使用上方工具栏填写的「事件名称 / 可排课 / 备注」</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="预计生成">
|
||||
<span>{{ rulePreviewCount }} 个时间格</span>
|
||||
<span v-if="ruleSkippedCount" class="rule-hint">(跳过校历不可排/已排课 {{ ruleSkippedCount }} 格)</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button size="small" @click="ruleDialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" size="small" :loading="ruleDialog.submitting" @click="applyRuleGenerate">生 成</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -93,6 +141,13 @@
|
||||
import { getSemester } from '@/api/teachBusiness/semester'
|
||||
import { listXqxlb, addXqxlb, updateXqxlb } from '@/api/teachBusiness/xqxlb'
|
||||
import { listClassCalendarEvent, updateClassCalendarEvent } from '@/api/teachOffice/classCalendarEvent'
|
||||
import {
|
||||
listVenueCalendarRange,
|
||||
batchSaveVenueCalendar,
|
||||
batchDeleteVenueCalendar,
|
||||
listVenueLessons,
|
||||
listVenueDesignatedTeams
|
||||
} from '@/api/teachBusiness/venueCalendar'
|
||||
|
||||
// 节次定义:12/34/56 常显,78/晚上/夜间由开关控制可见
|
||||
const SLOT_DEFS = [
|
||||
@@ -116,6 +171,9 @@ const SLOT_COURSE_MAP = {
|
||||
|
||||
const WEEK_DAYS = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
|
||||
// 场地历:单节次 -> 节次格 key(1-2 节合并在同一格)
|
||||
const JC_SLOT_MAP = { 1: '12', 2: '12', 3: '34', 4: '34', 5: '56', 6: '56', 7: '78', 8: '78', 9: 'night', 10: 'night', 11: 'late', 12: 'late' }
|
||||
|
||||
function pad2(n) {
|
||||
return n < 10 ? '0' + n : '' + n
|
||||
}
|
||||
@@ -142,6 +200,8 @@ export default {
|
||||
mode: { type: String, default: 'school' },
|
||||
xydxqbh: { type: String, default: '' },
|
||||
xydbh: { type: String, default: '' },
|
||||
// 场地历模式:教室编号
|
||||
jsbh: { type: String, default: '' },
|
||||
rangeStart: { type: String, default: '' },
|
||||
rangeEnd: { type: String, default: '' }
|
||||
},
|
||||
@@ -181,7 +241,24 @@ export default {
|
||||
moved: false, // 是否发生移动(区分点击与拖拽)
|
||||
dragAddMode: false, // ctrl 拖拽为追加
|
||||
// 窗口控制
|
||||
absorbPreview: ''
|
||||
absorbPreview: '',
|
||||
// ---- 场地历模式 ----
|
||||
// 校历不可排格:'yyyy-MM-dd#slotKey' -> 校历事件名(置灰只读,不落库)
|
||||
schoolOff: {},
|
||||
// 已排课次(蓝格只读):'yyyy-MM-dd#slotKey' -> [{ kcmc, jyxm, xydmc, jc }]
|
||||
lessons: {},
|
||||
// 指定本场地为专用教室的班次(顶部横幅)
|
||||
designatedTeams: [],
|
||||
weekDayOptions: WEEK_DAYS,
|
||||
slotOptions: SLOT_DEFS,
|
||||
ruleDialog: {
|
||||
visible: false,
|
||||
submitting: false,
|
||||
weekdays: [],
|
||||
slots: [],
|
||||
weekStart: 1,
|
||||
weekEnd: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -202,6 +279,36 @@ export default {
|
||||
// 不再按日历起点/季度取年份,避免跨年度学期解析出错。
|
||||
xqxlbNd() {
|
||||
return Number(String(this.nd).slice(0, 6)) || Number(this.nd) || 0
|
||||
},
|
||||
// 规律生成:预计写入的格子数(排除学期范围外/校历不可排/已排课的格)
|
||||
ruleTargets() {
|
||||
const cells = []
|
||||
let skipped = 0
|
||||
const dlg = this.ruleDialog
|
||||
if (!dlg.weekdays.length || !dlg.slots.length || !this.calendarStart) return { cells, skipped }
|
||||
const w0 = Math.max(0, (dlg.weekStart || 1) - 1)
|
||||
const w1 = Math.min(this.totalWeeks - 1, (dlg.weekEnd || this.totalWeeks) - 1)
|
||||
for (let w = w0; w <= w1; w++) {
|
||||
dlg.weekdays.forEach(dayIndex => {
|
||||
if (this.isOutOfRange(w, dayIndex)) return
|
||||
const d = this.cellDate(w, dayIndex)
|
||||
const dateStr = fmtDate(d)
|
||||
dlg.slots.forEach(slotKey => {
|
||||
if (this.isSchoolOff(dateStr, slotKey) || this.hasLessonAt(dateStr, slotKey)) {
|
||||
skipped++
|
||||
return
|
||||
}
|
||||
cells.push({ dateStr, slotKey })
|
||||
})
|
||||
})
|
||||
}
|
||||
return { cells, skipped }
|
||||
},
|
||||
rulePreviewCount() {
|
||||
return this.ruleTargets.cells.length
|
||||
},
|
||||
ruleSkippedCount() {
|
||||
return this.ruleTargets.skipped
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -217,6 +324,12 @@ export default {
|
||||
if (this.mode === 'class' && val) this.loadClassCalendar()
|
||||
}
|
||||
},
|
||||
jsbh: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (this.mode === 'venue' && val) this.loadVenueEvents()
|
||||
}
|
||||
},
|
||||
visibleColumns(newCols, oldCols) {
|
||||
// 节次列显隐会改变列索引,按「周期-星期-节次」重定位事件,避免事件随时间格列偏移
|
||||
if (oldCols && oldCols.length) {
|
||||
@@ -298,7 +411,8 @@ export default {
|
||||
this.calendarStart = null
|
||||
this.buildWeeks()
|
||||
}
|
||||
this.loadXqxlbEvents()
|
||||
if (this.mode === 'venue') this.loadVenueEvents()
|
||||
else this.loadXqxlbEvents()
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.warning('学期详情获取失败,请确认学期数据')
|
||||
@@ -360,6 +474,195 @@ export default {
|
||||
})
|
||||
this.events = loaded
|
||||
},
|
||||
/* ---------- 场地历(venue 模式) ---------- */
|
||||
// 场地历为稀疏存储:只拉"事件"行,空格默认即"可排";
|
||||
// 校历不可排格(节假日)整格置灰只读不落库;已排课次蓝格只读。
|
||||
loadVenueEvents() {
|
||||
if (!this.jsbh) return
|
||||
const s = this.startDate ? fmtDate(this.startDate) : ''
|
||||
const e = this.endDate ? fmtDate(this.endDate) : ''
|
||||
Promise.all([
|
||||
listXqxlb({ nd: this.xqxlbNd }).catch(() => ({ data: [] })),
|
||||
listVenueCalendarRange(this.jsbh, s, e).catch(() => ({ data: [] })),
|
||||
listVenueLessons(this.jsbh, s, e, this.xqxlbNd).catch(() => ({ data: [] })),
|
||||
listVenueDesignatedTeams(this.jsbh).catch(() => ({ data: [] }))
|
||||
]).then(([xlRes, evRes, lsRes, tmRes]) => {
|
||||
const xlList = Array.isArray(xlRes.data) ? xlRes.data : (xlRes.data && xlRes.data.records) || []
|
||||
const evList = Array.isArray(evRes.data) ? evRes.data : (evRes.data && evRes.data.records) || []
|
||||
const lsList = Array.isArray(lsRes.data) ? lsRes.data : (lsRes.data && lsRes.data.records) || []
|
||||
this.designatedTeams = Array.isArray(tmRes.data) ? tmRes.data : []
|
||||
// 校历不可排格 -> 灰
|
||||
const off = {}
|
||||
xlList.forEach(item => {
|
||||
if (item.kpk === true || item.kpk === 1) return
|
||||
const dateStr = String(item.jqsj || '').slice(0, 10)
|
||||
const slotKey = this.courseClassToSlotKey(item.courseClass)
|
||||
if (dateStr && slotKey) off[dateStr + '#' + slotKey] = item.jqmc || '校历不可排课'
|
||||
})
|
||||
this.schoolOff = off
|
||||
// 已排课次 -> 蓝
|
||||
const lessons = {}
|
||||
lsList.forEach(item => {
|
||||
const dateStr = String(item.rq || '').slice(0, 10)
|
||||
const slotKey = JC_SLOT_MAP[item.jc]
|
||||
if (!dateStr || !slotKey) return
|
||||
const key = dateStr + '#' + slotKey
|
||||
if (!lessons[key]) lessons[key] = []
|
||||
lessons[key].push(item)
|
||||
})
|
||||
this.lessons = lessons
|
||||
this.renderVenueEvents(evList)
|
||||
})
|
||||
},
|
||||
renderVenueEvents(list) {
|
||||
// 同格(日期+节次段)两行单节次记录归并为一个事件
|
||||
const merged = {}
|
||||
list.forEach(row => {
|
||||
const dateStr = String(row.rq || '').slice(0, 10)
|
||||
const slotKey = JC_SLOT_MAP[row.jc]
|
||||
if (!dateStr || !slotKey) return
|
||||
const pos = this.locateDateSlot(dateStr, slotKey)
|
||||
if (!pos) return
|
||||
const colIndex = this.colIndexOf(pos.dayIndex, pos.slotKey)
|
||||
const ck = colIndex >= 0 ? this.cellKey(pos.wIdx, colIndex) : null
|
||||
const storeKey = ck || this.cellStableKey(pos.wIdx, pos.dayIndex, pos.slotKey)
|
||||
const bucket = ck ? merged : this.hiddenEvents
|
||||
const prev = bucket[storeKey]
|
||||
if (prev) {
|
||||
if (row.id) prev.ids.push(row.id)
|
||||
if (!prev.name && row.mc) prev.name = row.mc
|
||||
if (row.kpk === false || row.kpk === 0) prev.schedulable = false
|
||||
if (!prev.remark && row.bz) prev.remark = row.bz
|
||||
} else {
|
||||
bucket[storeKey] = {
|
||||
ids: row.id ? [row.id] : [],
|
||||
name: row.mc || '',
|
||||
schedulable: !(row.kpk === false || row.kpk === 0),
|
||||
remark: row.bz || ''
|
||||
}
|
||||
}
|
||||
})
|
||||
this.events = merged
|
||||
},
|
||||
// 日期 + 节次格 -> 网格位置
|
||||
locateDateSlot(dateStr, slotKey) {
|
||||
if (!this.calendarStart || !dateStr) return null
|
||||
const d = new Date(dateStr.replace(/-/g, '/'))
|
||||
if (isNaN(d.getTime())) return null
|
||||
const offset = Math.round((d - this.calendarStart) / (24 * 3600 * 1000))
|
||||
if (offset < 0) return null
|
||||
return { wIdx: Math.floor(offset / 7), dayIndex: offset % 7, slotKey }
|
||||
},
|
||||
cellDateStr(wIdx, dayIndex) {
|
||||
const d = this.cellDate(wIdx, dayIndex)
|
||||
return d ? fmtDate(d) : ''
|
||||
},
|
||||
isSchoolOff(dateStr, slotKey) {
|
||||
return !!this.schoolOff[dateStr + '#' + slotKey]
|
||||
},
|
||||
hasLessonAt(dateStr, slotKey) {
|
||||
return !!(this.lessons[dateStr + '#' + slotKey] || []).length
|
||||
},
|
||||
getLessons(wIdx, colIndex) {
|
||||
const col = this.visibleColumns.find(c => c.colIndex === colIndex)
|
||||
if (!col) return null
|
||||
return this.lessons[this.cellDateStr(wIdx, col.dayIndex) + '#' + col.slotKey] || null
|
||||
},
|
||||
lessonTextOf(wIdx, colIndex) {
|
||||
const list = this.getLessons(wIdx, colIndex) || []
|
||||
const names = list.map(l => l.kcmc).filter(Boolean)
|
||||
return names.length ? names.join(';') : '已排课'
|
||||
},
|
||||
cellTitle(wIdx, col) {
|
||||
if (this.mode !== 'venue') return ''
|
||||
const dateStr = this.cellDateStr(wIdx, col.dayIndex)
|
||||
const parts = []
|
||||
const offName = this.schoolOff[dateStr + '#' + col.slotKey]
|
||||
if (offName) parts.push('校历:' + offName + '(不可排课)')
|
||||
const ls = this.lessons[dateStr + '#' + col.slotKey] || []
|
||||
ls.forEach(l => {
|
||||
parts.push('课次:' + (l.kcmc || '-') +
|
||||
(l.jyxm ? ' / 教员:' + l.jyxm : '') +
|
||||
(l.xydmc ? ' / 班次:' + l.xydmc : ''))
|
||||
})
|
||||
const ev = this.getEvent(wIdx, col.colIndex)
|
||||
if (ev && (ev.name || ev.remark)) {
|
||||
parts.push('场地事件:' + (ev.name || '-') + (ev.remark ? '(' + ev.remark + ')' : ''))
|
||||
}
|
||||
return parts.join('\n')
|
||||
},
|
||||
// 场地历可编辑格过滤:剔除校历不可排、已排课次、学期范围外的格
|
||||
filterVenueEditable(keys) {
|
||||
const ok = []
|
||||
let skipped = 0
|
||||
keys.forEach(key => {
|
||||
const pos = this.parseCellKey(key)
|
||||
if (!pos) { skipped++; return }
|
||||
const dateStr = this.cellDateStr(pos.wIdx, pos.dayIndex)
|
||||
if (this.isOutOfRange(pos.wIdx, pos.dayIndex)
|
||||
|| this.isSchoolOff(dateStr, pos.slotKey)
|
||||
|| this.hasLessonAt(dateStr, pos.slotKey)) {
|
||||
skipped++
|
||||
return
|
||||
}
|
||||
ok.push({ key, pos, dateStr })
|
||||
})
|
||||
return { ok, skipped }
|
||||
},
|
||||
periodsOfSlot(slotKey) {
|
||||
const seg = SLOT_COURSE_MAP[slotKey]
|
||||
if (!seg) return []
|
||||
return seg.split('-').map(Number).filter(n => !isNaN(n))
|
||||
},
|
||||
/* ---------- 规律生成 ---------- */
|
||||
openRuleDialog() {
|
||||
if (!this.toolbar.eventName.trim()) {
|
||||
this.$message.warning('请先在上方工具栏填写事件名称')
|
||||
return
|
||||
}
|
||||
this.ruleDialog.weekEnd = this.totalWeeks || 1
|
||||
this.ruleDialog.visible = true
|
||||
},
|
||||
applyRuleGenerate() {
|
||||
const name = this.toolbar.eventName.trim()
|
||||
if (!name) {
|
||||
this.$message.warning('请先填写事件名称')
|
||||
return
|
||||
}
|
||||
const { cells } = this.ruleTargets
|
||||
if (!cells.length) {
|
||||
this.$message.warning('所选条件下没有可写入的时间格')
|
||||
return
|
||||
}
|
||||
this.ruleDialog.submitting = true
|
||||
this.saveVenueCells(cells, name).then(ok => {
|
||||
if (ok) this.ruleDialog.visible = false
|
||||
}).finally(() => {
|
||||
this.ruleDialog.submitting = false
|
||||
})
|
||||
},
|
||||
// 把 [{dateStr, slotKey}] 展开为单节次行并批量保存
|
||||
saveVenueCells(cells, name) {
|
||||
const rows = []
|
||||
cells.forEach(c => {
|
||||
this.periodsOfSlot(c.slotKey).forEach(jc => {
|
||||
rows.push({
|
||||
jsbh: this.jsbh,
|
||||
rq: c.dateStr + ' 00:00:00',
|
||||
jc: jc,
|
||||
kpk: !!this.toolbar.schedulable,
|
||||
mc: name,
|
||||
bz: this.toolbar.remark || null
|
||||
})
|
||||
})
|
||||
})
|
||||
if (!rows.length) return Promise.resolve(false)
|
||||
return batchSaveVenueCalendar(rows).then(res => {
|
||||
this.$message.success((res && res.message) || '已保存 ' + rows.length + ' 条场地历')
|
||||
this.reloadEvents()
|
||||
return true
|
||||
}).catch(() => false)
|
||||
},
|
||||
// 根据假期记录反推时间格位置(jqsj 日期 + courseClass 节次),与列是否可见无关
|
||||
locateXqxlb(item) {
|
||||
if (!this.calendarStart || !item.jqsj) return null
|
||||
@@ -442,13 +745,20 @@ export default {
|
||||
cellClass(wIdx, col) {
|
||||
const classes = []
|
||||
if (this.selectedKeys.includes(this.cellKey(wIdx, col.colIndex))) classes.push('is-selected')
|
||||
// 班历:班次日期范围外的格子不可排,给出明确视觉提示
|
||||
if (this.mode === 'class' && this.isOutOfRange(wIdx, col.dayIndex)) {
|
||||
// 班历/场地历:学期日期范围外的格子不可排,给出明确视觉提示
|
||||
if ((this.mode === 'class' || this.mode === 'venue') && this.isOutOfRange(wIdx, col.dayIndex)) {
|
||||
classes.push('is-out-of-range')
|
||||
}
|
||||
const ev = this.getEvent(wIdx, col.colIndex)
|
||||
// 可排课的全部白色;不可排课且事件名非空才标红
|
||||
if (ev && ev.name && !ev.schedulable) {
|
||||
if (this.mode === 'venue') {
|
||||
const dateStr = this.cellDateStr(wIdx, col.dayIndex)
|
||||
// 校历不可排(节假日)置灰只读;已排课次蓝色只读
|
||||
if (this.isSchoolOff(dateStr, col.slotKey)) classes.push('is-school-off')
|
||||
if (this.hasLessonAt(dateStr, col.slotKey)) classes.push('has-lesson')
|
||||
// 场地事件:不可排标红,仍可排的纯备注标黄
|
||||
if (ev) classes.push(ev.schedulable ? 'has-note' : 'no-schedule')
|
||||
} else if (ev && ev.name && !ev.schedulable) {
|
||||
// 可排课的全部白色;不可排课且事件名非空才标红
|
||||
classes.push('no-schedule')
|
||||
}
|
||||
return classes
|
||||
@@ -585,6 +895,16 @@ export default {
|
||||
}
|
||||
}
|
||||
const keys = [...this.selectedKeys]
|
||||
// 场地历:过滤不可编辑格(校历不可排/已排课次/范围外),按单节次展开批量保存
|
||||
if (this.mode === 'venue') {
|
||||
const { ok, skipped } = this.filterVenueEditable(keys)
|
||||
if (skipped > 0) {
|
||||
this.$message.warning(`已跳过 ${skipped} 个不可编辑格(校历不可排/已排课次/范围外)`)
|
||||
}
|
||||
if (!ok.length) return
|
||||
this.saveVenueCells(ok.map(t => ({ dateStr: t.dateStr, slotKey: t.pos.slotKey })), name)
|
||||
return
|
||||
}
|
||||
keys.forEach(key => {
|
||||
const prev = this.events[key]
|
||||
this.$set(this.events, key, {
|
||||
@@ -613,6 +933,25 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const keys = [...this.selectedKeys]
|
||||
// 场地历:收集事件行 ID 走批量删除
|
||||
if (this.mode === 'venue') {
|
||||
const ids = []
|
||||
keys.forEach(key => {
|
||||
const ev = this.events[key]
|
||||
if (ev && ev.ids) ids.push(...ev.ids)
|
||||
})
|
||||
if (!ids.length) {
|
||||
this.$message.warning('所选时间格没有场地事件')
|
||||
return
|
||||
}
|
||||
batchDeleteVenueCalendar(ids).then(res => {
|
||||
this.$message.success((res && res.message) || '已删除场地事件')
|
||||
keys.forEach(key => this.$delete(this.events, key))
|
||||
this.selectedKeys = []
|
||||
this.reloadEvents()
|
||||
}).catch(() => {})
|
||||
return
|
||||
}
|
||||
this.persistDeleteEvents(keys).then(({ ok, fail }) => {
|
||||
if (fail === 0) {
|
||||
keys.forEach(key => {
|
||||
@@ -643,6 +982,17 @@ export default {
|
||||
},
|
||||
onCellDblClick(wIdx, col) {
|
||||
const ev = this.getEvent(wIdx, col.colIndex)
|
||||
// 场地历:双击蓝格显示课次详情
|
||||
if (this.mode === 'venue') {
|
||||
const ls = this.getLessons(wIdx, col.colIndex)
|
||||
if (ls && ls.length && !(ev && ev.name)) {
|
||||
const lines = ls.map(l => '课程:' + (l.kcmc || '-') +
|
||||
(l.jyxm ? ' 教员:' + l.jyxm : '') +
|
||||
(l.xydmc ? ' 班次:' + l.xydmc : ''))
|
||||
this.$alert(lines.join('<br/>'), '已排课次', { dangerouslyUseHTMLString: true })
|
||||
return
|
||||
}
|
||||
}
|
||||
if (ev && ev.name) {
|
||||
this.toolbar.eventName = ev.name
|
||||
this.toolbar.bold = !!ev.bold
|
||||
@@ -660,6 +1010,7 @@ export default {
|
||||
this.events = {}
|
||||
this.hiddenEvents = {}
|
||||
if (this.mode === 'class') this.loadClassEvents()
|
||||
else if (this.mode === 'venue') this.loadVenueEvents()
|
||||
else this.loadXqxlbEvents()
|
||||
this.$message.info('已刷新')
|
||||
},
|
||||
@@ -667,6 +1018,7 @@ export default {
|
||||
this.events = {}
|
||||
this.hiddenEvents = {}
|
||||
if (this.mode === 'class') this.loadClassEvents()
|
||||
else if (this.mode === 'venue') this.loadVenueEvents()
|
||||
else this.loadXqxlbEvents()
|
||||
},
|
||||
savePayload(payload) {
|
||||
@@ -765,7 +1117,7 @@ export default {
|
||||
/* ---------- 返回学期管理 ---------- */
|
||||
handleClose() {
|
||||
this.$emit('close')
|
||||
if (this.mode !== 'class') {
|
||||
if (this.mode === 'school') {
|
||||
this.$router.replace({ path: '/teachBusiness/semester' })
|
||||
}
|
||||
}
|
||||
@@ -827,6 +1179,15 @@ export default {
|
||||
.sce-divider { width: 1px; height: 18px; background: #dcdfe6; margin: 0 14px; }
|
||||
}
|
||||
|
||||
/* 场地历:专用教室横幅 */
|
||||
.sce-venue-banner {
|
||||
padding: 6px 14px;
|
||||
font-size: 12px;
|
||||
color: #e6a23c;
|
||||
background: #fdf6ec;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
/* 时间编排区 */
|
||||
.sce-grid-wrap {
|
||||
flex: 1;
|
||||
@@ -912,6 +1273,34 @@ export default {
|
||||
// 可排课白色,不可排课且有事件标红
|
||||
&.no-schedule { background: #fde2e2; }
|
||||
|
||||
// 场地历:仍可排的纯备注事件标黄
|
||||
&.has-note { background: #fdf6ec; }
|
||||
|
||||
// 场地历:已排课次蓝格(只读)
|
||||
&.has-lesson {
|
||||
background: #e8f1fd;
|
||||
cursor: default;
|
||||
|
||||
.sce-lesson-name {
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
color: #409eff;
|
||||
line-height: 1;
|
||||
padding: 2px 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// 场地历:校历不可排格置灰只读
|
||||
&.is-school-off {
|
||||
background: #f0f0f0;
|
||||
cursor: not-allowed;
|
||||
|
||||
.sce-date-num { color: #c0c4cc; }
|
||||
}
|
||||
|
||||
// 班历:班次日期范围外的格子不可排
|
||||
&.is-out-of-range {
|
||||
background: #f4f4f5;
|
||||
@@ -936,6 +1325,28 @@ export default {
|
||||
background: #fafafa;
|
||||
|
||||
.sce-absorb-tip { margin-left: 12px; color: #00875a; }
|
||||
|
||||
.sce-legend {
|
||||
float: right;
|
||||
|
||||
.lg {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 0 4px 0 14px;
|
||||
border: 1px solid #dcdfe6;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.lg-red { background: #fde2e2; }
|
||||
.lg-yellow { background: #fdf6ec; }
|
||||
.lg-blue { background: #e8f1fd; }
|
||||
.lg-gray { background: #f0f0f0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rule-week { width: 110px; }
|
||||
.rule-sep { margin: 0 8px; color: #606266; }
|
||||
.rule-unit { margin-left: 8px; color: #606266; }
|
||||
.rule-hint { font-size: 12px; color: #909399; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user