|
@@ -1,9 +1,53 @@
|
|
<template>
|
|
<template>
|
|
<div class="h-full bg-white">
|
|
<div class="h-full bg-white">
|
|
- <n-space>
|
|
|
|
- <n-button type="primary" @click="pageState = !pageState"> 新增排课 </n-button>
|
|
|
|
- </n-space>
|
|
|
|
- <div v-if="pageState">
|
|
|
|
|
|
+ <div v-if="pageState" style="margin-top: 1rem">
|
|
|
|
+ <n-form inline>
|
|
|
|
+ <n-form-item label="请选择查询学员" path="user.name">
|
|
|
|
+ <n-input placeholder="请选择查询学员" />
|
|
|
|
+ </n-form-item>
|
|
|
|
+ <n-form-item label="请选择要查询的班级" path="classId">
|
|
|
|
+ <n-select
|
|
|
|
+ v-model:value="scheduleParamsOptions.classId"
|
|
|
|
+ :options="groupList"
|
|
|
|
+ clearable
|
|
|
|
+ placeholder="请选择班级"
|
|
|
|
+ />
|
|
|
|
+ </n-form-item>
|
|
|
|
+ <n-form-item label="请选择要查询的时间范围" path="user.name">
|
|
|
|
+ <n-date-picker
|
|
|
|
+ v-model:value="dateRange"
|
|
|
|
+ type="daterange"
|
|
|
|
+ clearable
|
|
|
|
+ time-zone="Asia/Shanghai"
|
|
|
|
+ placeholder="请选择时间范围"
|
|
|
|
+ :on-confirm="differenceInSevenDays"
|
|
|
|
+ :on-clear="
|
|
|
|
+ () => {
|
|
|
|
+ scheduleParamsOptions.startTime = '';
|
|
|
|
+ scheduleParamsOptions.endTime = '';
|
|
|
|
+ }
|
|
|
|
+ "
|
|
|
|
+ />
|
|
|
|
+ </n-form-item>
|
|
|
|
+ <n-form-item label="请选择要查询的授课教师" path="user.name">
|
|
|
|
+ <n-select
|
|
|
|
+ v-model:value="scheduleParamsOptions.teacherId"
|
|
|
|
+ :options="teacherOptions"
|
|
|
|
+ placeholder="请选择授课教师"
|
|
|
|
+ clearable
|
|
|
|
+ />
|
|
|
|
+ </n-form-item>
|
|
|
|
+ <n-form-item>
|
|
|
|
+ <n-button-group>
|
|
|
|
+ <n-button type="primary" ghost> 上一周 </n-button>
|
|
|
|
+ <n-button type="primary" ghost> 下一周 </n-button>
|
|
|
|
+ <n-button type="primary" ghost @click="loadScheduleQuery"> 搜索 </n-button>
|
|
|
|
+ <n-button type="primary" @click="pageState = !pageState"> 新增排课 </n-button>
|
|
|
|
+ </n-button-group>
|
|
|
|
+ </n-form-item>
|
|
|
|
+ </n-form>
|
|
|
|
+ <div style="width: 100%; height: 1rem"></div>
|
|
|
|
+ <div style="width: 100%; height: 1rem"></div>
|
|
<table border="1" style="width: 100%">
|
|
<table border="1" style="width: 100%">
|
|
<tbody width="100">
|
|
<tbody width="100">
|
|
<tr>
|
|
<tr>
|
|
@@ -20,13 +64,17 @@
|
|
<td>{{ key }}</td>
|
|
<td>{{ key }}</td>
|
|
<template v-for="index in [1, 2, 3, 4, 5, 6, 7]" :key="index">
|
|
<template v-for="index in [1, 2, 3, 4, 5, 6, 7]" :key="index">
|
|
<td
|
|
<td
|
|
- v-if="scheduleList[index][key]['empty'] === false && scheduleList[index][key]['break'] === false"
|
|
|
|
|
|
+ v-if="
|
|
|
|
+ scheduleList[index][key] &&
|
|
|
|
+ scheduleList[index][key]['empty'] === false &&
|
|
|
|
+ scheduleList[index][key]['break'] === false
|
|
|
|
+ "
|
|
:rowspan="scheduleList[index][key]['colspan']"
|
|
:rowspan="scheduleList[index][key]['colspan']"
|
|
>
|
|
>
|
|
{{ scheduleList[index][key]['startTime'] }} <br />
|
|
{{ scheduleList[index][key]['startTime'] }} <br />
|
|
{{ scheduleList[index][key]['endTime'] }}
|
|
{{ scheduleList[index][key]['endTime'] }}
|
|
</td>
|
|
</td>
|
|
- <td v-else-if="scheduleList[index][key]['empty'] === true">暂无</td>
|
|
|
|
|
|
+ <td v-else-if="scheduleList[index][key] && scheduleList[index][key]['empty'] === true">暂无</td>
|
|
</template>
|
|
</template>
|
|
</tr>
|
|
</tr>
|
|
</tbody>
|
|
</tbody>
|
|
@@ -41,25 +89,14 @@
|
|
<n-select v-model:value="model.roomId" :options="classRoomList" />
|
|
<n-select v-model:value="model.roomId" :options="classRoomList" />
|
|
</n-form-item>
|
|
</n-form-item>
|
|
<n-form-item label="任课老师" path="teacherId">
|
|
<n-form-item label="任课老师" path="teacherId">
|
|
- <n-select
|
|
|
|
- v-model:value="model.teacherId"
|
|
|
|
- placeholder="请选择任课老师"
|
|
|
|
- :options="teacherOptions"
|
|
|
|
- filterable
|
|
|
|
- clearable
|
|
|
|
- remote
|
|
|
|
- @search="teacherSearch"
|
|
|
|
- />
|
|
|
|
|
|
+ <n-select v-model:value="model.teacherId" placeholder="请选择任课老师" :options="teacherOptions" clearable />
|
|
</n-form-item>
|
|
</n-form-item>
|
|
<n-form-item label="助教老师" path="multipleSelectValue">
|
|
<n-form-item label="助教老师" path="multipleSelectValue">
|
|
<n-select
|
|
<n-select
|
|
v-model:value="model.assistantId"
|
|
v-model:value="model.assistantId"
|
|
placeholder="请选择助教老师"
|
|
placeholder="请选择助教老师"
|
|
- :options="generalOptions"
|
|
|
|
- filterable
|
|
|
|
|
|
+ :options="teacherOptions"
|
|
clearable
|
|
clearable
|
|
- remote
|
|
|
|
- @search="assistantSearch"
|
|
|
|
/>
|
|
/>
|
|
</n-form-item>
|
|
</n-form-item>
|
|
<n-form-item label="教授科目" path="multipleSelectValue">
|
|
<n-form-item label="教授科目" path="multipleSelectValue">
|
|
@@ -90,10 +127,14 @@
|
|
<n-input-number v-model:value="model.lessonTime" />
|
|
<n-input-number v-model:value="model.lessonTime" />
|
|
</n-form-item>
|
|
</n-form-item>
|
|
<div style="display: flex; justify-content: flex-end">
|
|
<div style="display: flex; justify-content: flex-end">
|
|
- <n-button type="primary" @click="handleValidateButtonClick"> 确认提交 </n-button>
|
|
|
|
|
|
+ <n-button-group>
|
|
|
|
+ <n-button type="primary" @click="handleValidateButtonClick"> 确认提交 </n-button>
|
|
|
|
+ <n-button type="primary" @click="pageState = !pageState"> 返回前一页 </n-button>
|
|
|
|
+ </n-button-group>
|
|
</div>
|
|
</div>
|
|
</n-form>
|
|
</n-form>
|
|
</div>
|
|
</div>
|
|
|
|
+ <div style="width: 100%; height: 1rem"></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
@@ -102,7 +143,7 @@ import { useRoute } from 'vue-router';
|
|
import type { CascaderOption } from 'naive-ui';
|
|
import type { CascaderOption } from 'naive-ui';
|
|
import { formatTimestamp } from '~/src/utils';
|
|
import { formatTimestamp } from '~/src/utils';
|
|
import {
|
|
import {
|
|
- queryByRealname,
|
|
|
|
|
|
+ queryUserAll,
|
|
queryCategoryParams,
|
|
queryCategoryParams,
|
|
querySubject,
|
|
querySubject,
|
|
queryClassAll,
|
|
queryClassAll,
|
|
@@ -110,18 +151,18 @@ import {
|
|
queryClassRoomList,
|
|
queryClassRoomList,
|
|
querySchedule
|
|
querySchedule
|
|
} from './api';
|
|
} from './api';
|
|
-import type { ScheduleParams } from './api';
|
|
|
|
|
|
+import type { ScheduleParams, ScheduleParamsList } from './api';
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
const model = reactive<ScheduleParams>({
|
|
const model = reactive<ScheduleParams>({
|
|
week: 0,
|
|
week: 0,
|
|
startTime: 0,
|
|
startTime: 0,
|
|
endTime: 0,
|
|
endTime: 0,
|
|
- roomId: 0,
|
|
|
|
- classId: 0,
|
|
|
|
- assistantId: 0,
|
|
|
|
- teacherId: 0,
|
|
|
|
- categoryId: 0,
|
|
|
|
- subjectsId: 0,
|
|
|
|
|
|
+ roomId: null,
|
|
|
|
+ classId: null,
|
|
|
|
+ assistantId: null,
|
|
|
|
+ teacherId: null,
|
|
|
|
+ categoryId: null,
|
|
|
|
+ subjectsId: null,
|
|
createTime: 0,
|
|
createTime: 0,
|
|
modifyTime: 0,
|
|
modifyTime: 0,
|
|
createUid: 0,
|
|
createUid: 0,
|
|
@@ -138,7 +179,17 @@ const categoryAndSubjectOptions = ref<any[]>([]);
|
|
const groupList = ref<any[]>([]);
|
|
const groupList = ref<any[]>([]);
|
|
const classRoomList = ref<any[]>([]);
|
|
const classRoomList = ref<any[]>([]);
|
|
const teacherOptions = ref();
|
|
const teacherOptions = ref();
|
|
-const generalOptions = ref();
|
|
|
|
|
|
+const dateRange = ref<[number, number]>([new Date().getTime(), new Date().getTime() + 86400000]);
|
|
|
|
+const scheduleParamsOptions = reactive<ScheduleParamsList>({
|
|
|
|
+ startTime: '',
|
|
|
|
+ endTime: '',
|
|
|
|
+ roomId: null,
|
|
|
|
+ classId: null,
|
|
|
|
+ assistantId: null,
|
|
|
|
+ teacherId: null,
|
|
|
|
+ categoryId: null,
|
|
|
|
+ subjectsId: null
|
|
|
|
+});
|
|
|
|
|
|
const scheduleList = ref<{ [index: string]: any }>({
|
|
const scheduleList = ref<{ [index: string]: any }>({
|
|
'1': {},
|
|
'1': {},
|
|
@@ -167,42 +218,6 @@ const timeKey = ref<string[]>([
|
|
'22:00',
|
|
'22:00',
|
|
'23:00'
|
|
'23:00'
|
|
]);
|
|
]);
|
|
-for (let i = 1; i <= 7; i += 1) {
|
|
|
|
- scheduleList.value[i] = {};
|
|
|
|
- for (let j = 0; j < timeKey.value.length; j += 1) {
|
|
|
|
- scheduleList.value[i][timeKey.value[j]] = { empty: true, break: false };
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-function teacherSearch(keyword: string) {
|
|
|
|
- if (keyword.length <= 0 || !keyword.length) {
|
|
|
|
- teacherOptions.value = [];
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- queryByRealname(keyword).then(respone => {
|
|
|
|
- teacherOptions.value = respone.data?.map(r => {
|
|
|
|
- return {
|
|
|
|
- label: r.relname,
|
|
|
|
- value: r.id
|
|
|
|
- };
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-function assistantSearch(keyword: string) {
|
|
|
|
- if (keyword.length <= 0 || !keyword.length) {
|
|
|
|
- generalOptions.value = [];
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- queryByRealname(keyword).then(respone => {
|
|
|
|
- generalOptions.value = respone.data?.map(r => {
|
|
|
|
- return {
|
|
|
|
- label: r.relname,
|
|
|
|
- value: r.id
|
|
|
|
- };
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
-}
|
|
|
|
|
|
|
|
function categoryAndSubjectLoad(option: CascaderOption) {
|
|
function categoryAndSubjectLoad(option: CascaderOption) {
|
|
model.categoryId = option.value as number;
|
|
model.categoryId = option.value as number;
|
|
@@ -237,9 +252,67 @@ async function handleValidateButtonClick() {
|
|
return window.$message?.success('操作成功!');
|
|
return window.$message?.success('操作成功!');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function differenceInSevenDays(nowtime: number | [number, number] | null) {
|
|
|
|
+ if (!nowtime) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (nowtime instanceof Array) {
|
|
|
|
+ const differenceInMilliseconds: number = nowtime[1] - nowtime[0] + 86400000;
|
|
|
|
+ const days = Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24));
|
|
|
|
+ if (days > 7) {
|
|
|
|
+ scheduleParamsOptions.startTime = '';
|
|
|
|
+ scheduleParamsOptions.endTime = '';
|
|
|
|
+ window.$message?.error('查询时间范围不能超过7天');
|
|
|
|
+ } else {
|
|
|
|
+ scheduleParamsOptions.startTime = formatTimestamp(Number(nowtime[1]));
|
|
|
|
+ scheduleParamsOptions.endTime = formatTimestamp(Number(nowtime[0] + 86400000));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function loadScheduleQuery() {
|
|
|
|
+ loadSchedule();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function loadSchedule() {
|
|
|
|
+ querySchedule(1, 100, scheduleParamsOptions).then(response => {
|
|
|
|
+ scheduleList.value = [];
|
|
|
|
+ for (let i = 1; i <= 7; i += 1) {
|
|
|
|
+ scheduleList.value[i] = {};
|
|
|
|
+ for (let j = 0; j < timeKey.value.length; j += 1) {
|
|
|
|
+ scheduleList.value[i][timeKey.value[j]] = { empty: true, break: false };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ response.data?.data.forEach(r => {
|
|
|
|
+ const time = r.startTime?.split(' ').pop();
|
|
|
|
+ const week = r.week;
|
|
|
|
+ if (week && time && r.endTime && r.startTime && scheduleList.value[week][time].empty) {
|
|
|
|
+ r.colspan = new Date(r.endTime).getHours() - new Date(r.startTime).getHours() + 1;
|
|
|
|
+ r.empty = false;
|
|
|
|
+ r.break = false;
|
|
|
|
+ scheduleList.value[week][time] = r;
|
|
|
|
+ let n = 1;
|
|
|
|
+ while (n < r.colspan) {
|
|
|
|
+ const index = timeKey.value.indexOf(time) + n;
|
|
|
|
+ scheduleList.value[week][timeKey.value[index]] = { empty: false, break: true };
|
|
|
|
+ n += 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
function loadData() {
|
|
function loadData() {
|
|
- queryCategoryParams(1, 100, {}).then(respone => {
|
|
|
|
- respone.data?.map(r => {
|
|
|
|
|
|
+ queryUserAll().then(response => {
|
|
|
|
+ teacherOptions.value = response.data?.map(r => {
|
|
|
|
+ return {
|
|
|
|
+ label: r.relname,
|
|
|
|
+ value: r.id
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ queryCategoryParams(1, 100, {}).then(response => {
|
|
|
|
+ response.data?.map(r => {
|
|
categoryAndSubjectOptions.value.push({
|
|
categoryAndSubjectOptions.value.push({
|
|
label: r.name,
|
|
label: r.name,
|
|
value: r.id,
|
|
value: r.id,
|
|
@@ -249,8 +322,8 @@ function loadData() {
|
|
return r;
|
|
return r;
|
|
});
|
|
});
|
|
});
|
|
});
|
|
- queryClassAll().then(respone => {
|
|
|
|
- respone.data?.map(r => {
|
|
|
|
|
|
+ queryClassAll().then(response => {
|
|
|
|
+ response.data?.map(r => {
|
|
groupList.value.push({
|
|
groupList.value.push({
|
|
label: r.name,
|
|
label: r.name,
|
|
value: r.id
|
|
value: r.id
|
|
@@ -258,9 +331,8 @@ function loadData() {
|
|
return r;
|
|
return r;
|
|
});
|
|
});
|
|
});
|
|
});
|
|
-
|
|
|
|
- queryClassRoomList(1, 100, {}).then(respone => {
|
|
|
|
- respone.data?.map(r => {
|
|
|
|
|
|
+ queryClassRoomList(1, 100, {}).then(response => {
|
|
|
|
+ response.data?.map(r => {
|
|
classRoomList.value.push({
|
|
classRoomList.value.push({
|
|
label: r.name,
|
|
label: r.name,
|
|
value: r.id
|
|
value: r.id
|
|
@@ -271,24 +343,7 @@ function loadData() {
|
|
model.classId = Number(classId);
|
|
model.classId = Number(classId);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
- querySchedule(1, 100, {}).then(response => {
|
|
|
|
- response.data?.data.forEach(r => {
|
|
|
|
- const time = r.startTime?.split(' ').pop();
|
|
|
|
- const week = r.week;
|
|
|
|
- if (week && time && r.endTime && r.startTime && scheduleList.value[week][time].empty) {
|
|
|
|
- r.colspan = new Date(r.endTime).getHours() - new Date(r.startTime).getHours() + 1;
|
|
|
|
- r.empty = false;
|
|
|
|
- r.break = false;
|
|
|
|
- scheduleList.value[week][time] = r;
|
|
|
|
- let n = 1;
|
|
|
|
- while (n < r.colspan) {
|
|
|
|
- const index = timeKey.value.indexOf(time) + n;
|
|
|
|
- scheduleList.value[week][timeKey.value[index]] = { empty: false, break: true };
|
|
|
|
- n += 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
|
|
+ loadSchedule();
|
|
}
|
|
}
|
|
|
|
|
|
loadData();
|
|
loadData();
|