calendar.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <template>
  2. <BasicModal
  3. :destroyOnClose="true"
  4. :maskClosable="false"
  5. v-bind="$attrs"
  6. @register="registerModal"
  7. title="我的课表"
  8. :width="1002"
  9. :footer="null"
  10. :default-fullscreen="true"
  11. >
  12. <div class="h-full">
  13. <div style="height: 34px">
  14. <div class="flex justify-end">
  15. <div>
  16. <div v-if="state.type === '1'">
  17. <span class="mr-2">周次</span>
  18. <Select
  19. v-model:value="state.week"
  20. @change="handelWeekChange"
  21. :options="state.weekList"
  22. style="width: 180px"
  23. placeholder="请选择周次"
  24. />
  25. </div>
  26. <div v-else>
  27. <span class="mr-2">日期</span>
  28. <DatePicker
  29. v-model:value="dataValue"
  30. @change="handelDateChange"
  31. style="width: 180px"
  32. />
  33. </div>
  34. </div>
  35. <div class="ml-4">
  36. <Radio.Group v-model:value="state.type" buttonStyle="solid" @change="handelTypeChange">
  37. <Radio.Button value="1">周视图</Radio.Button>
  38. <Radio.Button value="2">月视图</Radio.Button>
  39. </Radio.Group>
  40. </div>
  41. </div>
  42. </div>
  43. <div style="height: calc(100vh - 34px)">
  44. <BasicTable @register="registerTable" v-show="state.type === '1'" />
  45. <Calendar v-model:value="dataValue" @panelChange="handelChange" v-show="state.type === '2'">
  46. <template #headerRender></template>
  47. <template #dateCellRender="{ current }">
  48. <div class="c-item" v-for="(item, index) in getListData(current)" :key="index">
  49. <div class="flex justify-between items-center">
  50. <div class="flex">
  51. <div>
  52. {{ item.timeNumber }}
  53. </div>
  54. <div class="c-item-time">
  55. {{ item.time }}
  56. </div>
  57. </div>
  58. <Tag color="green" style="font-size: 10px"> {{ item.className }}</Tag>
  59. </div>
  60. <div class="flex justify-between mt-1">
  61. <div>
  62. {{ item.courseName }}
  63. </div>
  64. </div>
  65. </div>
  66. </template>
  67. </Calendar>
  68. </div>
  69. </div>
  70. </BasicModal>
  71. </template>
  72. <script setup lang="ts">
  73. import { ref, unref, reactive, onMounted } from 'vue';
  74. import { Calendar, Tag, Radio, DatePicker, Select } from 'ant-design-vue';
  75. import { BasicModal, useModalInner } from '/@/components/Modal';
  76. import { Dayjs } from 'dayjs';
  77. import { dateUtil, formatToDate } from '/@/utils/dateUtil';
  78. import {
  79. getScheduleCourseTable,
  80. getScheduleCurrentWeek,
  81. getScheduleWeekList,
  82. } from '/@/services/apis/ScheduleController';
  83. import { BasicOptionModel } from '/@/api/model/baseModel';
  84. import { BasicTable, useTable } from '/@/components/Table';
  85. import { tableColumns } from '/@/views/educational/timetable/data.config';
  86. import { orderBy } from 'lodash-es';
  87. const modelDataRef = ref<Recordable[]>([]);
  88. const dataValue = ref<Dayjs>();
  89. const timePeriods = ['', '上午', '下午', '晚上', ''];
  90. defineEmits(['success', 'register']);
  91. const state = reactive({
  92. type: '1',
  93. week: '',
  94. semesterId: '',
  95. weekList: [],
  96. });
  97. const reloadApi = async () => {
  98. const resData = await getScheduleCourseTable({
  99. week: state.week,
  100. });
  101. const { classTimeList, courseList } = resData;
  102. const timePeriods = ['', '上午', '下午', '晚上', ''];
  103. const displayData: Recordable[] = [];
  104. let timePeriod = -1;
  105. orderBy(classTimeList, ['timePeriod', 'number'], ['asc', 'asc']).forEach((item) => {
  106. let rowSpan = 0;
  107. if (timePeriod !== item.timePeriod) {
  108. timePeriod = item.timePeriod;
  109. rowSpan = classTimeList.filter((row) => row.timePeriod === timePeriod).length;
  110. }
  111. const getWeekObj = (weeks) => {
  112. const weekFilter = courseList.filter(
  113. (row) =>
  114. Number(row.timePeriod) === item.timePeriod &&
  115. Number(row.timeNumber) === item.number &&
  116. row.weeks === weeks,
  117. );
  118. if (weekFilter && weekFilter.length > 0) {
  119. return {
  120. siteName: weekFilter[0].classroomName || '-',
  121. courseName: weekFilter[0].courseName || '-',
  122. name: weekFilter[0].className || '1',
  123. };
  124. } else {
  125. return {};
  126. }
  127. };
  128. let displayItem: Recordable = {
  129. rowSpan: rowSpan,
  130. timePeriod: timePeriods[item.timePeriod],
  131. timeNumber: {
  132. title: `${item.shortName}`,
  133. time: `${item.summerStartTime}-${item.summerEndTime}`,
  134. },
  135. week1: getWeekObj(1),
  136. week2: getWeekObj(2),
  137. week3: getWeekObj(3),
  138. week4: getWeekObj(4),
  139. week5: getWeekObj(5),
  140. week6: getWeekObj(6),
  141. week7: getWeekObj(7),
  142. };
  143. displayData.push(displayItem);
  144. });
  145. return displayData;
  146. };
  147. const [registerTable, { reload }] = useTable({
  148. api: reloadApi,
  149. title: '',
  150. rowKey: 'id',
  151. columns: tableColumns,
  152. useSearchForm: false,
  153. showTableSetting: false,
  154. bordered: true,
  155. immediate: false,
  156. canResize: true,
  157. showIndexColumn: false,
  158. pagination: false,
  159. });
  160. const [registerModal, { setModalProps }] = useModalInner(async () => {
  161. dataValue.value = dateUtil(new Date());
  162. reload();
  163. await getPageData(dataValue.value);
  164. });
  165. const getPageData = async (value) => {
  166. setModalProps({ confirmLoading: true });
  167. const startDate = dateUtil(value).startOf('month').format('YYYY-MM-DD') + ' 00:00:00';
  168. const endDate = dateUtil(value).endOf('month').format('YYYY-MM-DD') + ' 23:59:59';
  169. modelDataRef.value = await getScheduleCourseTable({
  170. startDate: startDate,
  171. endDate: endDate,
  172. });
  173. setModalProps({ confirmLoading: false });
  174. };
  175. const handelChange = async (value: Dayjs) => {
  176. await getPageData(value);
  177. };
  178. const handelTypeChange = async () => {};
  179. const handelDateChange = async () => {
  180. await getPageData(dataValue.value);
  181. };
  182. const handelWeekChange = async () => {
  183. await reload();
  184. };
  185. const getWeeks = async () => {
  186. const data = await getScheduleWeekList({});
  187. state.weekList = data.map((item) => {
  188. return {
  189. label: `${item.weekCn}(${formatToDate(item.startDate, 'MM.DD')}~${formatToDate(
  190. item.endDate,
  191. 'MM.DD',
  192. )})`,
  193. value: item.week,
  194. };
  195. });
  196. };
  197. const getListData = (value: Dayjs) => {
  198. const current = formatToDate(value);
  199. const { classTimeList = [], courseList = [] } = unref(modelDataRef);
  200. const itemFilter = courseList.filter((item) => item.scheduleDate === current);
  201. const tabList: Recordable[] = [];
  202. itemFilter.forEach((item) => {
  203. const classTimeFilter = classTimeList.filter(
  204. (row) =>
  205. row.timePeriod === Number(item.timePeriod) && row.number === Number(item.timeNumber),
  206. );
  207. const classTimeItem = classTimeFilter.length > 0 ? classTimeFilter[0] : {};
  208. tabList.push({
  209. className: item.className,
  210. classroomName: item.classroomName || '-',
  211. courseName: item.courseName,
  212. timePeriod: timePeriods[Number(item.timePeriod)],
  213. timeNumber: `${classTimeItem.shortName}`,
  214. time: `${classTimeItem?.summerStartTime}~${classTimeItem?.summerEndTime}`,
  215. });
  216. });
  217. return tabList;
  218. };
  219. onMounted(async () => {
  220. state.week = await getScheduleCurrentWeek({});
  221. await getWeeks();
  222. });
  223. </script>
  224. <style scoped lang="less">
  225. .c-item {
  226. border-radius: 6px;
  227. background: linear-gradient(135deg, rgb(247, 248, 251) 0%, rgb(247, 248, 251) 100%);
  228. padding: 4px;
  229. margin-bottom: 4px;
  230. color: rgb(127, 127, 128);
  231. font-size: 10px;
  232. &:last-child {
  233. margin-bottom: 0;
  234. }
  235. &-time {
  236. color: rgb(22, 100, 255);
  237. }
  238. &-tag {
  239. border-radius: 8px;
  240. background: rgb(22, 100, 255);
  241. color: #fff;
  242. padding: 2px 6px;
  243. }
  244. }
  245. </style>