feat: 初始化仓库

This commit is contained in:
2024-11-11 11:08:47 +08:00
commit 1809b49e6b
90 changed files with 24491 additions and 0 deletions

View File

@@ -0,0 +1,310 @@
<script setup lang="ts">
import { onShow } from '@dcloudio/uni-app'
import FullCalendar from '@fullcalendar/vue3'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from '@fullcalendar/interaction'
import listPlugin from '@fullcalendar/list'
import dayjs from 'dayjs'
import { onMounted, ref } from 'vue'
import type {
CalendarOptions,
} from '@fullcalendar/core'
import cusSelects from '~/components/cus-selects-fan.vue'
import { usePageStore } from '~/stores/modules/page'
import { useAppStore } from '~/stores/modules/app'
import { type BuildInfo, type ClassroomCourseInfo, type ClassroomInfo, getBuildListAPI, getClassroomCourseListAPI, getClassroomListAPI } from '~/services/course'
const { startDate, campusList, campusId, buildId, classroomId } = storeToRefs(useAppStore())
const { setPageConfig } = usePageStore()
onShow(() => {
setPageConfig({
showNavBar: true,
pageTitle: '教室课表',
showBackAction: true,
})
})
// #ifdef H5
const campus = ref('')
const buildList = ref<BuildInfo[]>([])
const classroomList = ref<ClassroomInfo[]>([])
const getClassroomList = async () => {
if (buildId.value) {
uni.showLoading({ title: '加载中~' })
const res = await getClassroomListAPI(buildId.value)
if (res.code === 200)
classroomList.value = res.data
uni.hideLoading()
uni.showToast({ icon: res.code === 200 ? 'success' : 'error', title: res.msg })
}
}
const getBuildList = async () => {
if (campusId.value) {
uni.showLoading({ title: '加载中~' })
const res = await getBuildListAPI(campus.value)
if (res.code === 200)
buildList.value = res.data
uni.hideLoading()
uni.showToast({ icon: res.code === 200 ? 'success' : 'error', title: res.msg })
}
}
const onCampusSelectChange = async (e: string) => {
campus.value = e
await getBuildList()
}
const onBuildSelectChange = async (e: string) => {
buildId.value = e
await getClassroomList()
}
/** 当前事件列表 */
const currentEvents = ref([])
/** 日历对象 */
const fullCalendar = ref()
const courseList = ref<ClassroomCourseInfo[]>([])
const getClassroomCourses = async () => {
const startTime = dayjs(startDate.value).unix()
// const start = dayjs(fullCalendar.value.getApi().view.activeStart).unix()
const endTime = dayjs(fullCalendar.value.getApi().view.activeEnd).unix()
const week = Math.floor((endTime - startTime) / (60 * 60 * 24 * 7))
if (classroomId.value) {
const res = await getClassroomCourseListAPI(classroomId.value, week)
if (res.code === 200) {
courseList.value = res.data
if (res.data) {
fullCalendar.value.getApi().removeAllEvents() // 清除所有事件
currentEvents.value = courseList.value.map(data => ({
id: data.id,
title: `${data.course} - ${data.teacher}`,
start: data.startTime.replace('T', ' ').replace('Z', ''),
end: data.endTime.replace('T', ' ').replace('Z', ''),
extendedProps: {
classnames: data.classnames,
campus: data.campus,
build: data.build,
},
}))
fullCalendar.value.getApi().addEventSource(currentEvents.value) // 添加新的事件源
}
}
fullCalendar.value.getApi().render() // 手动刷新日历
}
}
const onClassroomSelectChange = async (e: string) => {
classroomId.value = e
await getClassroomCourses()
}
/** 自定义上周按钮点击事件 */
const preWeekCustomClick = async () => {
fullCalendar.value.getApi().prev() // 切换到上一周
await getClassroomCourses()
}
/** 自定义下周按钮点击事件 */
const nextWeekCustomClick = async () => {
fullCalendar.value.getApi().next()
await getClassroomCourses()
}
/** 日历组件属性 */
const calendarOptions = ref<CalendarOptions>({
// 插件
plugins: [
listPlugin, // 列表视图插件
timeGridPlugin, // 周视图和日视图插件
interactionPlugin, // 交互插件,支持点击事件
],
// 自定义按钮
customButtons: {
preWeekCustom: {
text: '上周',
click() {
preWeekCustomClick() // 点击调用 preWeekCustomClick 函数
},
},
nextWeekCustom: {
text: '下周',
click() {
nextWeekCustomClick() // 点击调用 nextWeekCustomClick 函数
},
},
},
/** 修改headerToolbar */
headerToolbar: {
left: 'preWeekCustom',
center: 'title', // 显示日历标题
right: 'nextWeekCustom',
},
dayHeaderFormat: {
weekday: 'short', // 显示周几,如"周日"
month: '2-digit', // 显示两位数的月份
day: '2-digit', // 显示两位数的日期
omitCommas: true, // 去除逗号
},
/** 设置日历高度 */
contentHeight: uni.getWindowInfo().windowHeight - 260, // 动态计算高度
timeZone: 'Asia/Shanghai',
/** 默认视图 (月:dayGridMonth,周:timeGridWeek,日:timeGridDay) */
initialView: 'timeGridWeek', // 默认显示周视图
firstDay: 1, // 一周的第一天0表示星期天1表示星期一
slotMinTime: '08:00', // 最小时间段08:00
slotMaxTime: '22:10', // 最大时间段22:10
slotDuration: '00:05', // 时间间隔5分钟
slotLabelFormat: {
hour: '2-digit',
minute: '2-digit',
omitZeroMinute: false, // 忽略零分钟
hour12: false, // 24小时制
meridiem: 'short',
},
eventTimeFormat: {
hour: '2-digit',
minute: '2-digit',
hour12: false, // 24小时制
},
eventColor: '#3BB2E3', // 全部日历日程背景色
themeSystem: 'bootstrap', // 主题色(本地测试未能生效)
events: currentEvents.value, // 事件列表
editable: false, // 是否可以拖动修改事件
allDaySlot: false, // 是否显示全天事件区域
nowIndicator: true, // 是否显示当前时间线
selectable: true, // 是否可以选择时间段
selectMirror: true, // 是否在选择时间段时显示虚影
handleWindowResize: true, // 是否在窗口大小变化时调整日历
navLinks: false, // 是否可以通过点击日期导航
fixedWeekCount: true, // 每月显示固定周数
showNonCurrentDates: true, // 是否显示非当前月的日期
dayMaxEvents: true, // 每天最大事件数,超过则显示更多按钮
weekends: true, // 是否显示周末
/** 切换语言 */
locale: 'zh-cn', // 语言设置为简体中文
buttonText: {
today: '今天',
week: '周视图',
day: '日',
list: '周列表',
},
})
onMounted(async () => {
campus.value = campusId.value
await getBuildList()
await getClassroomList()
await getClassroomCourses()
fullCalendar.value.getApi().render()
})
// #endif
</script>
<template>
<!-- #ifdef H5 -->
<UBasePage>
<view class="query-select">
<view class="query-select-item">
<view class="query-select-item-left">
<uni-icons type="map" color="#A0E2AA" size="24" />
<text>校区</text>
</view>
<view>
<cus-selects
:value="campus"
filterable
:data="campusList"
:value-type="{ label: 'name', value: 'id' }"
placeholder="请选择校区~"
style="width: 100%"
@change="onCampusSelectChange"
/>
</view>
</view>
<view class="query-select-item">
<view class="query-select-item-left">
<uni-icons type="home" color="#F9BD56" size="24" />
<text>教学楼</text>
</view>
<view>
<cus-selects
:value="buildId"
filterable
:data="buildList"
:value-type="{ label: 'name', value: 'id' }"
placeholder="请选择教学楼~"
style="width: 100%"
@change="onBuildSelectChange"
/>
</view>
</view>
<view class="query-select-item">
<view class="query-select-item-left">
<uni-icons type="location" color="#FEC2BF" size="24" />
<text>教室</text>
</view>
<view>
<cus-selects
:value="classroomId"
filterable
:data="classroomList"
:value-type="{ label: 'name', value: 'id' }"
placeholder="请选择教室~"
style="width: 100%"
@change="onClassroomSelectChange"
/>
</view>
</view>
</view>
<FullCalendar ref="fullCalendar" :options="calendarOptions">
<template #eventContent="arg">
<view class="calender-content">
{{ arg.timeText }}
</view>
<view class="calender-content">
{{ arg.event.title }}
</view>
<view class="calender-content">
上课班级数量: {{ arg.event.extendedProps.classnames.length }}
</view>
</template>
</FullCalendar>
</UBasePage>
<!-- #endif -->
<!-- #ifndef H5 -->
<web-view src="/hybrid/html/calender.html" :fullscreen="false" style="width: 100%; height: 500px;" />
<!-- #endif -->
</template>
<style lang="scss">
.query-select{
padding: 10rpx 20rpx;
background-image: linear-gradient(-225deg, #FFFEFF 0%, #D7FFFE 100%);
.query-select-item{
border-bottom: 2rpx solid #e9e9e9;
padding: 10rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
.query-select-item-left {
width: 30%;
text {
margin-left: 5rpx;
color: #29a1f7;
}
}
}
}
.calender-content{
text-align: center;
}
:deep(.fc .fc-toolbar-title){
font-size: 30rpx;
}
:deep(.fc){
font-size: 26rpx;
}
:deep(.fc .fc-toolbar.fc-header-toolbar){
margin-bottom: 10rpx;
}
</style>