1课表模板管理;

2、课表生成;
3、课表的网格视图;
4、导出与打印
This commit is contained in:
2026-09-18 09:02:41 +08:00
parent 971ea46da5
commit 911dfe911b
16 changed files with 1864 additions and 0 deletions
@@ -0,0 +1,217 @@
<template>
<div class="tg-view" v-loading="loading">
<template v-if="grid && grid.weeks && grid.weeks.length">
<div v-for="week in grid.weeks" :key="week.weekNo" class="tg-week">
<div class="tg-week-title">
第 {{ week.weekNo }} 周({{ week.startDate }} ~ {{ week.endDate }})
</div>
<table class="tg-table">
<thead>
<tr>
<th class="tg-col-period">节次</th>
<th v-for="d in week.days" :key="d.date" :class="{ 'tg-blocked': d.blocked }">
<div>星期{{ weekdayName(d.weekday) }}</div>
<div class="tg-date">{{ d.date }}</div>
<div v-if="d.blocked && d.blockReason" class="tg-block-reason">{{ d.blockReason }}</div>
</th>
</tr>
</thead>
<tbody>
<tr v-for="p in grid.periods" :key="p.jc">
<td class="tg-period">
<div class="tg-period-name">{{ p.mc }}</div>
<div v-if="p.kssj" class="tg-period-time">{{ p.kssj }}-{{ p.jssj }}</div>
<div class="tg-period-sd">{{ p.sd }}</div>
</td>
<td
v-for="d in week.days"
:key="d.date"
class="tg-cell"
:class="{ 'tg-blocked': d.blocked }"
>
<div v-for="(cell, i) in cellsOf(d, p.jc)" :key="i" class="tg-lesson">
<div class="tg-course">{{ cell.kcjc || cell.kcmc }}</div>
<div v-if="showTeacher && cell.jyxm" class="tg-sub">{{ cell.jyxm }}</div>
<div v-if="showRoom && cell.jsmc" class="tg-sub">{{ cell.jsmc }}</div>
<div v-if="showTeam && cell.xydmc" class="tg-sub">{{ cell.xydmc }}</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div v-if="grid.remarks && grid.remarks.length" class="tg-remarks">
<div class="tg-remarks-title">备注栏</div>
<div v-for="(r, i) in grid.remarks" :key="i" class="tg-remark-row">
<span class="tg-remark-date">{{ r.date }}</span>
<span class="tg-remark-scope">[{{ r.scope }}]</span>
<span>{{ r.text }}</span>
</div>
</div>
</template>
<el-empty v-else-if="!loading" description="请选择维度与日期范围后生成课表" />
</div>
</template>
<script>
const WEEKDAY_NAMES = ['', '一', '二', '三', '四', '五', '六', '日']
/**
* 周次横版课表网格(手册一第12章)。
* 行=节次、列=星期一~日、纵向按周分块;备注栏事件不落格。
* 供「课表生成」页与后续角色化页面(教员端/学员端)复用。
*/
export default {
name: 'TimetableGridView',
props: {
grid: { type: Object, default: null },
loading: { type: Boolean, default: false },
showTeacher: { type: Boolean, default: true },
showRoom: { type: Boolean, default: true },
showTeam: { type: Boolean, default: false }
},
methods: {
weekdayName(wd) {
return WEEKDAY_NAMES[wd] || wd
},
cellsOf(day, jc) {
return (day.cells && day.cells[String(jc)]) || []
}
}
}
</script>
<style scoped lang="scss">
.tg-view {
.tg-week {
margin-bottom: 20px;
}
.tg-week-title {
font-size: 14px;
font-weight: 700;
color: #303133;
margin-bottom: 8px;
}
.tg-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
background: #fff;
th, td {
border: 1px solid #dcdfe6;
padding: 6px;
vertical-align: top;
font-size: 12px;
}
th {
background: #f5f7fa;
text-align: center;
font-weight: 600;
}
.tg-col-period {
width: 96px;
}
.tg-date {
font-size: 11px;
color: #909399;
font-weight: 400;
}
.tg-block-reason {
font-size: 11px;
color: #f56c6c;
font-weight: 400;
}
th.tg-blocked {
background: repeating-linear-gradient(45deg, #f5f7fa, #f5f7fa 6px, #eceff2 6px, #eceff2 12px);
}
td.tg-blocked {
background: repeating-linear-gradient(45deg, #fafafa, #fafafa 6px, #f0f1f2 6px, #f0f1f2 12px);
}
}
.tg-period {
text-align: center;
background: #fafbfc;
.tg-period-name {
font-weight: 600;
}
.tg-period-time {
font-size: 11px;
color: #909399;
}
.tg-period-sd {
font-size: 11px;
color: #c0c4cc;
}
}
.tg-lesson {
margin-bottom: 4px;
padding: 4px;
background: #eef6f2;
border-radius: 3px;
border-left: 3px solid var(--edu-color-primary, #0b6b55);
.tg-course {
font-weight: 600;
color: #303133;
}
.tg-sub {
font-size: 11px;
color: #606266;
}
}
.tg-remarks {
margin-top: 8px;
border: 1px solid #ebeef5;
border-radius: 6px;
padding: 10px 14px;
background: #fff;
.tg-remarks-title {
font-weight: 700;
font-size: 13px;
margin-bottom: 6px;
}
.tg-remark-row {
font-size: 12px;
color: #606266;
line-height: 1.8;
.tg-remark-date {
color: #909399;
margin-right: 6px;
}
.tg-remark-scope {
color: #e6a23c;
margin-right: 6px;
}
}
}
}
@media print {
.tg-view {
.tg-week {
page-break-inside: avoid;
}
}
}
</style>