index.tsx 13 KB

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