index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. import Calendar from '@/business-components/calendar'
  2. import request from '@/helpers/request'
  3. import { state } from '@/state'
  4. import Arrange from '@/teacher/live-class/create-components/arrange'
  5. import dayjs from 'dayjs'
  6. import {
  7. computed,
  8. defineComponent,
  9. nextTick,
  10. onMounted,
  11. reactive,
  12. ref,
  13. watch
  14. } from 'vue'
  15. import styles from './index.module.less'
  16. import { params as classInfo } from '../class-info'
  17. import { Button, Cell, Dialog, Popup, Sticky, Tag, Toast } from 'vant'
  18. import { getWeekCh } from '@/helpers/utils'
  19. import { useRouter } from 'vue-router'
  20. import CourseSchedule from '../course-schedule'
  21. export default defineComponent({
  22. name: 'createClass',
  23. props: {
  24. active: {
  25. type: Number,
  26. default: 1
  27. },
  28. onBack: {
  29. type: Function,
  30. default: () => () => ({})
  31. }
  32. },
  33. setup(props) {
  34. watch(
  35. () => props.active,
  36. val => {
  37. // console.log(val)
  38. if (val === 2) {
  39. getList()
  40. }
  41. }
  42. )
  43. //日期设置
  44. const data = reactive({
  45. calendarList: {},
  46. selectList: []
  47. })
  48. const getList = async (date?: Date) => {
  49. const tempDate = date || dayjs().add(1, 'day').toDate()
  50. const params = {
  51. day: dayjs(tempDate).format('DD'),
  52. month: dayjs(tempDate).format('MM'),
  53. year: dayjs(tempDate).format('YYYY')
  54. }
  55. try {
  56. const res = await request.post(
  57. '/api-teacher/courseSchedule/createLiveCourseCalendar',
  58. {
  59. data: {
  60. ...params,
  61. singleCourseMinutes: classInfo.singleClassTime,
  62. freeCourseMinutes: classInfo.freeCourseMinutes,
  63. teacherId: state.user.data?.userId
  64. }
  65. }
  66. )
  67. const result = res.data || []
  68. const tempObj = {}
  69. result.forEach((item: any) => {
  70. tempObj[item.date] = item
  71. })
  72. data.calendarList = tempObj
  73. } catch {
  74. //
  75. }
  76. }
  77. const onSelectDay = (res: any) => {
  78. // 对数组进行排序
  79. res.sort((first: any, second: any) => {
  80. if (first.startTime > second.startTime) return 1
  81. if (first.startTime < second.startTime) return -1
  82. return 0
  83. })
  84. data.selectList = res
  85. }
  86. const showSelectList = computed(() => {
  87. // 显示时间
  88. const list = [...data.selectList]
  89. list.forEach((item: any) => {
  90. item.title =
  91. dayjs(item.startTime).format('YYYY-MM-DD') +
  92. ' ' +
  93. getWeekCh(dayjs(item.startTime).day()) +
  94. ' ' +
  95. item.start +
  96. '~' +
  97. item.end
  98. })
  99. return list
  100. })
  101. const selectType = computed(() => {
  102. // 循环次数是否足够
  103. return data.selectList.length < classInfo.classNum ? 'noEnough' : 'enough'
  104. })
  105. const onCloseTag = (item: any) => {
  106. // 删除课程
  107. Dialog.confirm({
  108. title: '提示',
  109. message: '您是否要删除该选择的课程?',
  110. confirmButtonColor: 'var(--van-primary)'
  111. }).then(() => {
  112. const index = data.selectList.findIndex(
  113. (course: any) => course.startTime === item.startTime
  114. )
  115. data.selectList.splice(index, 1)
  116. })
  117. }
  118. const selectStatus = ref(false)
  119. const onSubmit = async () => {
  120. if (data.selectList.length <= 0) {
  121. Toast('请选择课程时间')
  122. return
  123. }
  124. if (data.selectList.length < classInfo.classNum) {
  125. selectStatus.value = true
  126. return
  127. }
  128. // await this._lookCourse()
  129. confirmShow.value = true
  130. }
  131. const onComfirm = async () => {
  132. if (selectType.value === 'noEnough') {
  133. const times = [] as any
  134. data.selectList.forEach((item: any) => {
  135. times.push({
  136. startTime: item.startTime,
  137. endTime: item.endTime
  138. })
  139. })
  140. console.log(data.selectList)
  141. const res = await request.post(
  142. '/api-teacher/courseGroup/lockCourseToCache',
  143. {
  144. data: {
  145. courseNum: classInfo.classNum,
  146. courseType: 'PIANO_ROOM_CLASS',
  147. loop: 1,
  148. teacherId: state.user.data?.userId,
  149. timeList: [...times]
  150. }
  151. }
  152. )
  153. if (res.code === 200) {
  154. res.data.forEach((n: any) => {
  155. n.start = dayjs(n.startTime).format('HH:mm')
  156. n.end = dayjs(n.endTime).format('HH:mm')
  157. })
  158. data.selectList = res.data
  159. }
  160. } else {
  161. selectStatus.value = false
  162. nextTick(() => {
  163. confirmShow.value = true
  164. })
  165. }
  166. }
  167. const router = useRouter()
  168. const confirmShow = ref(false)
  169. // 排课
  170. const onCourseSchedule = async () => {
  171. const timeList = data.selectList
  172. const n = classInfo.studentIds.length
  173. try {
  174. const { code, data } = await request.post(
  175. '/api-teacher/courseSchedule/arrangeCourse',
  176. {
  177. data: {
  178. classNum: classInfo.classNum, //课时数
  179. consumeTime: Math.ceil(
  180. n * classInfo.classNum * parseInt(classInfo.singleClassTime)
  181. ), //消耗时长
  182. courseName: classInfo.courseName, //课程名称
  183. singleClssTime: classInfo.singleClassTime, //单课时长
  184. studentIds: classInfo.studentIds.map(n => n.userId), //学员id集合
  185. subjectId: classInfo.subjectId, //声部id
  186. timeList
  187. }
  188. }
  189. )
  190. if (code === 200) {
  191. confirmShow.value = false
  192. if (data) {
  193. setTimeout(() => {
  194. Toast({
  195. message: data,
  196. duration: 1500,
  197. onClose: () => {
  198. router.back()
  199. }
  200. })
  201. }, 100)
  202. } else {
  203. setTimeout(() => {
  204. Toast({
  205. icon: 'success',
  206. message: '排课成功',
  207. duration: 1500,
  208. onClose: () => {
  209. router.back()
  210. }
  211. })
  212. }, 100)
  213. }
  214. }
  215. } catch (error) {
  216. //
  217. }
  218. }
  219. return () => {
  220. return (
  221. <div class={styles.createClass}>
  222. {props.active === 2 && (
  223. <Calendar
  224. maxDays={classInfo.classNum}
  225. list={data.calendarList}
  226. prevMonth={(date: Date) => getList(date)}
  227. nextMonth={(date: Date) => getList(date)}
  228. selectDay={onSelectDay}
  229. selectList={data.selectList}
  230. isSkipHolidays={classInfo.isSkipHolidays}
  231. />
  232. )}
  233. <Cell
  234. class={[styles.arrangeCell, 'mb12']}
  235. v-slots={{
  236. title: () => (
  237. <div class={styles.rTitle}>
  238. <span>已选择课程时间</span>
  239. </div>
  240. ),
  241. label: () => (
  242. <div class={styles.rTag}>
  243. {showSelectList.value.map((item: any) => (
  244. <>
  245. <Tag
  246. plain
  247. round
  248. closeable
  249. size="large"
  250. type="primary"
  251. class={styles.tag}
  252. onClose={() => onCloseTag(item)}
  253. >
  254. {item.title}
  255. </Tag>
  256. <br />
  257. </>
  258. ))}
  259. </div>
  260. )
  261. }}
  262. ></Cell>
  263. <Sticky offsetBottom={0} position="bottom">
  264. <div class={['btnGroup', 'btnMore']}>
  265. <Button
  266. block
  267. round
  268. type="primary"
  269. plain
  270. onClick={() => {
  271. props.onBack && props.onBack()
  272. // 重置选择的课次
  273. data.selectList = []
  274. }}
  275. >
  276. 上一步
  277. </Button>
  278. <Button block round type="primary" onClick={() => onSubmit()}>
  279. 下一步
  280. </Button>
  281. </div>
  282. </Sticky>
  283. {/* <Arrange /> */}
  284. <Popup show={selectStatus.value} class={styles.selectPopup}>
  285. <div class={styles.selectContainer}>
  286. <div class={styles.rTitle}>
  287. <span>提示</span>
  288. </div>
  289. <div class={styles.selectPopupContent}>
  290. <p class={styles.desc}>
  291. {selectType.value === 'noEnough'
  292. ? '您所选择的上课时间未达到您输入的课时数,系统根据已选时间将自动按周顺延排课。'
  293. : '您已选择以下上课时间段,时间段会暂时锁定,锁定期间学员不可购买该时间段课程。'}
  294. </p>
  295. {selectType.value === 'enough' && (
  296. <p class={styles.times}>
  297. {data.selectList.map((item: any) => (
  298. <span>
  299. {dayjs(item.startTime || new Date()).format(
  300. 'YYYY-MM-DD'
  301. )}{' '}
  302. {dayjs(item.startTime || new Date()).format('HH:mm')}~
  303. {dayjs(item.endTime || new Date()).format('HH:mm')}
  304. </span>
  305. ))}
  306. </p>
  307. )}
  308. </div>
  309. <div class={styles.selectBtn}>
  310. <Button
  311. class={styles.btn}
  312. type="primary"
  313. round
  314. block
  315. plain
  316. onClick={() => (selectStatus.value = false)}
  317. >
  318. {selectType.value === 'noEnough' ? '继续选择' : '重新选择'}
  319. </Button>
  320. <Button
  321. class={styles.btn}
  322. type="primary"
  323. round
  324. block
  325. onClick={() => onComfirm()}
  326. >
  327. 确认
  328. </Button>
  329. </div>
  330. </div>
  331. </Popup>
  332. {/* 确认排课 */}
  333. <Popup
  334. position="bottom"
  335. class={styles.coursePopup}
  336. v-model:show={confirmShow.value}
  337. closeable
  338. round
  339. >
  340. <CourseSchedule
  341. curriculum={data.selectList}
  342. onClose={() => {
  343. confirmShow.value = false
  344. }}
  345. onComfirm={() => {
  346. onCourseSchedule()
  347. }}
  348. />
  349. </Popup>
  350. </div>
  351. )
  352. }
  353. }
  354. })