index.tsx 13 KB

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