diff --git a/frontend/src/views/teachBusiness/calendar/components/SchoolCalendarEditor.vue b/frontend/src/views/teachBusiness/calendar/components/SchoolCalendarEditor.vue
index e7a47594f..999428ac4 100644
--- a/frontend/src/views/teachBusiness/calendar/components/SchoolCalendarEditor.vue
+++ b/frontend/src/views/teachBusiness/calendar/components/SchoolCalendarEditor.vue
@@ -74,7 +74,7 @@
:data-key="cellKey(wIdx, col.colIndex)"
@dblclick="onCellDblClick(wIdx, col)"
>
- {{ getEvent(wIdx, col.colIndex).name }}
+ {{ getEvent(wIdx, col.colIndex).name }}
{{ dateNumberOf(wIdx, col.dayIndex) }}
@@ -134,6 +134,8 @@ export default {
// 学期日期范围
startDate: null,
endDate: null,
+ // 日历渲染起点(学期当周周一)
+ calendarStart: null,
totalWeeks: 0,
dateRangeText: '',
weeks: [],
@@ -248,6 +250,7 @@ export default {
if (kx && jx) {
this.startDate = new Date(kx.replace(/-/g, '/'))
this.endDate = new Date(jx.replace(/-/g, '/'))
+ this.calendarStart = null
this.buildWeeks()
}
this.loadXqxlbEvents()
@@ -292,10 +295,10 @@ export default {
},
// 根据假期记录反推时间格位置(jqsj 日期 + courseClass 节次),与列是否可见无关
locateXqxlb(item) {
- if (!this.startDate || !item.jqsj) return null
+ if (!this.calendarStart || !item.jqsj) return null
const d = new Date(String(item.jqsj).slice(0, 10).replace(/-/g, '/'))
if (isNaN(d.getTime())) return null
- const offset = Math.round((d - this.startDate) / (24 * 3600 * 1000))
+ const offset = Math.round((d - this.calendarStart) / (24 * 3600 * 1000))
if (offset < 0) return null
const wIdx = Math.floor(offset / 7)
const dayIndex = offset % 7
@@ -315,13 +318,22 @@ export default {
if (s === '1112') return 'late'
return null
},
+ // 获取日期所在周的周一(周一为一周起点)
+ getMonday(d) {
+ const date = new Date(d)
+ const day = date.getDay() // 0=周日,1=周一,...,6=周六
+ const diff = date.getDate() - day + (day === 0 ? -6 : 1)
+ date.setDate(diff)
+ return date
+ },
buildWeeks() {
if (!this.startDate || !this.endDate) return
- const start = new Date(this.startDate)
+ const start = this.getMonday(new Date(this.startDate))
const end = new Date(this.endDate)
+ this.calendarStart = start
const days = Math.round((end - start) / (24 * 3600 * 1000)) + 1
this.totalWeeks = Math.ceil(days / 7)
- this.dateRangeText = fmtDate(start) + ' 到 ' + fmtDate(end)
+ this.dateRangeText = fmtDate(new Date(this.startDate)) + ' 到 ' + fmtDate(new Date(this.endDate))
const weeks = []
for (let w = 0; w < this.totalWeeks; w++) {
const wkStart = new Date(start)
@@ -355,21 +367,18 @@ export default {
},
// 单元格内显示的日期数字(如 0703)
dateNumberOf(wIdx, dayIndex) {
- if (!this.startDate) return ''
- const d = new Date(this.startDate)
- d.setDate(this.startDate.getDate() + wIdx * 7 + dayIndex)
+ if (!this.calendarStart) return ''
+ const d = new Date(this.calendarStart)
+ d.setDate(this.calendarStart.getDate() + wIdx * 7 + dayIndex)
return pad2(d.getMonth() + 1) + pad2(d.getDate())
},
cellClass(wIdx, col) {
const classes = []
- // 星期交替背景(单双日不同底色)
- if (col.dayIndex % 2 === 0) classes.push('sce-cell-odd')
- else classes.push('sce-cell-even')
if (this.selectedKeys.includes(this.cellKey(wIdx, col.colIndex))) classes.push('is-selected')
const ev = this.getEvent(wIdx, col.colIndex)
- if (ev) {
- classes.push('has-event')
- if (!ev.schedulable) classes.push('no-schedule')
+ // 可排课的全部白色;不可排课且事件名非空才标红
+ if (ev && ev.name && !ev.schedulable) {
+ classes.push('no-schedule')
}
return classes
},
@@ -467,8 +476,9 @@ export default {
return
}
const name = this.toolbar.eventName.trim()
+ // 空名称时按清除处理
if (!name) {
- this.$message.warning('请输入事件名称')
+ this.deleteEvent()
return
}
const keys = [...this.selectedKeys]
@@ -492,16 +502,20 @@ export default {
return
}
const keys = [...this.selectedKeys]
- keys.forEach(key => {
- this.$delete(this.events, key)
+ this.persistDeleteEvents(keys).then(({ ok, fail }) => {
+ if (fail === 0) {
+ keys.forEach(key => {
+ this.$delete(this.events, key)
+ })
+ this.selectedKeys = []
+ }
})
- this.$message.success('已删除 ' + keys.length + ' 个时间格事件')
},
absorbEvent() {
- // 吸取:取选择中第一个有事件的格
+ // 吸取:取选择中第一个事件名非空的格
let target = null
for (const key of this.selectedKeys) {
- if (this.events[key]) { target = this.events[key]; break }
+ if (this.events[key] && this.events[key].name) { target = this.events[key]; break }
}
if (!target) {
this.$message.warning('所选时间格中无事件可吸取')
@@ -517,7 +531,7 @@ export default {
},
onCellDblClick(wIdx, col) {
const ev = this.getEvent(wIdx, col.colIndex)
- if (ev) {
+ if (ev && ev.name) {
this.toolbar.eventName = ev.name
this.toolbar.bold = !!ev.bold
this.toolbar.schedulable = !!ev.schedulable
@@ -561,12 +575,35 @@ export default {
return { ok: ok, fail: fail }
})
},
+ // 批量删除选中格事件
+ persistDeleteEvents(keys) {
+ const tasks = keys
+ .filter(key => this.events[key])
+ .map(key => {
+ const payload = this.buildXqxlbPayload(key, this.events[key])
+ if (!payload) return Promise.resolve(false)
+ payload.delFlag = 1
+ return updateXqxlb(payload)
+ .then(() => true)
+ .catch(() => false)
+ })
+ return Promise.all(tasks).then(results => {
+ const ok = results.filter(r => r === true).length
+ const fail = results.length - ok
+ if (fail > 0) {
+ this.$message.error(fail + ' 个事件删除失败,请检查后端接口')
+ } else if (ok > 0) {
+ this.$message.success('已删除 ' + ok + ' 个时间格事件')
+ }
+ return { ok: ok, fail: fail }
+ })
+ },
// 构造 xqxlb 提交数据
buildXqxlbPayload(key, ev) {
const pos = this.parseCellKey(key)
if (!pos) return null
- const d = new Date(this.startDate)
- d.setDate(this.startDate.getDate() + pos.wIdx * 7 + pos.dayIndex)
+ const d = new Date(this.calendarStart)
+ d.setDate(this.calendarStart.getDate() + pos.wIdx * 7 + pos.dayIndex)
return {
delFlag: 0,
bh: ev.bh || undefined,
@@ -722,14 +759,20 @@ export default {
background: #fff;
transition: background 0.15s;
- .sce-date-num { color: #c0c4cc; }
+ .sce-event-name {
+ display: block;
+ line-height: 1;
+ padding: 2px 0;
+ }
- // 星期交替底色:周一/三/五/日为浅绿,周二/四/六为白,便于区分星期
- &.sce-cell-odd { background: #eef6f1; }
- &.sce-cell-even { background: #ffffff; }
- &.has-event { background: #e6f4ea; }
- &.has-event .sce-event-name { color: #00663e; font-weight: 500; }
- &.has-event .sce-event-name.is-bold { font-weight: 700; }
+ .sce-date-num {
+ display: block;
+ font-size: 10px;
+ color: #c0c4cc;
+ line-height: 1;
+ }
+
+ // 可排课白色,不可排课且有事件标红
&.no-schedule { background: #fde2e2; }
&.is-selected {
diff --git a/frontend/src/views/teachBusiness/calendar/index.vue b/frontend/src/views/teachBusiness/calendar/index.vue
index d5bcb56fd..7418c5948 100644
--- a/frontend/src/views/teachBusiness/calendar/index.vue
+++ b/frontend/src/views/teachBusiness/calendar/index.vue
@@ -40,7 +40,7 @@
class="cal-cell"
:class="cellClass(wIdx, col)"
>
-
+
{{ getEvent(wIdx, col.colIndex).name }}
{{ dateNumberOf(wIdx, col.dayIndex) }}
@@ -102,6 +102,8 @@ export default {
// 学期日期范围
startDate: null,
endDate: null,
+ // 日历渲染起点(学期当周周一)
+ calendarStart: null,
totalWeeks: 0,
dateRangeText: '',
weeks: [],
@@ -173,6 +175,7 @@ export default {
if (!this.nd) return
this.startDate = null
this.endDate = null
+ this.calendarStart = null
getSemester(this.nd)
.then(res => {
const data = res.data || res || {}
@@ -215,10 +218,10 @@ export default {
},
// 根据假期记录反推时间格 key(jqsj 日期 + courseClass 节次)
locateXqxlb(item) {
- if (!this.startDate || !item.jqsj) return null
+ if (!this.calendarStart || !item.jqsj) return null
const d = new Date(String(item.jqsj).slice(0, 10).replace(/-/g, '/'))
if (isNaN(d.getTime())) return null
- const offset = Math.round((d - this.startDate) / (24 * 3600 * 1000))
+ const offset = Math.round((d - this.calendarStart) / (24 * 3600 * 1000))
if (offset < 0) return null
const wIdx = Math.floor(offset / 7)
const dayIndex = offset % 7
@@ -240,13 +243,22 @@ export default {
if (s === '1112') return 'late'
return null
},
+ // 获取日期所在周的周一(周一为一周起点)
+ getMonday(d) {
+ const date = new Date(d)
+ const day = date.getDay() // 0=周日,1=周一,...,6=周六
+ const diff = date.getDate() - day + (day === 0 ? -6 : 1)
+ date.setDate(diff)
+ return date
+ },
buildWeeks() {
if (!this.startDate || !this.endDate) return
- const start = new Date(this.startDate)
+ const start = this.getMonday(new Date(this.startDate))
const end = new Date(this.endDate)
+ this.calendarStart = start
const days = Math.round((end - start) / (24 * 3600 * 1000)) + 1
this.totalWeeks = Math.ceil(days / 7)
- this.dateRangeText = fmtDate(start) + ' 到 ' + fmtDate(end)
+ this.dateRangeText = fmtDate(new Date(this.startDate)) + ' 到 ' + fmtDate(new Date(this.endDate))
const weeks = []
for (let w = 0; w < this.totalWeeks; w++) {
const wkStart = new Date(start)
@@ -276,20 +288,17 @@ export default {
},
// 单元格内显示的日期数字(如 0703)
dateNumberOf(wIdx, dayIndex) {
- if (!this.startDate) return ''
- const d = new Date(this.startDate)
- d.setDate(this.startDate.getDate() + wIdx * 7 + dayIndex)
+ if (!this.calendarStart) return ''
+ const d = new Date(this.calendarStart)
+ d.setDate(this.calendarStart.getDate() + wIdx * 7 + dayIndex)
return pad2(d.getMonth() + 1) + pad2(d.getDate())
},
cellClass(wIdx, col) {
const classes = []
- // 星期交替背景(单双日不同底色)
- if (col.dayIndex % 2 === 0) classes.push('cal-cell-odd')
- else classes.push('cal-cell-even')
const ev = this.getEvent(wIdx, col.colIndex)
- if (ev) {
- classes.push('has-event')
- if (!ev.schedulable) classes.push('no-schedule')
+ // 可排课的全部白色;不可排课且事件名非空才标红
+ if (ev && ev.name && !ev.schedulable) {
+ classes.push('no-schedule')
}
return classes
},
@@ -339,7 +348,7 @@ export default {
html += '| ' + week.rangeText + ' | '
this.visibleColumns.forEach(col => {
const ev = this.getEvent(wIdx, col.colIndex)
- if (ev) {
+ if (ev && ev.name) {
const remark = ev.remark && ev.remarkShow ? '(' + ev.remark + ')' : ''
html += '' + ev.name + remark + ' | '
} else if (this.showDate) {
@@ -466,13 +475,20 @@ export default {
position: relative;
background: #fff;
- .cal-date-num { color: #c0c4cc; }
+ .cal-event-name {
+ display: block;
+ line-height: 1;
+ padding: 2px 0;
+ }
- // 星期交替底色:周一/三/五/日为浅绿,周二/四/六为白
- &.cal-cell-odd { background: #eef6f1; }
- &.cal-cell-even { background: #ffffff; }
- &.has-event { background: #e6f4ea; }
- &.has-event .cal-event-name { color: #00663e; font-weight: 500; }
+ .cal-date-num {
+ display: block;
+ font-size: 10px;
+ color: #c0c4cc;
+ line-height: 1;
+ }
+
+ // 可排课白色,不可排课且有事件标红
&.no-schedule { background: #fde2e2; }
}
}