index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import OHeader from '@/components/o-header'
  2. import OSticky from '@/components/o-sticky'
  3. import {
  4. Button,
  5. Cell,
  6. CellGroup,
  7. Dialog,
  8. Icon,
  9. Image,
  10. showConfirmDialog,
  11. showToast,
  12. Tab,
  13. Tabs,
  14. Tag
  15. } from 'vant'
  16. import { defineComponent, onMounted, reactive } from 'vue'
  17. import styles from './index.module.less'
  18. import iconTimer from '../../images/icon-timer.png'
  19. import iconTeacher from '@common/images/icon_teacher.png'
  20. import { useRoute, useRouter } from 'vue-router'
  21. import request from '@/helpers/request'
  22. import dayjs from 'dayjs'
  23. import { forms } from '../../create'
  24. import { postMessage } from '@/helpers/native-message'
  25. export default defineComponent({
  26. name: 'course-preview',
  27. setup() {
  28. // SAME_SCHOOL_TEACHER("同学校老师课程冲突"),
  29. // DIFF_SCHOOL_TEACHER("不同学校老师课程冲突"),
  30. // STUDENT("学生课程冲突"),
  31. const route = useRoute()
  32. const router = useRouter()
  33. const state = reactive({
  34. conflictStatus: false,
  35. conflictMessage: '该时间段伴学指导在其他学校有课',
  36. tabValue: '',
  37. courseValue: '',
  38. selectClasses: [] as any, // 选中的班级列表
  39. selectCourse: [] as any, // 选中的课程
  40. choiceCourse: {}, // 选中需要调整的课程
  41. isClick: false
  42. })
  43. // 获取所有
  44. const getClasses = async () => {
  45. try {
  46. const { data } = await request.post('/api-school/orchestra/trainingPlanListCache', {
  47. requestType: 'form',
  48. data: {
  49. cacheId: route.query.cacheId,
  50. classGroupId: forms.selectClassGroupId || null
  51. }
  52. })
  53. // 初始化数据
  54. formatClasses(data)
  55. if (forms.planList.orchestra.length > 0) {
  56. const selectOrchestra = forms.selectOrchestraId
  57. ? { orchestraId: forms.selectOrchestraId }
  58. : forms.planList.orchestra[0]
  59. state.tabValue = selectOrchestra.orchestraId
  60. const selectClasses = forms.selectClassGroupId
  61. ? { classGroupId: forms.selectClassGroupId }
  62. : forms.planList.classes[selectOrchestra.orchestraId]
  63. ? forms.planList.classes[selectOrchestra.orchestraId][0]
  64. : {}
  65. state.selectClasses = forms.planList.classes[selectOrchestra.orchestraId] || []
  66. state.courseValue = selectClasses.classGroupId
  67. state.selectCourse = forms.planList.course[selectClasses.classGroupId]
  68. // 判断是否有数据
  69. forms.selectOrchestraId = null
  70. forms.selectClassGroupId = null
  71. }
  72. } catch {
  73. //
  74. }
  75. }
  76. // 格式化班级数据
  77. const formatClasses = async (data: any) => {
  78. // 判断是否有班级编号,如果有就说明接口只会返回该班的数据
  79. if (forms.selectClassGroupId) {
  80. forms.planList.classes[forms.selectClassGroupId] = data || []
  81. return
  82. }
  83. // 初始化乐团
  84. const orchestra: any = []
  85. data.forEach((item: any) => {
  86. const index = orchestra.findIndex((o: any) => o.orchestraId === item.orchestraId)
  87. // 判断是否已经添加过
  88. if (index === -1) {
  89. orchestra.push({
  90. orchestraId: item.orchestraId,
  91. orchestraName: item.orchestraName
  92. })
  93. }
  94. })
  95. // 初始化班级
  96. const classes: any = {}
  97. orchestra.forEach((item: any) => {
  98. data.forEach((child: any) => {
  99. // 判断是否是同一个乐团
  100. if (item.orchestraId === child.orchestraId) {
  101. const classInOrchestra = classes[item.orchestraId]
  102. // // 判断是否已经存在乐团数据
  103. if (classInOrchestra) {
  104. const index = classInOrchestra.findIndex(
  105. (c: any) => c.classGroupId === child.classGroupId
  106. )
  107. if (index === -1) {
  108. classes[item.orchestraId].push({
  109. classGroupId: child.classGroupId,
  110. className: child.className
  111. })
  112. }
  113. } else {
  114. classes[item.orchestraId] = [
  115. {
  116. classGroupId: child.classGroupId,
  117. className: child.className
  118. }
  119. ]
  120. }
  121. }
  122. })
  123. })
  124. // 初始化课程数据
  125. const course: any = {}
  126. for (const item in classes) {
  127. const oList = classes[item] || []
  128. oList.forEach((child: any) => {
  129. const courseList = data.filter((d: any) => d.classGroupId === child.classGroupId)
  130. course[child.classGroupId] = courseList
  131. })
  132. }
  133. forms.planList = {
  134. orchestra,
  135. classes,
  136. course
  137. }
  138. }
  139. const onChoiceCourse = (course: any) => {
  140. forms.selectOrchestraId = state.tabValue || null
  141. forms.selectClassGroupId = state.courseValue || null
  142. router.push({
  143. path: '/course-adjust',
  144. query: {
  145. id: course.id,
  146. cacheId: route.query.cacheId
  147. }
  148. })
  149. }
  150. const onSubmit = async () => {
  151. try {
  152. state.isClick = true
  153. await request.post('/api-school/orchestra/trainingPlan/' + route.query.cacheId)
  154. setTimeout(() => {
  155. showToast('排课成功')
  156. }, 100)
  157. setTimeout(() => {
  158. state.isClick = false
  159. postMessage({ api: 'back', content: {} })
  160. }, 1100)
  161. } catch {
  162. //
  163. state.isClick = false
  164. }
  165. }
  166. onMounted(() => {
  167. getClasses()
  168. })
  169. return () => (
  170. <div class={styles.coursePreview}>
  171. <OSticky position="top">
  172. <OHeader border={false} />
  173. <Tabs
  174. lineWidth={20}
  175. lineHeight={4}
  176. v-model:active={state.tabValue}
  177. swipeThreshold={3}
  178. class={styles.orchestraTabs}
  179. onChange={(val: any) => {
  180. // 乐团变化时
  181. state.selectClasses = forms.planList.classes[val] || []
  182. const selectClasses = forms.planList.classes[val]
  183. ? forms.planList.classes[val][0]
  184. : {}
  185. state.courseValue = selectClasses.classGroupId
  186. state.selectCourse = forms.planList.course[selectClasses.classGroupId]
  187. }}
  188. >
  189. {forms.planList.orchestra.map((item: any) => (
  190. <Tab title={item.orchestraName} name={item.orchestraId}></Tab>
  191. ))}
  192. </Tabs>
  193. <Tabs
  194. swipeThreshold={3}
  195. class={styles.courseTabs}
  196. v-model:active={state.courseValue}
  197. lineHeight={0}
  198. shrink
  199. onChange={(val: any) => {
  200. state.selectCourse = forms.planList.course[val]
  201. }}
  202. >
  203. {state.selectClasses.map((item: any) => (
  204. <Tab title={item.className} name={item.classGroupId}></Tab>
  205. ))}
  206. </Tabs>
  207. </OSticky>
  208. {state.selectCourse.map((item: any) => (
  209. <CellGroup inset class={styles.cellGroup}>
  210. <Cell center class={styles.cellDatetime}>
  211. {{
  212. title: () => (
  213. <div class={styles.cellDate}>
  214. <Icon name={iconTimer} class={styles.iconTimer} />
  215. {dayjs(item.classDate).format('YYYY-MM-DD')}
  216. </div>
  217. ),
  218. value: () => <span class={styles.cellTime}>{item.singleCourseTime}分钟</span>
  219. }}
  220. </Cell>
  221. <div class={styles.cellTimeRange}>
  222. {dayjs(item.startTime).format('HH:mm')}-{dayjs(item.endTime).format('HH:mm')}
  223. {item.conflictType && item.conflictType.includes('STUDENT') ? (
  224. <Tag
  225. class={styles.conflict}
  226. color="#F44541"
  227. onClick={() => {
  228. // conflictStatus: false,
  229. // conflictMessage: '该时间段伴学指导在其他学校有课',
  230. state.conflictMessage = '学生时间冲突'
  231. state.conflictStatus = true
  232. state.choiceCourse = item
  233. }}
  234. >
  235. 学生冲突
  236. </Tag>
  237. ) : (
  238. ''
  239. )}
  240. {(item.conflictType && item.conflictType.includes('DIFF_SCHOOL_TEACHER')) ||
  241. item.conflictType.includes('SAME_SCHOOL_TEACHER') ? (
  242. <Tag
  243. class={styles.conflict}
  244. color="#F44541"
  245. onClick={() => {
  246. const type = item.conflictType || []
  247. if (
  248. type.includes('DIFF_SCHOOL_TEACHER') &&
  249. type.includes('SAME_SCHOOL_TEACHER')
  250. ) {
  251. state.conflictMessage =
  252. '该时间段伴学指导在其他学校有课 \n 伴学指导在本学校时间有冲突'
  253. } else if (type.includes('DIFF_SCHOOL_TEACHER')) {
  254. state.conflictMessage = '该时间段伴学指导在其他学校有课'
  255. } else if (type.includes('SAME_SCHOOL_TEACHER')) {
  256. state.conflictMessage = '伴学指导在本学校时间有冲突'
  257. }
  258. state.conflictStatus = true
  259. state.choiceCourse = item
  260. }}
  261. >
  262. 学校冲突
  263. </Tag>
  264. ) : (
  265. ''
  266. )}
  267. </div>
  268. <Cell center class={styles.cellTeacher}>
  269. {{
  270. icon: () => <Image src={iconTeacher} class={styles.img} />,
  271. title: () => (
  272. <div class={styles.teacherInfo}>
  273. <p class={styles.teacherName}>{item.teacherName}</p>
  274. <Tag type="primary">{item.className}</Tag>
  275. </div>
  276. ),
  277. value: () => (
  278. <Button
  279. round
  280. plain
  281. type="primary"
  282. class={styles.btn}
  283. onClick={() => onChoiceCourse(item)}
  284. >
  285. 调整
  286. </Button>
  287. )
  288. }}
  289. </Cell>
  290. </CellGroup>
  291. ))}
  292. <OSticky position="bottom">
  293. <div class={'btnGroup'}>
  294. <Button
  295. round
  296. block
  297. type="primary"
  298. size="large"
  299. onClick={onSubmit}
  300. disabled={state.isClick}
  301. >
  302. 确认排课
  303. </Button>
  304. </div>
  305. </OSticky>
  306. <Dialog
  307. v-model:show={state.conflictStatus}
  308. message={state.conflictMessage}
  309. messageAlign="left"
  310. confirmButtonText="去调整"
  311. cancelButtonText="知道了"
  312. showCancelButton
  313. onConfirm={() => {
  314. state.conflictStatus = false
  315. onChoiceCourse(state.choiceCourse)
  316. }}
  317. >
  318. {{
  319. title: () => (
  320. <div class={styles.dialogTitle}>
  321. <i></i>
  322. 课程冲突
  323. </div>
  324. )
  325. }}
  326. </Dialog>
  327. </div>
  328. )
  329. }
  330. })