123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- import Calendar from '@/business-components/calendar'
- import request from '@/helpers/request'
- import { state } from '@/state'
- import dayjs from 'dayjs'
- import {
- ActionSheet,
- Button,
- Cell,
- CellGroup,
- Dialog,
- Stepper,
- Sticky,
- Tag,
- Popup,
- Toast,
- Icon
- } from 'vant'
- import { defineComponent } from 'vue'
- import { getWeekCh } from '@/helpers/utils'
- import styles from './practice.module.less'
- import { orderStatus } from '@/views/order-detail/orderStatus'
- import ColResult from '@/components/col-result'
- import { tradeOrder } from '@/student/trade/tradeOrder'
- import icon3 from '../images/icon3.png'
- import Tips from './tips'
- export default defineComponent({
- name: 'VIP_COURSE',
- props: {
- userInfo: {
- type: Object,
- default: {}
- }
- },
- data() {
- const query = this.$route.query
- return {
- teacherId: query.teacherId,
- subjectId: query.subjectId,
- teacherSubjectList: [],
- subjectStatus: false,
- subjectInfo: {
- freeMinutes: 0,
- subjectPrice: 0,
- courseMinutes: 0,
- id: null,
- subjectName: '',
- subjectId: 0
- },
- courseNum: 4,
- calendarStatus: false,
- calendarList: [] as any,
- selectCourseList: [] as any,
- coursePlanStatus: false,
- selectStatus: false,
- coursePlanList: [] as any,
- calendarDate: dayjs().add(1, 'day').toDate() as Date, // 日历当前时间
- settingStatus: true, // 是否设置VIP定制课
- loadDataStatus: true // 是否加载数据
- }
- },
- async mounted() {
- try {
- this.loadDataStatus = true
- const res = await request.get(
- '/api-student/courseSchedule/getTeacherSubjectPrice',
- {
- params: {
- teacherId: this.teacherId,
- groupType: 'VIP'
- }
- }
- )
-
- const result = res.data || []
- if (result.length > 0) {
- const userSubjectId = this.subjectId || state.user.data?.subjectId
- const findItem = result.find((item: any) => {
- return item.subjectId === Number(userSubjectId)
- })
- // 判断是否有跟学生相同的科目,如果没有则默认取第一个
- const tempRes = findItem || result[0]
- const { subjectName, subjectPrice, courseMinutes, subjectId, id, freeMinutes } = tempRes
- this.subjectInfo = {
- subjectPrice,
- freeMinutes,
- id,
- courseMinutes,
- subjectName,
- subjectId
- }
- result.forEach((item: any) => {
- item.name = item.subjectName
- })
- this.teacherSubjectList = result
- this.getList()
- this.onBuy(true)
- this.settingStatus = true
- // 判断如果是审核的则不显示
- const resVersion = await request.post('/api-teacher/open/appVersion', {
- data: {
- platform:
- state.platformType === 'STUDENT' ? 'ios-student' : 'ios-teacher',
- version: state.version
- }
- })
- this.settingStatus = resVersion.data.check ? false : true
- } else {
- this.settingStatus = false
- }
-
- this.loadDataStatus = false
- } catch {
- this.loadDataStatus = false
- }
- },
- computed: {
- showSelectList() {
- const arr: any = this.selectCourseList
- let list = [...arr]
- list.forEach((item: any) => {
- item.title =
- dayjs(item.startTime).format('YYYY-MM-DD') +
- ' ' +
- getWeekCh(dayjs(item.startTime).day()) +
- ' ' +
- item.start +
- '~' +
- item.end
- })
- return list
- },
- selectType() {
- // 循环次数是否足够
- return this.selectCourseList.length < this.courseNum
- ? 'noEnough'
- : 'enough'
- }
- },
- methods: {
- async onSubmit() {
- if (this.selectCourseList.length <= 0) {
- Toast('请选择课程时间')
- return
- }
- if (this.selectCourseList.length < this.courseNum) {
- this.selectStatus = true
- return
- }
- await this._lookCourse()
- },
- async getList(date?: Date) {
- try {
- const tempDate = date || dayjs().add(1, 'day').toDate()
- let params = {
- day: dayjs(tempDate).format('DD'),
- month: dayjs(tempDate).format('MM'),
- year: dayjs(tempDate).format('YYYY')
- }
- let res = await request.post(
- '/api-student/courseSchedule/createPracticeCourseCalendar',
- {
- data: {
- ...params,
- teacherSubjectPriceId: this.subjectInfo.id,
- studentId: state.user.data?.userId,
- teacherId: this.teacherId
- }
- }
- )
- const result = res.data || []
- let tempObj = {}
- result.forEach((item: any) => {
- tempObj[item.date] = item
- })
- this.calendarList = tempObj
- this.calendarStatus = result.length > 0
- } catch {}
- },
- onSelectDay(obj: any) {
- const result = obj || []
- let list = [...this.selectCourseList] as any
- result.forEach((item: any) => {
- const isExist = list.some(
- (course: any) => course.startTime === item.startTime
- )
- !isExist && list.push({ ...item })
- })
- // 去掉不在
- let tempList: any[] = []
- list.forEach((item: any) => {
- const isExist = result.some(
- (course: any) => course.startTime === item.startTime
- )
- isExist && tempList.push(item)
- })
- // 对数组进行排序
- tempList.sort((first: any, second: any) => {
- if (first.startTime > second.startTime) return 1
- if (first.startTime < second.startTime) return -1
- return 0
- })
- console.log(tempList, 'list')
- this.selectCourseList = [...tempList] as any
- },
- onCloseTag(item: any) {
- Dialog.confirm({
- title: '提示',
- message: '您是否要删除该选择的课程?',
- confirmButtonColor: 'var(--van-primary)'
- }).then(() => {
- const index = this.selectCourseList.findIndex(
- (course: any) => course.startTime === item.startTime
- )
- this.selectCourseList.splice(index, 1)
- })
- },
- async _lookCourse(callBack?: Function) {
- try {
- let times = [] as any
- this.selectCourseList.forEach((item: any) => {
- times.push({
- startTime: item.startTime,
- endTime: item.endTime
- })
- })
- const res = await request.post(
- '/api-student/courseGroup/lockCourseToCache',
- {
- data: {
- courseFreeMinutes: this.subjectInfo.freeMinutes,
- courseNum: this.courseNum,
- courseType: 'VIP',
- loop: this.selectType === 'noEnough' ? 1 : 0,
- teacherId: this.teacherId,
- timeList: [...times]
- }
- }
- )
- const result = res.data || []
- result.forEach((item: any, index: number) => {
- this.coursePlanList[index] = {
- ...this.coursePlanList[index],
- startTime: item.startTime,
- endTime: item.endTime,
- classNum: index + 1
- }
- })
- this.coursePlanStatus = true
- this.selectStatus = true
- callBack && callBack()
- } catch (e: any) {
- // 报错时需要重置日历表的数据
- const message = e.message
- Dialog.alert({
- title: '提示',
- confirmButtonColor: 'var(--van-primary)',
- message
- }).then(() => {
- this.getList(this.calendarDate || new Date())
- this.selectCourseList = []
- this.selectStatus = false
- })
- }
- },
- async onReset() {
- // 是否有锁课状态 或 是锁课类型的
- if (this.coursePlanStatus || this.selectType === 'enough') {
- this.selectStatus = false
- setTimeout(() => {
- this.coursePlanList = []
- }, 500)
- } else if (this.selectType === 'noEnough') {
- this.selectStatus = false
- }
- setTimeout(() => {
- this.coursePlanStatus = false
- }, 500)
- },
- async onSure() {
- const status = this.coursePlanStatus
- await this._lookCourse(() => {
- if (status) {
- this.selectStatus = false
- this.onBuy()
- }
- })
- },
- async onBuy(goTo?: boolean) {
- try {
- const res = await request.post(
- '/api-student/userOrder/getPendingOrder',
- {
- data: {
- goodType: 'VIP_COURSE',
- bizId: this.teacherId
- }
- }
- )
- const subjectInfo = this.subjectInfo
- const tempCourseList = [...this.coursePlanList]
- // console.log(this.coursePlanList)
- tempCourseList.forEach((item: any) => {
- item.classDate = dayjs(item.startTime).format('YYYY-MM-DD')
- item.title = `${dayjs(item.startTime).format(
- 'YYYY-MM-DD'
- )} ${getWeekCh(dayjs(item.startTime).day())} ${dayjs(
- item.startTime
- ).format('HH:mm')}~${dayjs(item.endTime).format('HH:mm')}`
- })
- orderStatus.orderObject.orderType = 'VIP_COURSE'
- orderStatus.orderObject.orderName = subjectInfo.subjectName + 'VIP定制课'
- orderStatus.orderObject.orderDesc = subjectInfo.subjectName + 'VIP定制课'
- orderStatus.orderObject.actualPrice = Number(
- (this.courseNum * subjectInfo.subjectPrice).toFixed(2)
- )
- orderStatus.orderObject.orderNo = ''
- orderStatus.orderObject.orderList = [
- {
- orderType: 'VIP_COURSE',
- goodsName: subjectInfo.subjectName + 'VIP定制课',
- courseGroupName: subjectInfo.subjectName + 'VIP定制课',
- courseIntroduce: subjectInfo.subjectName + 'VIP定制课',
- subjectId: subjectInfo.subjectId,
- singleCourseMinutes: subjectInfo.courseMinutes,
- teacherSubjectPriceId: subjectInfo.id,
- courseNum: this.courseNum,
- coursePrice: (this.courseNum * subjectInfo.subjectPrice).toFixed(2),
- price: (this.courseNum * subjectInfo.subjectPrice).toFixed(2),
- teacherName:
- this.userInfo.username || `游客${this.userInfo.userId || ''}`,
- teacherId: this.userInfo.userId,
- starGrade: this.userInfo.starGrade,
- avatar: this.userInfo.heardUrl,
- classTime: tempCourseList
- }
- ]
- const result = res.data
- if (result) {
- Dialog.confirm({
- title: '提示',
- message: '您有一个未支付的订单,是否继续支付?',
- confirmButtonColor: '#269a93',
- cancelButtonText: '取消订单',
- confirmButtonText: '继续支付'
- })
- .then(async () => {
- tradeOrder(result, this.routerTo)
- // this.routerTo()
- })
- .catch(() => {
- Dialog.close()
- // 只用取消订单,不用做其它处理
- this.cancelPayment(result.orderNo)
- })
- } else {
- !goTo && this.routerTo()
- }
- } catch {}
- },
- routerTo() {
- this.$router.push({
- path: '/orderDetail',
- query: {
- orderType: 'VIP_COURSE'
- }
- })
- },
- async cancelPayment(orderNo: string) {
- try {
- await request.post('/api-student/userOrder/orderCancel', {
- data: {
- orderNo
- }
- })
- // this.routerTo()
- } catch {}
- }
- },
- render() {
- return (
- <>
- <div class={styles.tipSection}><Tips type="LIVE_COURSE" title='什么是VIP定制课?' content='VIP定制课程采用一对一专属授课模式,每节课时长为45分钟。课程内容根据学生的具体需求量身打造,旨在全面提升学生的个人技能与表现。不论是希望在乐器演奏技巧上取得突破,如提高指法精准度、气息控制能力或节奏掌握等;还是为即将到来的重要活动、比赛或考级做充分准备,我们都能提供高度匹配的教学方案。此外,教学进度将根据每位学员的学习吸收情况灵活调整,确保每个人都能在最适合自己的节奏中稳步前进,扎实提升个人能力。' /></div>
- {!this.loadDataStatus &&
- (this.settingStatus ? (
- <>
- <div class={styles.practice}>
- <CellGroup class={styles.group} border={false}>
- <Cell
- title="选择专业"
- isLink
- value={this.subjectInfo.subjectName}
- onClick={() => (this.subjectStatus = true)}
- />
- {this.subjectInfo.subjectPrice > 0 && (
- <Cell
- title="VIP定制课收费"
- v-slots={{
- default: () => (
- <div class={styles.price}>
- <span>
- ¥
- {(this as any).$filters.moneyFormat(
- this.subjectInfo.subjectPrice
- )}
- </span>
- /{this.subjectInfo.courseMinutes}分钟
- </div>
- )
- }}
- />
- )}
- <Cell
- title="课时数"
- v-slots={{
- default: () => (
- <Stepper
- v-model={this.courseNum}
- theme="round"
- longPress={false}
- max={12}
- min={4}
- buttonSize={22}
- onChange={() => {
- this.selectCourseList = []
- }}
- />
- )
- }}
- />
- </CellGroup>
- {this.calendarStatus && (
- <div class={styles.group}>
- <Calendar
- selectList={this.selectCourseList}
- list={this.calendarList}
- maxDays={this.courseNum}
- nextMonth={(date: Date) => this.getList(date)}
- prevMonth={(date: Date) => this.getList(date)}
- selectDay={this.onSelectDay}
- v-model:calendarDate={this.calendarDate}
- />
- </div>
- )}
- {this.showSelectList.length > 0 && <Cell
- class={[styles.arrangeCell]}
- v-slots={{
- title: () => (
- <div class={styles.rTitle}>
- <span>已选择课程时间</span>
- </div>
- ),
- label: () => (
- <div class={styles.rTag}>
- {this.showSelectList.map((item: any) => (
- <>
- <Tag
- plain
- round
- closeable
- size="large"
- type="primary"
- class={styles.tag}
- onClose={() => this.onCloseTag(item)}
- >
- {item.title}
- </Tag>
- <br />
- </>
- ))}
- </div>
- )
- }}
- ></Cell>}
- <Popup show={this.selectStatus} class={styles.selectPopup}>
- <div class={styles.selectContainer}>
- <div class={styles.rTitle}>
- <span>提示</span>
- </div>
- <div class={styles.selectPopupContent}>
- <p class={styles.desc}>
- {this.selectType === 'noEnough' &&
- !this.coursePlanStatus
- ? '您所选择的上课时间未达到您输入的课时数,系统根据已选时间将自动按周顺延排课。'
- : '您已选择以下上课时间段,时间段会暂时锁定,锁定期间学员不可购买该时间段课程。'}
- </p>
- {this.coursePlanList &&
- this.coursePlanList.length > 0 &&
- this.coursePlanStatus && (
- <p class={styles.times}>
- {this.coursePlanList.map((item: any) => (
- <span>
- {dayjs(item.startTime || new Date()).format(
- 'YYYY-MM-DD'
- )}{' '}
- {dayjs(item.startTime || new Date()).format(
- 'HH:mm'
- )}
- ~
- {dayjs(item.endTime || new Date()).format(
- 'HH:mm'
- )}
- </span>
- ))}
- </p>
- )}
- </div>
- <div class={styles.selectBtn}>
- <Button
- class={styles.btn}
- type="primary"
- round
- block
- plain
- onClick={this.onReset}
- >
- {this.selectType === 'noEnough'
- ? '继续选择'
- : '重新选择'}
- </Button>
- <Button
- class={styles.btn}
- type="primary"
- round
- block
- onClick={this.onSure}
- >
- 确认
- </Button>
- </div>
- </div>
- </Popup>
- <ActionSheet
- show={this.subjectStatus}
- actions={this.teacherSubjectList}
- cancelText="取消"
- closeOnClickAction
- onCancel={() => (this.subjectStatus = false)}
- onSelect={(item: any) => {
- const {
- subjectName,
- subjectPrice,
- courseMinutes,
- id,
- subjectId,
- freeMinutes
- } = item
- this.subjectInfo = {
- subjectPrice,
- freeMinutes,
- id,
- courseMinutes,
- subjectName,
- subjectId
- }
- this.subjectStatus = false
- }}
- />
- </div>
- <div
- class={['btnGroup', styles.fixedBtn]}
- style={{ background: '#fff', paddingTop: '10px' }}
- >
- <Button block round type="primary" onClick={this.onSubmit}>
- 确认约课
- </Button>
- </div>
- </>
- ) : (
- <ColResult
- btnStatus={false}
- // type="emptyBook"
- classImgSize="SMALL"
- tips="老师暂未开放VIP定制课"
- />
- ))}
- </>
- )
- }
- })
|