后端代码

This commit is contained in:
liumengyu
2026-08-24 17:48:55 +08:00
parent e0485f7366
commit aa4145fd33
419 changed files with 3684 additions and 53031 deletions
@@ -1,274 +0,0 @@
<template>
<div class="semester-bar">
<!-- 当前学期信息 -->
<div class="semester-bar__item semester-bar__current">
<i class="el-icon-date" />
<span class="label">当前学期</span>
<span class="value">{{ currentSemesterName }}</span>
<span v-if="currentSemesterDate" class="date">{{ currentSemesterDate }}</span>
</div>
<span class="semester-bar__divider" />
<!-- 今日日期 -->
<div class="semester-bar__item semester-bar__date">
<i class="el-icon-time" />
<span class="value">{{ todayText }}</span>
<span class="week">{{ weekText }}</span>
</div>
<span class="semester-bar__divider" />
<!-- 学期切换下拉框 -->
<div class="semester-bar__item semester-bar__switch">
<span class="label">切换学期</span>
<div class="semester-select-wrap">
<el-select
:value="activeSemester ? activeSemester.nd : ''"
placeholder="请选择学期"
size="small"
class="semester-select"
@change="handleSwitch"
>
<el-option
v-for="item in semesterList"
:key="item.nd"
:label="getSemesterName(item.nd)"
:value="item.nd"
/>
</el-select>
</div>
</div>
</div>
</template>
<script>
import { listSemester, updateSemester } from '@/api/teachBusiness/semester'
export default {
name: 'SemesterBar',
data() {
return {
// 学期列表(接口数据)
semesterList: [],
// 当前选中的学期对象
activeSemester: null,
today: new Date(),
loading: false
}
},
computed: {
currentSemesterName() {
return this.getSemesterName(this.activeSemester ? this.activeSemester.nd : '')
},
currentSemesterDate() {
const item = this.activeSemester
if (!item) return ''
const start = this.formatDate(item.kxrq)
const end = this.formatDate(item.jsrq)
if (!start && !end) return ''
return `${start || '?'} ~ ${end || '?'}`
},
todayText() {
const d = this.today
const pad = n => (n < 10 ? '0' + n : '' + n)
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
},
weekText() {
const weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
return weeks[this.today.getDay()]
}
},
created() {
this.getSemesterList()
},
methods: {
/** 加载学期列表,默认选中当前学期(dqxq=true),无当前学期则选第一条 */
getSemesterList() {
this.loading = true
listSemester({ pageNum: 1, pageSize: 100 }).then(response => {
const data = response.data || {}
const list = data.records || []
this.semesterList = list
const current = list.find(i => i.dqxq)
this.activeSemester = current || (list[0] ? list[0] : null)
this.loading = false
}).catch(() => {
this.semesterList = []
this.loading = false
})
},
/** 格式化后端 LocalDateTime2026-02-23T00:00:00 -> 2026-02-23 */
formatDate(value) {
if (!value) return ''
return String(value).slice(0, 10)
},
/** 学期代号 -> 学期名称(如 202601 -> 2026年春季学期) */
getSemesterName(nd) {
if (!nd) return ''
const s = String(nd)
const xn = s.slice(0, 4)
const xq = s.slice(4)
const map = { '01': '春季学期', '02': '夏季学期', '03': '秋季学期' }
return xn + '年' + (map[xq] || '第' + xq + '学期')
},
/** 切换学期:将目标学期设为当前学期,原当前学期取消 */
handleSwitch(nd) {
const current = this.activeSemester
if (!nd || (current && nd === current.nd)) return
const target = this.semesterList.find(i => i.nd === nd)
if (!target) return
// 当前已是"当前学期"的其他记录(需取消)
const others = this.semesterList.filter(i => i.dqxq && i.nd !== nd)
updateSemester({ ...target, dqxq: true }).then(() => {
// 若存在原当前学期,一并取消
if (others.length) {
return Promise.all(others.map(o => updateSemester({ ...o, dqxq: false })))
}
return Promise.resolve()
}).then(() => {
this.activeSemester = target
this.$message.success(`已切换至:${this.getSemesterName(nd)}`)
// 重新拉取,同步最新 dqxq 状态
this.getSemesterList()
// 通知学期管理页面自动刷新
this.$root.$emit('semester-current-changed')
}).catch(() => {
this.$message.error('切换学期失败,请稍后重试')
})
}
}
}
</script>
<style scoped lang="scss">
.semester-bar {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
height: 36px;
font-size: 13px;
color: rgba(255, 255, 255, 0.85);
user-select: none;
&__item {
display: flex;
align-items: center;
justify-content: center;
height: 36px;
padding: 0 16px;
border-radius: 18px;
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.22);
backdrop-filter: blur(2px);
box-sizing: border-box;
i {
color: #fff;
margin-right: 7px;
font-size: 15px;
display: flex;
align-items: center;
height: 100%;
}
.label,
.value,
.week,
.date {
display: flex;
align-items: center;
height: 100%;
white-space: nowrap;
}
.label {
color: rgba(255, 255, 255, 0.75);
margin-right: 6px;
}
.value {
font-weight: 600;
color: #fff;
}
.date {
margin-left: 10px;
font-size: 12px;
color: rgba(255, 255, 255, 0.75);
letter-spacing: 0.5px;
padding-left: 10px;
border-left: 1px solid rgba(255, 255, 255, 0.25);
}
.week {
margin-left: 8px;
color: rgba(255, 255, 255, 0.75);
}
}
&__current {
margin-right: 0;
}
&__date {
margin-right: 0;
}
/* 胶囊式布局后不再需要分隔线 */
&__divider {
display: none;
}
&__switch {
background: transparent;
border: none;
padding: 0;
border-radius: 0;
height: 36px;
/* 用一层定高 flex 容器包裹 select,彻底隔离其默认行高外溢 */
.semester-select-wrap {
display: flex;
align-items: center;
height: 36px;
}
.semester-select {
width: 200px;
}
/* 关闭 select/input 外层默认行高,交给 flex 居中 */
::v-deep .el-select,
::v-deep .el-input {
height: 36px;
line-height: normal;
}
::v-deep .el-input__inner {
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.35);
color: #fff;
border-radius: 18px;
height: 36px;
padding: 0 12px;
display: flex;
align-items: center;
&::placeholder {
color: rgba(255, 255, 255, 0.7);
}
}
::v-deep .el-input__inner:hover {
border-color: rgba(255, 255, 255, 0.6);
}
::v-deep .el-input__icon {
color: rgba(255, 255, 255, 0.85);
}
}
}
</style>