index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <template>
  2. <PageWrapper dense contentFullHeight fixedHeight>
  3. <BasicTable @register="registerTable">
  4. <template #toolbar>
  5. <div style="display: flex; align-items: center; flex: 1">
  6. <div style="flex: 1; text-align: center; font-size: 14px; font-weight: bold">
  7. <span style="margin-right: 16px">{{ tableText.semesterName }}</span>
  8. <span style="margin-right: 16px">{{ tableText.name }}</span>
  9. <span style="margin-right: 16px">{{ tableText.week }}</span>
  10. <span>课程表</span>
  11. </div>
  12. <div style="margin-right: 16px"> 总课时:{{ tableText.classHour }}</div>
  13. <a-button type="primary" @click="handleExport()">导出</a-button>
  14. </div>
  15. </template>
  16. </BasicTable>
  17. </PageWrapper>
  18. </template>
  19. <script setup lang="ts">
  20. import { onMounted, ref, reactive } from 'vue';
  21. import { PageWrapper } from '/@/components/Page';
  22. import { BasicTable, useTable } from '/@/components/Table';
  23. import { tableColumns } from './data.config';
  24. import {
  25. getScheduleCourseTable,
  26. getScheduleWeekList,
  27. postScheduleScheduleWeekExportQuery,
  28. } from '/@/services/apis/ScheduleController';
  29. import { requestMagicApi } from '/@/api/magicApi';
  30. import { BasicOptionModel } from '/@/api/model/baseModel';
  31. import { orderBy } from 'lodash-es';
  32. import { downloadByData } from '/@/utils/file/download';
  33. import { formatToDate, formatToDateTime } from '/@/utils/dateUtil';
  34. const tableText = reactive({
  35. semesterName: '',
  36. name: '',
  37. week: '',
  38. classHour: '',
  39. });
  40. const reloadApi = async (data) => {
  41. const resData = await getScheduleCourseTable(data);
  42. const { classTimeList, courseList } = resData;
  43. const formData = getForm().getFieldsValue();
  44. tableText.semesterName = resData.semesterName;
  45. tableText.name = formData.courseType === 'teacher' ? resData.teacherName : resData.className;
  46. tableText.week = resData.week;
  47. tableText.classHour = resData.classHour;
  48. const timePeriods = ['', '上午', '下午', '晚上', ''];
  49. const displayData: Recordable[] = [];
  50. let timePeriod = -1;
  51. orderBy(classTimeList, ['timePeriod', 'number'], ['asc', 'asc']).forEach((item) => {
  52. let rowSpan = 0;
  53. if (timePeriod !== item.timePeriod) {
  54. timePeriod = item.timePeriod;
  55. rowSpan = classTimeList.filter((row) => row.timePeriod === timePeriod).length;
  56. }
  57. const getWeekObj = (weeks) => {
  58. const weekFilter = courseList.filter(
  59. (row) =>
  60. Number(row.timePeriod) === item.timePeriod &&
  61. Number(row.timeNumber) === item.number &&
  62. row.weeks === weeks,
  63. );
  64. if (weekFilter && weekFilter.length > 0) {
  65. return {
  66. siteName: weekFilter[0].classroomName || '-',
  67. courseName: weekFilter[0].courseName || '-',
  68. name:
  69. formData.courseType === 'teacher'
  70. ? weekFilter[0].className || '-'
  71. : weekFilter[0].teacherName || '-',
  72. };
  73. } else {
  74. return {};
  75. }
  76. };
  77. let displayItem: Recordable = {
  78. rowSpan: rowSpan,
  79. timePeriod: timePeriods[item.timePeriod],
  80. timeNumber: {
  81. title: `${item.shortName}`,
  82. time: `${item.summerStartTime}-${item.summerEndTime}`,
  83. },
  84. week1: getWeekObj(1),
  85. week2: getWeekObj(2),
  86. week3: getWeekObj(3),
  87. week4: getWeekObj(4),
  88. week5: getWeekObj(5),
  89. week6: getWeekObj(6),
  90. week7: getWeekObj(7),
  91. };
  92. displayData.push(displayItem);
  93. });
  94. return displayData;
  95. };
  96. const tabTitle = ref<string>('课表');
  97. const [registerTable, { getForm }] = useTable({
  98. api: reloadApi,
  99. title: tabTitle,
  100. rowKey: 'id',
  101. columns: tableColumns,
  102. formConfig: {
  103. labelWidth: 100,
  104. schemas: [
  105. {
  106. field: 'semesterId',
  107. label: '学期',
  108. component: 'ApiSelect',
  109. componentProps: {
  110. getPopupContainer: () => document.body,
  111. api: requestMagicApi,
  112. params: { url: 'baseData/semester/option' },
  113. },
  114. required: true,
  115. colProps: { span: 8 },
  116. },
  117. {
  118. field: 'courseType',
  119. label: '课表类型',
  120. component: 'Select',
  121. required: true,
  122. colProps: { span: 8 },
  123. componentProps: ({ formModel }) => {
  124. return {
  125. getPopupContainer: () => document.body,
  126. options: [
  127. { label: '教职工课表', value: 'teacher' },
  128. { label: '班级课表', value: 'class' },
  129. ],
  130. onChange: (value) => {
  131. formModel.teacherName = '';
  132. formModel.gradeId = '';
  133. formModel.majorSetId = '';
  134. formModel.classId = '';
  135. if (value === 'teacher') {
  136. tabTitle.value = '教职工课表';
  137. }
  138. if (value === 'class') {
  139. tabTitle.value = '班级课表';
  140. }
  141. },
  142. };
  143. },
  144. },
  145. {
  146. field: 'week',
  147. label: '周次',
  148. component: 'ApiSelect',
  149. required: true,
  150. colProps: { span: 8 },
  151. componentProps: {
  152. api: async () => {
  153. const data = await getScheduleWeekList({});
  154. return data.map((item) => {
  155. return {
  156. label: `${item.weekCn}(${formatToDate(item.startDate, 'MM.DD')}~${formatToDate(
  157. item.endDate,
  158. 'MM.DD',
  159. )})`,
  160. value: item.week,
  161. };
  162. });
  163. },
  164. getPopupContainer: () => document.body,
  165. },
  166. },
  167. {
  168. field: 'gradeId',
  169. label: '年级',
  170. component: 'ApiSelect',
  171. componentProps: ({ formActionType }) => {
  172. return {
  173. getPopupContainer: () => document.body,
  174. api: requestMagicApi,
  175. params: { url: 'baseData/grade/option' },
  176. showSearch: true,
  177. filterOption: (input: string, option: any) => {
  178. return (
  179. option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
  180. option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
  181. );
  182. },
  183. onChange: async (vlaue) => {
  184. const { getFieldsValue, updateSchema } = formActionType;
  185. const formData = getFieldsValue();
  186. const classData = await requestMagicApi({
  187. url: 'educational/class-by',
  188. query: { grade_id: vlaue, major_set_id: formData.majorSetId },
  189. } as any);
  190. updateSchema({
  191. field: 'classId',
  192. componentProps: {
  193. getPopupContainer: () => document.body,
  194. options: classData,
  195. },
  196. });
  197. },
  198. };
  199. },
  200. colProps: { span: 8 },
  201. ifShow: ({ values }) => {
  202. return values.courseType === 'class';
  203. },
  204. },
  205. {
  206. field: 'majorSetId',
  207. label: '专业',
  208. component: 'ApiSelect',
  209. required: true,
  210. componentProps: ({ formActionType }) => {
  211. return {
  212. getPopupContainer: () => document.body,
  213. api: requestMagicApi,
  214. params: { url: `/major/majorset/option` },
  215. showSearch: true,
  216. filterOption: (input: string, option: any) => {
  217. return (
  218. option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
  219. option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
  220. );
  221. },
  222. onChange: async (vlaue) => {
  223. const { getFieldsValue, updateSchema } = formActionType;
  224. const formData = getFieldsValue();
  225. const classData = await requestMagicApi({
  226. url: 'educational/class-by',
  227. query: { grade_id: formData.gradeId, major_set_id: vlaue },
  228. } as any);
  229. updateSchema({
  230. field: 'classId',
  231. componentProps: {
  232. getPopupContainer: () => document.body,
  233. options: classData,
  234. },
  235. });
  236. },
  237. };
  238. },
  239. colProps: { span: 8 },
  240. ifShow: ({ values }) => {
  241. return values.courseType === 'class';
  242. },
  243. },
  244. {
  245. field: 'classId',
  246. label: '班级',
  247. component: 'Select',
  248. componentProps: ({ formActionType }) => {
  249. const { getFieldsValue } = formActionType;
  250. const formData = getFieldsValue();
  251. return {
  252. api: requestMagicApi,
  253. getPopupContainer: () => document.body,
  254. params: {
  255. url: 'educational/class-by',
  256. query: { grade_id: formData.gradeId, major_set_id: formData.majorSetId },
  257. },
  258. showSearch: true,
  259. filterOption: (input: string, option: any) => {
  260. return (
  261. option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
  262. option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
  263. );
  264. },
  265. };
  266. },
  267. required: true,
  268. colProps: { span: 8 },
  269. ifShow: ({ values }) => {
  270. return values.courseType === 'class';
  271. },
  272. },
  273. {
  274. field: 'teacherName',
  275. label: '姓名/工号',
  276. component: 'Input',
  277. required: true,
  278. colProps: { span: 8 },
  279. ifShow: ({ values }) => {
  280. return values.courseType === 'teacher';
  281. },
  282. },
  283. ],
  284. },
  285. useSearchForm: true,
  286. showTableSetting: true,
  287. bordered: true,
  288. immediate: false,
  289. canResize: true,
  290. showIndexColumn: false,
  291. pagination: false,
  292. });
  293. const handleExport = async () => {
  294. const postData = getForm().getFieldsValue();
  295. const data = await postScheduleScheduleWeekExportQuery(postData);
  296. downloadByData(data.data, `周课表${formatToDateTime(new Date(), 'YYYYMMDDHHmmss')}.xlsx`);
  297. };
  298. onMounted(async () => {});
  299. </script>
  300. <style scoped lang="less"></style>