index.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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. showDialog,
  11. showToast,
  12. Tab,
  13. Tabs,
  14. Tag
  15. } from 'vant'
  16. import { defineComponent, onMounted, reactive, ref, nextTick } 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. import ODialog from '@/components/o-dialog'
  26. export default defineComponent({
  27. name: 'course-preview',
  28. setup() {
  29. // SAME_SCHOOL_TEACHER("同学校老师课程冲突"),
  30. // DIFF_SCHOOL_TEACHER("不同学校老师课程冲突"),
  31. // STUDENT("学生课程冲突"),
  32. // LEAVE 请假冲突
  33. const route = useRoute()
  34. const router = useRouter()
  35. const state = reactive({
  36. type: route.query.type,
  37. conflictStatus: false,
  38. conflictMessage: '该时间段伴学指导在其他学校有课',
  39. tabValue: '',
  40. courseValue: '',
  41. selectClasses: [] as any, // 选中的班级列表
  42. selectCourse: [] as any, // 选中的课程
  43. choiceCourse: {}, // 选中需要调整的课程
  44. isClick: false,
  45. dialogStatus: false,
  46. dialogMessage: ''
  47. })
  48. const courseTabsRef: any = ref()
  49. // 获取所有
  50. const getClasses = async (loading = true) => {
  51. try {
  52. const res = await request.post('/api-school/orchestra/trainingPlanListCache', {
  53. requestType: 'form',
  54. // hideLoading: !loading,
  55. data: {
  56. cacheId: route.query.cacheId
  57. }
  58. })
  59. if (res.code === 999) {
  60. state.dialogStatus = true
  61. state.dialogMessage = res.message
  62. return
  63. }
  64. // 初始化数据
  65. formatClasses(res.data)
  66. if (forms.planList.orchestra.length > 0) {
  67. const selectOrchestra = forms.selectOrchestraId
  68. ? { orchestraId: forms.selectOrchestraId }
  69. : forms.planList.orchestra[0]
  70. state.tabValue = selectOrchestra.orchestraId
  71. // console.log(forms.selectClassGroupId, forms.planList.classes[selectOrchestra.orchestraId])
  72. const selectClasses = forms.selectClassGroupId
  73. ? { classGroupId: forms.selectClassGroupId }
  74. : forms.planList.classes[selectOrchestra.orchestraId]
  75. ? forms.planList.classes[selectOrchestra.orchestraId][0]
  76. : {}
  77. state.selectClasses = forms.planList.classes[selectOrchestra.orchestraId] || []
  78. state.selectCourse = forms.planList.course[selectClasses.classGroupId]
  79. state.courseValue = selectClasses.classGroupId
  80. // console.log(selectClasses.classGroupId, 'selectClasses.classGroupId')
  81. // 判断是否有数据
  82. forms.selectOrchestraId = null
  83. forms.selectClassGroupId = null
  84. // console.log(selectClasses.classGroupId, 'selectClasses.classGroupId 333333')
  85. }
  86. } catch {
  87. //
  88. }
  89. }
  90. // 格式化班级数据
  91. const formatClasses = async (data: any) => {
  92. // 判断是否有班级编号,如果有就说明接口只会返回该班的数据
  93. // if (forms.selectClassGroupId) {
  94. // forms.planList.course[forms.selectClassGroupId] = data || []
  95. // return
  96. // }
  97. // 初始化乐团
  98. const orchestra: any = []
  99. data.forEach((item: any) => {
  100. const index = orchestra.findIndex((o: any) => o.orchestraId === item.orchestraId)
  101. // 判断是否已经添加过
  102. if (index === -1) {
  103. orchestra.push({
  104. orchestraId: item.orchestraId,
  105. orchestraName: item.orchestraName
  106. })
  107. }
  108. })
  109. // 初始化班级
  110. const classes: any = {}
  111. orchestra.forEach((item: any) => {
  112. data.forEach((child: any) => {
  113. // 判断是否是同一个乐团
  114. if (item.orchestraId === child.orchestraId) {
  115. const classInOrchestra = classes[item.orchestraId]
  116. // // 判断是否已经存在乐团数据
  117. if (classInOrchestra) {
  118. const index = classInOrchestra.findIndex(
  119. (c: any) => c.classGroupId === child.classGroupId
  120. )
  121. if (index === -1) {
  122. classes[item.orchestraId].push({
  123. classGroupId: child.classGroupId,
  124. className: child.className
  125. })
  126. }
  127. } else {
  128. classes[item.orchestraId] = [
  129. {
  130. classGroupId: child.classGroupId,
  131. className: child.className
  132. }
  133. ]
  134. }
  135. }
  136. })
  137. })
  138. // 初始化课程数据
  139. const course: any = {}
  140. for (const item in classes) {
  141. const oList = classes[item] || []
  142. oList.forEach((child: any) => {
  143. const courseList = data.filter((d: any) => d.classGroupId === child.classGroupId)
  144. course[child.classGroupId] = courseList
  145. })
  146. }
  147. forms.planList = {
  148. orchestra,
  149. classes,
  150. course
  151. }
  152. }
  153. const onChoiceCourse = (course: any) => {
  154. forms.selectOrchestraId = state.tabValue || null
  155. forms.selectClassGroupId = state.courseValue || null
  156. router.push({
  157. path: '/course-adjust',
  158. query: {
  159. id: course.id,
  160. cacheId: route.query.cacheId
  161. }
  162. })
  163. }
  164. const onSubmit = async () => {
  165. try {
  166. state.isClick = true
  167. const res = await request.post(
  168. '/api-school/orchestra/trainingPlan/' + route.query.cacheId,
  169. { hideLoading: false }
  170. )
  171. // 判断数据是否已经过期
  172. if (res.code === 999) {
  173. // showDialog({
  174. // title: '提示',
  175. // message: res.message,
  176. // confirmButtonColor: '#ff8057'
  177. // }).then(() => {
  178. // // 原生班级调整伴学指导时
  179. // // if (state.type === 'native') {
  180. // // postMessage({ api: 'back', content: {} })
  181. // // } else {
  182. // router.back()
  183. // // }
  184. // })
  185. state.dialogStatus = true
  186. state.dialogMessage = res.message
  187. return
  188. }
  189. // setTimeout(() => {
  190. // showToast(state.type === 'change' || state.type === 'native' ? '调整成功' : '排课成功')
  191. // }, 100)
  192. // setTimeout(() => {
  193. state.isClick = false
  194. // 伴学指导交接
  195. if (route.query.type === 'unbind') {
  196. router.replace('/companion-teacher')
  197. } else {
  198. postMessage({ api: 'back', content: {} })
  199. }
  200. // }, 1100)
  201. } catch {
  202. //
  203. state.isClick = false
  204. getClasses(false)
  205. // setTimeout(() => {
  206. // }, 1100)
  207. }
  208. }
  209. onMounted(() => {
  210. getClasses()
  211. })
  212. return () => (
  213. <div class={styles.coursePreview}>
  214. <OSticky position="top">
  215. <OHeader border={false} />
  216. <Tabs
  217. lineWidth={20}
  218. lineHeight={4}
  219. v-model:active={state.tabValue}
  220. swipeThreshold={3}
  221. class={styles.orchestraTabs}
  222. onChange={(val: any) => {
  223. console.log(val, 'val', state.tabValue)
  224. // 乐团变化时
  225. if (!forms.selectClassGroupId) {
  226. state.selectClasses = forms.planList.classes[val] || []
  227. const selectClasses = forms.planList.classes[val]
  228. ? forms.planList.classes[val][0]
  229. : {}
  230. state.selectCourse = forms.planList.course[selectClasses.classGroupId]
  231. state.courseValue = selectClasses.classGroupId
  232. }
  233. }}
  234. >
  235. {forms.planList.orchestra.map((item: any) => (
  236. <Tab title={item.orchestraName} name={item.orchestraId}></Tab>
  237. ))}
  238. </Tabs>
  239. <div class={styles.courseTabsContainer}>
  240. {state.courseValue && (
  241. <Tabs
  242. swipeThreshold={3}
  243. class={styles.courseTabs}
  244. v-model:active={state.courseValue}
  245. lineHeight={0}
  246. shrink
  247. ref={courseTabsRef}
  248. onChange={(val: any) => {
  249. state.selectCourse = forms.planList.course[val]
  250. }}
  251. >
  252. {state.selectClasses.map((item: any) => (
  253. <Tab title={item.className} name={item.classGroupId}></Tab>
  254. ))}
  255. </Tabs>
  256. )}
  257. </div>
  258. </OSticky>
  259. {state.selectCourse.map((item: any) => (
  260. <CellGroup inset class={styles.cellGroup}>
  261. <Cell center class={styles.cellDatetime}>
  262. {{
  263. title: () => (
  264. <div class={styles.cellDate}>
  265. <Icon name={iconTimer} class={styles.iconTimer} />
  266. {dayjs(item.classDate).format('YYYY-MM-DD')}
  267. </div>
  268. ),
  269. value: () => <span class={styles.cellTime}>{item.singleCourseTime}分钟</span>
  270. }}
  271. </Cell>
  272. <div
  273. class={[
  274. styles.cellTimeRange,
  275. item.conflictType && item.conflictType.length > 0 && styles.conflictType
  276. ]}
  277. >
  278. {dayjs(item.startTime).format('HH:mm')}-{dayjs(item.endTime).format('HH:mm')}
  279. </div>
  280. <Cell center class={styles.cellTeacher} border={false}>
  281. {{
  282. icon: () => (
  283. <Image src={item.teacherAvatar || iconTeacher} class={styles.img} fit="cover" />
  284. ),
  285. title: () => (
  286. <div class={styles.teacherInfo}>
  287. <p class={[styles.teacherName, 'van-ellipsis']}>{item.teacherName}</p>
  288. <Tag
  289. color="#FFE3DA"
  290. textColor="#F67146"
  291. style={{ fontWeight: '500', padding: '1px 6px' }}
  292. >
  293. {item.className}
  294. </Tag>
  295. </div>
  296. ),
  297. value: () => (
  298. <Button
  299. round
  300. plain
  301. type="primary"
  302. class={styles.btn}
  303. onClick={() => onChoiceCourse(item)}
  304. >
  305. 调整
  306. </Button>
  307. )
  308. }}
  309. </Cell>
  310. <Cell center border={false} class={[styles.cellTeacher, styles.conflictGrouop]}>
  311. {{
  312. title: () => (
  313. <>
  314. {item.conflictType && item.conflictType.includes('STUDENT') && (
  315. <Tag
  316. class={styles.conflict}
  317. color="#F44541"
  318. size="large"
  319. onClick={() => {
  320. state.conflictMessage = '学生时间冲突'
  321. state.conflictStatus = true
  322. state.choiceCourse = item
  323. }}
  324. >
  325. 学生冲突
  326. </Tag>
  327. )}
  328. {item.conflictType && item.conflictType.includes('DIFF_SCHOOL_TEACHER') && (
  329. <Tag
  330. class={styles.conflict}
  331. color="#F44541"
  332. size="large"
  333. onClick={() => {
  334. state.conflictMessage = '该时间段伴学指导在其他学校有课'
  335. state.conflictStatus = true
  336. state.choiceCourse = item
  337. }}
  338. >
  339. 学校冲突
  340. </Tag>
  341. )}
  342. {item.conflictType && item.conflictType.includes('SAME_SCHOOL_TEACHER') && (
  343. <Tag
  344. class={styles.conflict}
  345. color="#ff8057"
  346. size="large"
  347. onClick={() => {
  348. state.conflictMessage = '伴学指导在本学校时间有冲突'
  349. state.conflictStatus = true
  350. state.choiceCourse = item
  351. }}
  352. >
  353. 老师冲突
  354. </Tag>
  355. )}
  356. {item.conflictType && item.conflictType.includes('LEAVE') && (
  357. <Tag
  358. class={styles.conflict}
  359. color="#F44541"
  360. size="large"
  361. onClick={() => {
  362. state.conflictMessage = '伴学指导请假冲突'
  363. state.conflictStatus = true
  364. state.choiceCourse = item
  365. }}
  366. >
  367. 老师请假
  368. </Tag>
  369. )}
  370. </>
  371. )
  372. }}
  373. </Cell>
  374. </CellGroup>
  375. ))}
  376. <OSticky position="bottom">
  377. <div class={'btnGroup'}>
  378. <Button round block type="primary" onClick={onSubmit} disabled={state.isClick}>
  379. {state.type === 'change' || state.type === 'native' ? '确认调整' : '确认排课'}
  380. </Button>
  381. </div>
  382. </OSticky>
  383. {/* <Dialog
  384. v-model:show={state.conflictStatus}
  385. message={state.conflictMessage}
  386. messageAlign="center"
  387. confirmButtonText="去调整"
  388. cancelButtonText="知道了"
  389. showCancelButton
  390. onConfirm={() => {
  391. state.conflictStatus = false
  392. onChoiceCourse(state.choiceCourse)
  393. }}
  394. >
  395. {{
  396. title: () => (
  397. <div class={styles.dialogTitle}>
  398. <i></i>
  399. 课程冲突
  400. </div>
  401. )
  402. }}
  403. </Dialog> */}
  404. <ODialog
  405. title="课程冲突"
  406. message={state.conflictMessage}
  407. v-model:show={state.conflictStatus}
  408. messageAlign="center"
  409. confirmButtonText="去调整"
  410. cancelButtonText="知道了"
  411. showCancelButton
  412. onConfirm={() => {
  413. state.conflictStatus = false
  414. onChoiceCourse(state.choiceCourse)
  415. }}
  416. />
  417. <ODialog
  418. title="提示"
  419. v-model:show={state.dialogStatus}
  420. message={state.dialogMessage}
  421. confirmButtonText="确定"
  422. onConfirm={() => {
  423. router.back()
  424. }}
  425. />
  426. </div>
  427. )
  428. }
  429. })