lex-xin преди 3 години
родител
ревизия
78ad5b4af1
променени са 29 файла, в които са добавени 1360 реда и са изтрити 665 реда
  1. 68 3
      src/business-components/calendar/index.module.less
  2. 189 16
      src/business-components/calendar/index.tsx
  3. 20 7
      src/business-components/course-plan-step/index.tsx
  4. 173 170
      src/business-components/subject-list/index.tsx
  5. BIN
      src/common/images/icon_clock.png
  6. 72 40
      src/components/col-upload/index.tsx
  7. 32 32
      src/helpers/request.ts
  8. 27 0
      src/helpers/utils.ts
  9. 2 13
      src/student/trade/list/index.tsx
  10. 4 4
      src/styles/index.less
  11. 34 14
      src/teacher/live-class/create-components/arrange.module.less
  12. 253 26
      src/teacher/live-class/create-components/arrange.tsx
  13. 1 14
      src/teacher/live-class/create-components/course-plan.module.less
  14. 51 32
      src/teacher/live-class/create-components/course-plan.tsx
  15. 0 14
      src/teacher/live-class/create-components/course-start.module.less
  16. 72 16
      src/teacher/live-class/create-components/course-start.tsx
  17. 43 37
      src/teacher/live-class/create-components/course.tsx
  18. 27 6
      src/teacher/live-class/create-components/createState.ts
  19. 0 13
      src/teacher/live-class/create-components/detail.module.less
  20. 67 18
      src/teacher/live-class/create-components/detail.tsx
  21. 58 49
      src/teacher/teacher-cert/cert-one.tsx
  22. 0 13
      src/teacher/teacher-cert/index.module.less
  23. 112 61
      src/teacher/teacher-cert/index.tsx
  24. 0 14
      src/teacher/video-class/class-content.module.less
  25. 1 1
      src/teacher/video-class/class-content.tsx
  26. 1 1
      src/teacher/video-class/class-info.tsx
  27. 2 16
      src/teacher/video-class/create-submit.module.less
  28. 50 34
      src/teacher/video-class/create-submit.tsx
  29. 1 1
      src/views/order-detail/userAuth/index.tsx

+ 68 - 3
src/business-components/calendar/index.module.less

@@ -25,9 +25,10 @@
       box-shadow: none;
     }
     .van-calendar__selected-day {
-      width: 36px !important;
+      width: 38px !important;
       height: 45px !important;
-      border-radius: 2px;
+      border-radius: 5px;
+      overflow: hidden;
       .van-calendar__bottom-info {
         color: #fff !important;
       }
@@ -44,7 +45,7 @@
         right: 0;
         bottom: 0;
         left: 50%;
-        width: 36px;
+        width: 38px;
         height: 45px;
         background: #2dc7aa;
         content: '';
@@ -73,3 +74,67 @@
     }
   }
 }
+
+.calenderPopup {
+  border-radius: 8px;
+  overflow: hidden;
+  padding: 18px 12px 28px;
+  .popup {
+    width: 312px;
+    background: #ffffff;
+  }
+  .title {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+    font-size: 18px;
+    font-weight: 500;
+    color: #333333;
+    line-height: 25px;
+    padding: 0 20px 25px;
+  }
+  .container {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    padding-bottom: 14px;
+    & > div {
+      flex-basis: 33.33%;
+      text-align: center;
+    }
+  }
+  .noDay {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex: 1;
+    padding: 25px 0 35px;
+    .clock {
+      width: 30px;
+    }
+    span {
+      padding-left: 10px;
+      font-size: 14px;
+      font-weight: 500;
+      color: #999;
+    }
+  }
+  .tag {
+    padding: 8px 10px;
+    margin-bottom: 10px;
+    font-size: 12px;
+    color: #333333;
+    border-color: #d8d8d8;
+
+    &.active {
+      color: var(--van-primary);
+      background: #e0f7f3;
+      border-color: var(--van-primary);
+    }
+  }
+
+  .dayBtn {
+    display: flex;
+    align-items: center;
+  }
+}

+ 189 - 16
src/business-components/calendar/index.tsx

@@ -1,12 +1,28 @@
-import { Calendar, Icon } from 'vant'
+import { Button, Calendar, Icon, Image, Popup, Tag, Toast } from 'vant'
 import { defineComponent } from 'vue'
 import dayjs from 'dayjs'
 import styles from './index.module.less'
 import IconArrow from '@/common/images/icon_arrow.png'
+import IconClock from '@/common/images/icon_clock.png'
 
 export default defineComponent({
   name: 'calendar',
   props: {
+    selectList: {
+      type: Array,
+      default: []
+    },
+    list: {
+      type: Object,
+      default: {}
+    },
+    /**
+     * 每天选择课程最大数
+     */
+    maxDays: {
+      type: [Number, String],
+      default: 0
+    },
     /**
      * 点击并选中任意日期时触发
      */
@@ -27,6 +43,10 @@ export default defineComponent({
     nextMonth: {
       type: Function,
       default: (date: Date) => {}
+    },
+    selectDay: {
+      type: Function,
+      default: (obj: any) => {}
     }
   },
   data() {
@@ -34,49 +54,126 @@ export default defineComponent({
       minDate: new Date(),
       maxDate: new Date(),
       currentDate: new Date(), // 当前日历日期
-      subtitle: ''
+      subtitle: '',
+      show: false,
+      dayList: [],
+      selectDays: [] as any
     }
   },
   computed: {
     arrowStatus() {
       // 上月箭头状态
-      // console.log(dayjs().subtract(1, 'date').format('YYYY年MM月DD日'))
-      // console.log(dayjs().isBefore(dayjs(this.currentDate), 'month'))
       return !dayjs().isBefore(dayjs(this.currentDate), 'month')
+    },
+    selectDayTitle() {
+      // 选中日期标题
+      return dayjs(this.currentDate).format('YYYY-MM-DD')
+    },
+    isPrevDay() {
+      // 是否可以点击上一天
+      return dayjs(this.currentDate)
+        .subtract(1, 'day')
+        .isBefore(dayjs(this.minDate), 'day')
+    },
+    isNextDay() {
+      // 是否可以点击下一天
+      return dayjs(this.currentDate)
+        .add(1, 'day')
+        .isAfter(dayjs(this.maxDate), 'day')
     }
   },
   mounted() {
     // 初始化标题和最大显示日期
     this.subtitle = dayjs().format('YYYY年MM月')
-    this.maxDate = new Date(dayjs().endOf('month').toDate())
+    this.maxDate = dayjs().endOf('month').toDate()
+    this.minDate = dayjs().add(1, 'day').toDate()
+
+    // 初始化日历
+    // console.log(this.list, 323, this.maxDays)
   },
   methods: {
     formatter(date: any) {
-      // console.log(date)
-      // date.bottomInfo = '满'
-      // date.className = 'full'
+      const dateStr = dayjs(date.date).format('YYYY-MM-DD')
+      const dateObj = this.list[dateStr]
+      if (dateObj && dateObj.fullCourse) {
+        date.bottomInfo = '满'
+        date.className = 'full'
+      }
+      date.type = date.type === 'selected' ? '' : date.type
       return date
     },
-    onDateSelect(date: any) {
-      console.log(date)
-      this.onSelect && this.onSelect(date)
-    },
     onPrevMonth() {
+      // 上一月
       if (this.arrowStatus) return
       const tempDate = dayjs(this.currentDate).subtract(1, 'month')
       this._monthChange(tempDate)
-      this.prevMonth && this.prevMonth(tempDate.toDate())
+      this.prevMonth && this.prevMonth(this.minDate)
     },
     onNextMonth() {
+      // 下一月
       const tempDate = dayjs(this.currentDate).add(1, 'month')
       this._monthChange(tempDate)
-      this.nextMonth && this.nextMonth(tempDate.toDate())
+      this.nextMonth && this.nextMonth(this.minDate)
     },
     _monthChange(date: any) {
-      this.minDate = date.startOf('month').toDate()
+      // 月份改变
+      // 需要判断是否是当月,需要单独处理最小时间
+      const currentMinDate = dayjs().add(1, 'day').toDate()
+      const monthMinDate = date.startOf('month').toDate()
+      this.minDate = dayjs(currentMinDate).isAfter(monthMinDate)
+        ? currentMinDate
+        : monthMinDate
+      // this.minDate = date.startOf('month').toDate()
       this.maxDate = date.endOf('month').toDate()
       this.currentDate = date.toDate()
       this.subtitle = date.format('YYYY年MM月')
+    },
+    onSelectDay(item: any) {
+      // 选择某个时间段
+      if (this.selectDays.length < this.maxDays) {
+        const index = this.selectDays.findIndex(
+          (days: any) => days.startTime === item.startTime
+        )
+        item.checked = !item.checked
+        if (index === -1) {
+          this.selectDays.push({ ...item })
+        } else {
+          this.selectDays.splice(index, 1)
+        }
+      } else {
+        Toast('最多选择' + this.maxDays + '个时间段')
+      }
+    },
+    onPrevDay() {
+      // 获取上一天的数据
+      const tempDate = dayjs(this.currentDate).subtract(1, 'day')
+      this._dayChange(tempDate.toDate())
+    },
+    onNextDay() {
+      // 获取下一天的数据
+      const tempDate = dayjs(this.currentDate).add(1, 'day')
+      this._dayChange(tempDate.toDate())
+    },
+    onDateSelect(date: any) {
+      // 选择日历上某一个日期
+      this.selectDays = [...this.selectList] // 初始化用户选中的值
+      this._dayChange(date)
+      this.onSelect && this.onSelect(date)
+    },
+    _dayChange(date: Date) {
+      const dateStr = dayjs(date).format('YYYY-MM-DD')
+      let dataList = (this.list[dateStr] && this.list[dateStr].courseTime) || []
+      dataList.forEach((item: any) => {
+        item.start = dayjs(item.startTime).format('HH:mm')
+        item.end = dayjs(item.endTime).format('HH:mm')
+        const isExist = this.selectList?.some(
+          (course: any) => course.startTime === item.startTime
+        )
+        item.checked = isExist
+      })
+      this.dayList = dataList
+      this.currentDate = date // 更新当前日期
+      this.show = true
     }
   },
   render() {
@@ -89,7 +186,7 @@ export default defineComponent({
           showConfirm={false}
           showMark={false}
           firstDayOfWeek={1}
-          rowHeight={50}
+          rowHeight={60}
           minDate={this.minDate}
           maxDate={this.maxDate}
           color="var(--van-primary)"
@@ -116,6 +213,82 @@ export default defineComponent({
             // 'bottom-info': (date: any) => <span>{date.type}</span>
           }}
         />
+
+        <Popup show={this.show} class={styles.calenderPopup}>
+          <div class={styles.popup}>
+            <div class={styles.title}>
+              <Button
+                type="primary"
+                plain
+                style={{ border: 0 }}
+                size="small"
+                disabled={this.isPrevDay}
+                onClick={this.onPrevDay}
+              >
+                上一日
+              </Button>
+              <span>{this.selectDayTitle}</span>
+              <Button
+                type="primary"
+                plain
+                style={{ border: 0 }}
+                size="small"
+                disabled={this.isNextDay}
+                onClick={this.onNextDay}
+              >
+                下一日
+              </Button>
+            </div>
+
+            <div class={styles.container}>
+              {this.dayList.map((item: any) => (
+                <div>
+                  <Tag
+                    round
+                    class={[styles.tag, item.checked ? styles.active : '']}
+                    size="large"
+                    plain
+                    onClick={() => this.onSelectDay(item)}
+                  >
+                    {item.start}~{item.end}
+                  </Tag>
+                </div>
+              ))}
+              {this.dayList.length <= 0 && (
+                <div class={styles.noDay}>
+                  <Image src={IconClock} class={styles.clock} fit="cover" />
+                  <span>今日已约满</span>
+                </div>
+              )}
+            </div>
+
+            <div class={styles.dayBtn}>
+              <Button
+                round
+                plain
+                style={{ width: '33.33%', marginRight: '10px' }}
+                onClick={() => {
+                  this.show = false
+                  this.selectDays = []
+                }}
+              >
+                取消
+              </Button>
+              <Button
+                type="primary"
+                block
+                round
+                disabled={!(this.selectDays.length > 0)}
+                onClick={() => {
+                  this.selectDay && this.selectDay(this.selectDays)
+                  this.show = false
+                }}
+              >
+                确认
+              </Button>
+            </div>
+          </div>
+        </Popup>
       </>
     )
   }

+ 20 - 7
src/business-components/course-plan-step/index.tsx

@@ -1,28 +1,41 @@
-import { defineComponent } from "vue";
+import { defineComponent, PropType } from "vue";
 import styles from './index.module.less';
 import { Icon, Image } from "vant";
 import videoStop from '@common/images/icon_video_stop.png';
 
+interface IProps {
+  courseTime: string;
+  coursePlan: string;
+  videoPosterUrl?: string;
+  id?: number | string;
+}
+
 export default defineComponent({
   name: "CoursePlanStep",
+  props: {
+    courseInfo: {
+      type: Array as PropType<IProps[]>,
+      default: []
+    }
+  },
   render() {
     return (
       <div class={styles['col-steps']}>
         <div class={styles['col-steps__items']}>
-          {[1, 2].map((item: any, index: number) => (
+          {this.courseInfo.map((item: any, index: number) => (
             <div class={styles['col-step']}>
               <div class={styles['col-step__title']}>
                 {this.$slots.content ? this.$slots.content() : <div class={styles.stepSection}>
                   <div class={styles.stepTitle}>
                     <span class={styles.stepTitleNum}>第 {index + 1} 课时</span>
-                    <span class={styles.stepTitleText}>2022-4-1 11:14:46</span>
+                    <span class={styles.stepTitleText}>{ item.courseTime }</span>
                   </div>
                   <div class={styles.stepContent}>
-                    <p>小酷老师带您零基础学习竖笛,通过4节课的学习掌握竖笛演奏的基本方式,培养娘好的吐息习惯。</p>
-                    <div class={styles.videoImg}>
-                      <Image src='https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png' fit="cover" />
+                    <p>{ item.coursePlan }</p>
+                    {item.videoPosterUrl && (<div class={styles.videoImg}>
+                      <Image src={item.videoPosterUrl} fit="cover" />
                       <Icon class={styles.videoStop} name={videoStop} size={32} />
-                    </div>
+                    </div>)}
                   </div>
                 </div>}
               </div>

+ 173 - 170
src/business-components/subject-list/index.tsx

@@ -39,6 +39,11 @@ export default defineComponent({
       // 选择类型,Radio:单选,Checkbox:多选
       type: String as PropType<'Checkbox' | 'Radio'>,
       default: 'Checkbox'
+    },
+    single: {
+      // 单选模式
+      type: Boolean,
+      default: false
     }
   },
   data() {
@@ -67,191 +72,189 @@ export default defineComponent({
         {this.subjectList.length ? (
           this.selectType === 'Checkbox' ? (
             <CheckboxGroup v-model={this.checkBox} max={this.max}>
-              {this.subjectList.map((item: any) =>
-                item.subjects && item.subjects.length > 0 ? (
-                  <>
-                    <div class={styles.title}>{item.name}</div>
-                    <div class={styles['subject-list']}>
-                      {item.subjects &&
-                        item.subjects.map((sub: any) => (
-                          <div
-                            class={styles['subject-item']}
-                            onClick={() => this.onSelect(sub.id)}
-                          >
-                            <Image
-                              src={sub.img}
-                              width="100%"
-                              height="100%"
-                              fit="cover"
-                              v-slots={{
-                                loading: () => (
-                                  <Loading type="spinner" size={20} />
-                                )
-                              }}
-                            />
-                            <div class={styles.topBg}>
-                              <Checkbox
-                                name={sub.id}
-                                class={styles.checkbox}
-                                ref={(el: any) =>
-                                  (this.checkboxRefs[sub.id] = el)
-                                }
+              {!this.single &&
+                this.subjectList.map((item: any) =>
+                  item.subjects && item.subjects.length > 0 ? (
+                    <>
+                      <div class={styles.title}>{item.name}</div>
+                      <div class={styles['subject-list']}>
+                        {item.subjects &&
+                          item.subjects.map((sub: any) => (
+                            <div
+                              class={styles['subject-item']}
+                              onClick={() => this.onSelect(sub.id)}
+                            >
+                              <Image
+                                src={sub.img}
+                                width="100%"
+                                height="100%"
+                                fit="cover"
                                 v-slots={{
-                                  icon: (props: any) => (
-                                    <Icon
-                                      name={
-                                        props.checked
-                                          ? checkBoxActive
-                                          : checkBoxDefault
-                                      }
-                                      size="22"
-                                    />
+                                  loading: () => (
+                                    <Loading type="spinner" size={20} />
                                   )
                                 }}
                               />
-                              <p class={styles.name}>{sub.name}</p>
+                              <div class={styles.topBg}>
+                                <Checkbox
+                                  name={sub.id}
+                                  class={styles.checkbox}
+                                  disabled
+                                  ref={(el: any) =>
+                                    (this.checkboxRefs[sub.id] = el)
+                                  }
+                                  v-slots={{
+                                    icon: (props: any) => (
+                                      <Icon
+                                        name={
+                                          props.checked
+                                            ? checkBoxActive
+                                            : checkBoxDefault
+                                        }
+                                        size="22"
+                                      />
+                                    )
+                                  }}
+                                />
+                                <p class={styles.name}>{sub.name}</p>
+                              </div>
                             </div>
-                          </div>
-                        ))}
+                          ))}
+                      </div>
+                    </>
+                  ) : null
+                )}
+              {this.single ? (
+                <div class={styles['subject-list']}>
+                  {this.subjectList.map((item: any) => (
+                    <div
+                      class={styles['subject-item']}
+                      onClick={() => this.onSelect(item.id)}
+                    >
+                      <Image
+                        src={item.img}
+                        width="100%"
+                        height="100%"
+                        fit="cover"
+                        v-slots={{
+                          loading: () => <Loading type="spinner" size={20} />
+                        }}
+                      />
+                      <div class={styles.topBg}>
+                        <Checkbox
+                          name={item.id}
+                          class={styles.checkbox}
+                          disabled
+                          ref={(el: any) => (this.checkboxRefs[item.id] = el)}
+                          v-slots={{
+                            icon: (props: any) => (
+                              <Icon
+                                name={
+                                  props.checked
+                                    ? checkBoxActive
+                                    : checkBoxDefault
+                                }
+                                size="22"
+                              />
+                            )
+                          }}
+                        />
+                        <p class={styles.name}>{item.name}</p>
+                      </div>
                     </div>
-                  </>
-                ) : (
-                  <div class={styles['subject-list']}>
-                    {item.subjects &&
-                      item.subjects.map((sub: any) => (
-                        <div
-                          class={styles['subject-item']}
-                          onClick={() => this.onSelect(sub.id)}
-                        >
-                          <Image
-                            src={sub.img}
-                            width="100%"
-                            height="100%"
-                            fit="cover"
-                            v-slots={{
-                              loading: () => (
-                                <Loading type="spinner" size={20} />
-                              )
-                            }}
-                          />
-                          <div class={styles.topBg}>
-                            <Checkbox
-                              name={sub.id}
-                              class={styles.checkbox}
-                              ref={(el: any) =>
-                                (this.checkboxRefs[sub.id] = el)
-                              }
-                              v-slots={{
-                                icon: (props: any) => (
-                                  <Icon
-                                    name={
-                                      props.checked
-                                        ? checkBoxActive
-                                        : checkBoxDefault
-                                    }
-                                    size="22"
-                                  />
-                                )
-                              }}
-                            />
-                            <p class={styles.name}>{sub.name}</p>
-                          </div>
-                        </div>
-                      ))}
-                  </div>
-                )
-              )}
+                  ))}
+                </div>
+              ) : null}
             </CheckboxGroup>
           ) : (
             <RadioGroup v-model={this.radio}>
-              {this.subjectList.map((item: any) =>
-                item.subjects && item.subjects.length > 0 ? (
-                  <>
-                    <div class={styles.title}>{item.name}</div>
-                    <div class={styles['subject-list']}>
-                      {item.subjects &&
-                        item.subjects.map((sub: any) => (
-                          <div
-                            class={styles['subject-item']}
-                            onClick={() => this.onSelect(sub.id)}
-                          >
-                            <Image
-                              src={sub.img}
-                              width="100%"
-                              height="100%"
-                              fit="cover"
-                              v-slots={{
-                                loading: () => (
-                                  <Loading type="spinner" size={20} />
-                                )
-                              }}
-                            />
-                            <div class={styles.topBg}>
-                              <Radio
-                                name={sub.id}
-                                class={styles.checkbox}
+              {!this.single &&
+                this.subjectList.map((item: any) =>
+                  item.subjects && item.subjects.length > 0 ? (
+                    <>
+                      <div class={styles.title}>{item.name}</div>
+                      <div class={styles['subject-list']}>
+                        {item.subjects &&
+                          item.subjects.map((sub: any) => (
+                            <div
+                              class={styles['subject-item']}
+                              onClick={() => this.onSelect(sub.id)}
+                            >
+                              <Image
+                                src={sub.img}
+                                width="100%"
+                                height="100%"
+                                fit="cover"
                                 v-slots={{
-                                  icon: (props: any) => (
-                                    <Icon
-                                      name={
-                                        props.checked
-                                          ? checkBoxActive
-                                          : checkBoxDefault
-                                      }
-                                      size="22"
-                                    />
+                                  loading: () => (
+                                    <Loading type="spinner" size={20} />
                                   )
                                 }}
                               />
-                              <p class={styles.name}>{sub.name}</p>
+                              <div class={styles.topBg}>
+                                <Radio
+                                  name={sub.id}
+                                  class={styles.checkbox}
+                                  v-slots={{
+                                    icon: (props: any) => (
+                                      <Icon
+                                        name={
+                                          props.checked
+                                            ? checkBoxActive
+                                            : checkBoxDefault
+                                        }
+                                        size="22"
+                                      />
+                                    )
+                                  }}
+                                />
+                                <p class={styles.name}>{sub.name}</p>
+                              </div>
                             </div>
-                          </div>
-                        ))}
+                          ))}
+                      </div>
+                    </>
+                  ) : null
+                )}
+              {this.single ? (
+                <div class={styles['subject-list']}>
+                  {this.subjectList.map((item: any) => (
+                    <div
+                      class={styles['subject-item']}
+                      onClick={() => this.onSelect(item.id)}
+                    >
+                      <Image
+                        src={item.img}
+                        width="100%"
+                        height="100%"
+                        fit="cover"
+                        v-slots={{
+                          loading: () => <Loading type="spinner" size={20} />
+                        }}
+                      />
+                      <div class={styles.topBg}>
+                        <Radio
+                          name={item.id}
+                          class={styles.checkbox}
+                          v-slots={{
+                            icon: (props: any) => (
+                              <Icon
+                                name={
+                                  props.checked
+                                    ? checkBoxActive
+                                    : checkBoxDefault
+                                }
+                                size="22"
+                              />
+                            )
+                          }}
+                        />
+                        <p class={styles.name}>{item.name}</p>
+                      </div>
                     </div>
-                  </>
-                ) : (
-                  <div class={styles['subject-list']}>
-                    {item.subjects &&
-                      item.subjects.map((sub: any) => (
-                        <div
-                          class={styles['subject-item']}
-                          onClick={() => this.onSelect(sub.id)}
-                        >
-                          <Image
-                            src={sub.img}
-                            width="100%"
-                            height="100%"
-                            fit="cover"
-                            v-slots={{
-                              loading: () => (
-                                <Loading type="spinner" size={20} />
-                              )
-                            }}
-                          />
-                          <div class={styles.topBg}>
-                            <Radio
-                              name={sub.id}
-                              class={styles.checkbox}
-                              v-slots={{
-                                icon: (props: any) => (
-                                  <Icon
-                                    name={
-                                      props.checked
-                                        ? checkBoxActive
-                                        : checkBoxDefault
-                                    }
-                                    size="22"
-                                  />
-                                )
-                              }}
-                            />
-                            <p class={styles.name}>{sub.name}</p>
-                          </div>
-                        </div>
-                      ))}
-                  </div>
-                )
-              )}
+                  ))}
+                </div>
+              ) : null}
             </RadioGroup>
           )
         ) : (

BIN
src/common/images/icon_clock.png


+ 72 - 40
src/components/col-upload/index.tsx

@@ -1,11 +1,11 @@
-import { Icon, Image, Toast, Uploader } from "vant";
-import { defineComponent } from "vue";
-import styles from "./index.module.less";
-import ColCropper from "../col-cropper";
-import { useCustomFieldValue } from '@vant/use';
+import { Icon, Image, Toast, Uploader } from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+import ColCropper from '../col-cropper'
+import { useCustomFieldValue } from '@vant/use'
 
-import iconUploader from '@common/images/icon_uploader.png';
-import request from "@/helpers/request";
+import iconUploader from '@common/images/icon_uploader.png'
+import request from '@/helpers/request'
 
 export default defineComponent({
   name: 'col-upload',
@@ -19,18 +19,20 @@ export default defineComponent({
       type: Boolean,
       default: true
     },
-    cropper: { // 是否进行裁切
+    cropper: {
+      // 是否进行裁切
       type: Boolean,
       default: false
     },
-    options: { // 裁切需要参数
+    options: {
+      // 裁切需要参数
       type: Object,
       default: {}
     },
     onUploadChange: {
       type: Function,
-      default: (url: string) => { }
-    },
+      default: (url: string) => {}
+    }
   },
   methods: {
     beforeRead(file: any) {
@@ -41,68 +43,98 @@ export default defineComponent({
       }
       return true
     },
-    beforeDelete(file: any, detail: { index: any; }) {
+    beforeDelete(file: any, detail: { index: any }) {
       // this.dataModel.splice(detail.index, 1)
       return true
     },
     async afterRead(file: any, detail: any) {
       try {
-        file.status = 'uploading';
-        file.message = '上传中...';
-        let formData = new FormData();
-        formData.append('file', file.file);
+        file.status = 'uploading'
+        file.message = '上传中...'
+        let formData = new FormData()
+        formData.append('file', file.file)
         let res = await request.post('/api-teacher/uploadFile', {
           data: formData
         })
-        this.$emit('update:modelValue', res.data.url);
-        this.onUploadChange(res.data.url);
+        this.$emit('update:modelValue', res.data.url)
+        this.onUploadChange(res.data.url)
       } catch (error) {
         //
       }
     },
     onClose(e: any) {
-      this.$emit('update:modelValue', null);
-      this.onUploadChange();
-      e.stopPropagation();
+      this.$emit('update:modelValue', null)
+      this.onUploadChange()
+      e.stopPropagation()
     },
     async getFile(file: any) {
       // 上传文件
       try {
-        let formData = new FormData();
-        formData.append('file', file);
+        let formData = new FormData()
+        formData.append('file', file)
         let res = await request.post('/api-teacher/uploadFile', {
           data: formData
         })
-        this.$emit('update:modelValue', res.data.url);
-        this.onUploadChange(res.data.url);
+        this.$emit('update:modelValue', res.data.url)
+        this.onUploadChange(res.data.url)
       } catch {
         //
       }
     }
   },
   render() {
-    useCustomFieldValue(() => this.modelValue);
+    useCustomFieldValue(() => this.modelValue)
     return (
       <div class={styles['uploader-section']}>
-        {this.modelValue && this.deletable ? <Icon name="cross" onClick={this.onClose} class={styles["img-close"]} /> : null}
-        {this.cropper ? <div class={styles['col-uploader']}>
-          {this.modelValue ? <Image fit="cover" position="center" class={styles.uploadImg} src={this.modelValue} /> : <div class={styles.uploader}>
-            <Icon name={iconUploader} size="32" />
-            <p class={styles.uploaderText}>{this.tips}</p>
-          </div>}
-          <ColCropper option={this.options} getFile={this.getFile} />
-        </div> : (
-          // @ts-ignore
-          <Uploader afterRead={this.afterRead} beforeRead={this.beforeRead} beforeDelete={this.beforeDelete}
-            v-slots={{
-              default: () => (this.modelValue ? <Image fit="cover" position="center" class={styles.uploadImg} src={this.modelValue} /> : <div class={styles.uploader}>
+        {this.modelValue && this.deletable ? (
+          <Icon
+            name="cross"
+            onClick={this.onClose}
+            class={styles['img-close']}
+          />
+        ) : null}
+        {this.cropper ? (
+          <div class={styles['col-uploader']}>
+            {this.modelValue ? (
+              <Image
+                fit="cover"
+                position="center"
+                class={styles.uploadImg}
+                src={this.modelValue}
+              />
+            ) : (
+              <div class={styles.uploader}>
                 <Icon name={iconUploader} size="32" />
                 <p class={styles.uploaderText}>{this.tips}</p>
-              </div>)
+              </div>
+            )}
+            <ColCropper option={this.options} getFile={this.getFile} />
+          </div>
+        ) : (
+          // @ts-ignore
+          <Uploader
+            afterRead={this.afterRead}
+            beforeRead={this.beforeRead}
+            beforeDelete={this.beforeDelete}
+            v-slots={{
+              default: () =>
+                this.modelValue ? (
+                  <Image
+                    fit="cover"
+                    position="center"
+                    class={styles.uploadImg}
+                    src={this.modelValue}
+                  />
+                ) : (
+                  <div class={styles.uploader}>
+                    <Icon name={iconUploader} size="32" />
+                    <p class={styles.uploaderText}>{this.tips}</p>
+                  </div>
+                )
             }}
           />
         )}
       </div>
     )
   }
-})
+})

+ 32 - 32
src/helpers/request.ts

@@ -1,19 +1,19 @@
-import { extend } from 'umi-request';
-import cleanDeep from 'clean-deep';
-import { browser, openLoading, closeLoading } from '@/helpers/utils';
-import { setLogout, setLoginError } from '@/state';
-import { postMessage } from './native-message';
-import { Toast } from 'vant';
+import { extend } from 'umi-request'
+import cleanDeep from 'clean-deep'
+import { browser, openLoading, closeLoading } from '@/helpers/utils'
+import { setLogout, setLoginError } from '@/state'
+import { postMessage } from './native-message'
+import { Toast } from 'vant'
 
 export interface SearchInitParams {
-  rows?: string | number;
-  page?: string | number;
+  rows?: string | number
+  page?: string | number
 }
 
 const request = extend({
   // requestType: 'form',
-  timeout: 10000
-});
+  timeout: 15000
+})
 
 // request.use(async (ctx, next) => {
 //   const { url, options } = ctx.req
@@ -27,7 +27,7 @@ const request = extend({
 // })
 
 // 是否是初始化接口
-let initRequest = false;
+let initRequest = false
 
 request.interceptors.request.use(
   (url, options: any) => {
@@ -38,9 +38,9 @@ request.interceptors.request.use(
       loadingType: 'spinner',
       duration: 0
     })
-    initRequest = options.initRequest || false;
-    const Authorization = sessionStorage.getItem('Authorization') || '';
-    const authHeaders: any = {};
+    initRequest = options.initRequest || false
+    const Authorization = sessionStorage.getItem('Authorization') || ''
+    const authHeaders: any = {}
     if (
       Authorization &&
       ![
@@ -49,7 +49,7 @@ request.interceptors.request.use(
         '/api-auth/code/sendSms'
       ].includes(url)
     ) {
-      authHeaders.Authorization = Authorization;
+      authHeaders.Authorization = Authorization
     }
     return {
       url,
@@ -61,48 +61,48 @@ request.interceptors.request.use(
           ...authHeaders
         }
       }
-    };
+    }
   },
   { global: false }
-);
+)
 
 request.interceptors.response.use(
   async res => {
     // setTimeout(() => {
     // closeLoading();
     // }, 100);
-    Toast.clear();
+    Toast.clear()
     if (res.status > 299 || res.status < 200) {
-      const msg = '服务器错误,状态码' + res.status;
-      Toast(msg);
-      throw new Error(msg);
+      const msg = '服务器错误,状态码' + res.status
+      Toast(msg)
+      throw new Error(msg)
     }
-    const data = await res.clone().json();
+    const data = await res.clone().json()
     if (data.code !== 200 && data.errCode !== 0) {
-      const msg = data.msg || '处理失败,请重试';
+      const msg = data.msg || '处理失败,请重试'
       if (initRequest) {
         if (data.code === 403 || data.code === 401) {
-          setLogout();
+          setLogout()
         } else {
-          setLoginError();
+          setLoginError()
         }
       }
       if (!(data.code === 403 || data.code === 401)) {
-        Toast(msg);
+        Toast(msg)
       }
-      const browserInfo = browser();
+      const browserInfo = browser()
       if (data.code === 403) {
         if (browserInfo.isApp) {
           postMessage({
             api: 'login'
-          });
+          })
         }
       }
-      throw new Error(msg);
+      throw new Error(msg)
     }
-    return res;
+    return res
   },
   { global: false }
-);
+)
 
-export default request;
+export default request

+ 27 - 0
src/helpers/utils.ts

@@ -82,3 +82,30 @@ export const closeLoading = () => {
     }
   }, 200)
 }
+
+export const getWeekCh = (week: number, type = 0) => {
+  const template = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
+  const template2 = [
+    '星期天',
+    '星期一',
+    '星期二',
+    '星期三',
+    '星期四',
+    '星期五',
+    '星期六'
+  ]
+  return type ? template2[week] : template[week]
+}
+
+export const formatterDate = (type: string, val: any) => {
+  if (type === 'year') {
+    return `${val}年`
+  }
+  if (type === 'month') {
+    return `${val}月`
+  }
+  if (type === 'day') {
+    return `${val}日`
+  }
+  return val
+}

+ 2 - 13
src/student/trade/list/index.tsx

@@ -10,6 +10,7 @@ import {
   Sticky,
   Image
 } from 'vant'
+import { formatterDate } from '@/helpers/utils'
 
 import iconTeacher from '@common/images/icon_teacher.png'
 
@@ -38,18 +39,6 @@ export default defineComponent({
     onConfirm(date: Date) {
       this.currentDate = date
       this.timeStatus = false
-    },
-    formatter(type: string, val: any) {
-      if (type === 'year') {
-        return `${val}年`
-      }
-      if (type === 'month') {
-        return `${val}月`
-      }
-      if (type === 'day') {
-        return `${val}日`
-      }
-      return val
     }
   },
   render() {
@@ -138,7 +127,7 @@ export default defineComponent({
           <DatetimePicker
             type="date"
             v-model={this.currentDate}
-            formatter={this.formatter}
+            formatter={formatterDate}
             onCancel={() => {
               this.timeStatus = false
             }}

+ 4 - 4
src/styles/index.less

@@ -123,9 +123,9 @@ body {
 .btnMore {
   display: flex;
   justify-content: space-between;
-  :global {
-    .van-button {
-      width: 48%;
-    }
+  // :global {
+  .van-button {
+    width: 48% !important;
   }
+  // }
 }

+ 34 - 14
src/teacher/live-class/create-components/arrange.module.less

@@ -18,8 +18,8 @@
       content: ' ';
       display: inline-block;
       width: 4px;
-      height: 14px;
-      background: #2dc7aa;
+      height: 17px;
+      background: linear-gradient(180deg, #59e5d5 0%, #2dc7aa 100%);
       border-radius: 3px;
     }
   }
@@ -28,21 +28,41 @@
     .tag {
       background: #e9fff8;
       margin-bottom: 8px;
-      & + .tag {
-        margin-left: 8px;
-      }
     }
   }
 
-  .btnGroup {
-    padding: 0 14px;
-    padding-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
+  .selectPopup {
+    width: 312px;
+    background: #ffffff;
+    border-radius: 8px;
+    .selectContainer {
+      padding: 18px 14px;
+    }
+    .rTitle {
+      font-size: 18px;
+    }
+    .selectPopupContent {
+      padding: 20px 0;
+    }
+    .desc,
+    .times {
+      font-size: 14px;
+      color: #666666;
+      line-height: 20px;
+    }
+
+    .times {
+      padding-top: 15px;
+      span {
+        display: block;
+      }
+    }
+
+    .selectBtn {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .btn {
         width: 48%;
       }
     }

+ 253 - 26
src/teacher/live-class/create-components/arrange.tsx

@@ -1,70 +1,297 @@
 import Calendar from '@/business-components/calendar'
-import { Button, Cell, Sticky, Tag } from 'vant'
+import request from '@/helpers/request'
+import { Button, Cell, Dialog, Popup, Sticky, Tag, Toast } from 'vant'
 import { defineComponent } from 'vue'
 import styles from './arrange.module.less'
+import dayjs from 'dayjs'
 import { createState } from './createState'
+import { state } from '@/state'
+import { getWeekCh } from '@/helpers/utils'
 
 export default defineComponent({
   name: 'arrange',
+  data() {
+    return {
+      selectStatus: false,
 
+      calendarList: {}
+    }
+  },
+  computed: {
+    showSelectList() {
+      let list = [...createState.selectCourseList]
+      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 createState.selectCourseList.length < createState.live.courseNum
+        ? 'noEnough'
+        : 'enough'
+    }
+  },
+  async mounted() {
+    const initDate = dayjs().add(1, 'day').toDate()
+    await this.getList(initDate)
+
+    if (createState.coursePlanStatus) {
+      this.selectStatus = true
+    }
+  },
+  methods: {
+    async getList(date?: Date) {
+      let params = {
+        day: dayjs(date || new Date()).format('DD'),
+        month: dayjs(date || new Date()).format('MM'),
+        year: dayjs(date || new Date()).format('YYYY')
+      }
+      try {
+        let res = await request.post(
+          '/api-teacher/courseSchedule/createLiveCourseCalendar',
+          {
+            data: {
+              ...params,
+              singleCourseMinutes: createState.live.singleCourseMinutes,
+              teacherId: state.user.data?.userId
+            }
+          }
+        )
+        const result = res.data || []
+        let tempObj = {}
+        result.forEach((item: any) => {
+          tempObj[item.date] = item
+        })
+        this.calendarList = tempObj
+      } catch {}
+    },
+    onSelectDay(obj: any) {
+      const result = obj || []
+      let list = [...createState.selectCourseList]
+      result.forEach((item: any) => {
+        const isExist = list.some(
+          (course: any) => course.startTime === item.startTime
+        )
+        !isExist && list.push({ ...item })
+      })
+      // 对数组进行排序
+      list.sort((first: any, second: any) => {
+        if (first.startTime > second.startTime) return 1
+        if (first.startTime < second.startTime) return -1
+        return 0
+      })
+      createState.selectCourseList = [...list]
+    },
+    onCloseTag(item: any) {
+      Dialog.confirm({
+        title: '提示',
+        message: '您是否要删除该选择的课程?',
+        confirmButtonColor: 'var(--van-primary)'
+      }).then(() => {
+        const index = createState.selectCourseList.findIndex(
+          (course: any) => course.startTime === item.startTime
+        )
+        createState.selectCourseList.splice(index, 1)
+      })
+    },
+    async onSubmit() {
+      if (createState.selectCourseList.length <= 0) {
+        Toast('请选择课程时间')
+        return
+      }
+
+      if (createState.selectCourseList.length < createState.live.courseNum) {
+        this.selectStatus = true
+        return
+      }
+
+      await this._lookCourse()
+    },
+    async _lookCourse(callBack?: Function) {
+      try {
+        let times = [] as any
+        createState.selectCourseList.forEach((item: any) => {
+          times.push({
+            startTime: item.startTime,
+            endTime: item.endTime
+          })
+        })
+        const res = await request.post(
+          '/api-teacher/courseGroup/lockCourseToCache',
+          {
+            data: {
+              courseNum: createState.live.courseNum,
+              courseType: 'LIVE',
+              loop: this.selectType === 'noEnough' ? 1 : 0,
+              teacherId: state.user.data?.userId,
+              timeList: [...times]
+            }
+          }
+        )
+        const result = res.data || []
+        result.forEach((item: any, index: number) => {
+          createState.live.coursePlanList[index] = {
+            ...createState.live.coursePlanList[index],
+            startTime: item.startTime,
+            endTime: item.endTime,
+            classNum: index + 1
+          }
+        })
+        createState.coursePlanStatus = true
+        this.selectStatus = true
+        callBack && callBack()
+      } catch {}
+    },
+    async _unLookCourse() {
+      try {
+        await request.get('/api-teacher/courseGroup/unlockCourseToCache', {
+          params: {
+            teacherId: state.user.data?.userId
+          }
+        })
+        this.selectStatus = false
+        createState.live.coursePlanList.forEach((item: any) => {
+          item.startTime = ''
+          item.endTime = ''
+        })
+      } catch {}
+    },
+    async onReset() {
+      if (this.selectType === 'noEnough') {
+        this.selectStatus = false
+      } else if (this.selectType === 'enough') {
+        await this._unLookCourse()
+      }
+      createState.coursePlanStatus = false
+    },
+    async onSure() {
+      await this._lookCourse(() => {
+        this.selectStatus = false
+        createState.active = 4
+      })
+    }
+  },
   render() {
     return (
       <div class={styles.arrange}>
-        <Calendar />
+        <Calendar
+          selectList={createState.selectCourseList}
+          list={this.calendarList}
+          maxDays={createState.live.courseNum || 0}
+          nextMonth={(date: Date) => this.getList(date)}
+          prevMonth={(date: Date) => this.getList(date)}
+          selectDay={this.onSelectDay}
+        />
 
         <Cell
           class={[styles.arrangeCell, 'mb12']}
           v-slots={{
             title: () => (
               <div class={styles.rTitle}>
-                <span>评测记录</span>
+                <span>已选择课程时间</span>
               </div>
             ),
             label: () => (
               <div class={styles.rTag}>
-                <Tag
-                  plain
-                  round
-                  closeable
-                  size="large"
-                  type="primary"
-                  class={styles.tag}
-                >
-                  周一 9:30~9:55
-                </Tag>
-                <Tag
-                  plain
-                  round
-                  closeable
-                  size="large"
-                  type="primary"
-                  class={styles.tag}
-                >
-                  周一 9:30~9:55
-                </Tag>
+                {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>
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup, styles.btnMore]}>
+          <div class={['btnGroup', 'btnMore']}>
             <Button
               block
               round
               type="primary"
               plain
               onClick={() => {
-                createState.active = 1
+                createState.active = 2
               }}
             >
               上一步
             </Button>
-            <Button block round type="primary" native-type="submit">
+            <Button block round type="primary" onClick={this.onSubmit}>
               下一步
             </Button>
           </div>
         </Sticky>
+
+        <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'
+                  ? '您所选择的上课时间未达到您输入的课时数,系统根据已选时间将自动按周顺延排课。'
+                  : '您已选择以下上课时间,请确认后点击确认按'}
+              </p>
+              {createState.live.coursePlanList &&
+                createState.live.coursePlanList.length > 0 &&
+                this.selectType === 'enough' && (
+                  <p class={styles.times}>
+                    {createState.live.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>
       </div>
     )
   }

+ 1 - 14
src/teacher/live-class/create-components/course-plan.module.less

@@ -2,19 +2,6 @@
   .courseTime {
     font-size: 14px;
     color: #999999;
-  }
-
-  .btnGroup {
-    padding: 0 14px;
-    padding-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
-        width: 48%;
-      }
-    }
+    line-height: 20px;
   }
 }

+ 51 - 32
src/teacher/live-class/create-components/course-plan.tsx

@@ -8,44 +8,63 @@ import ColFieldGroup from '@/components/col-field-group'
 export default defineComponent({
   name: 'course-plan',
   data() {
-    return {
-      list: [1, 2, 3]
+    return {}
+  },
+  async mounted() {
+    let list = createState.live.coursePlanList
+    let listLength = list.length || 0
+    console.log(list)
+    if (createState.live.courseNum > listLength) {
+      for (let i = 0; i < createState.live.courseNum - listLength; i++) {
+        await this.addPlan()
+      }
+    } else if (createState.live.courseNum < listLength) {
+      for (let i = 0; i < listLength - createState.live.courseNum; i++) {
+        await this.delPlan()
+      }
+    }
+  },
+  methods: {
+    async addPlan() {
+      let list = createState.live.coursePlanList || []
+      list.push({
+        plan: '',
+        startTime: '',
+        endTime: '',
+        classNum: list.length + 1
+      })
+      createState.live.coursePlanList = list
+    },
+    async delPlan(index?: number) {
+      let list = createState.live.coursePlanList || []
+      list.splice(index || list.length - 1, 1)
+      createState.live.coursePlanList = list
     }
   },
   render() {
     return (
-      <Form
-        class={styles.coursePlan}
-        onSubmit={() => (createState.active = 3)}
-        scrollToError
-      >
-        {this.list.map((item: any, index: number) => (
-          <ColFieldGroup>
-            <ColField
-              title={`第${index + 1}课`}
-              required
-              border={false}
-              v-slots={{
-                right: () => (
-                  <span class={styles.courseTime}>2022年4月18日11:40:17</span>
-                )
-              }}
-            >
-              <Field
-                name="lessonDesc"
-                placeholder="请输入课程计划"
-                rows="3"
-                maxlength={200}
-                autosize
-                rules={[{ required: true, message: '请输入课程计划' }]}
-                type="textarea"
-              />
-            </ColField>
-          </ColFieldGroup>
-        ))}
+      <Form class={styles.coursePlan} onSubmit={() => (createState.active = 3)}>
+        {/* scrollToError */}
+        {createState.live.coursePlanList &&
+          createState.live.coursePlanList.map((item: any) => (
+            <ColFieldGroup>
+              <ColField title={`第${item.classNum}课`} required border={false}>
+                <Field
+                  v-model={item.plan}
+                  name="plan"
+                  placeholder="请输入课程计划"
+                  rows="3"
+                  maxlength={200}
+                  autosize
+                  rules={[{ required: true, message: '请输入课程计划' }]}
+                  type="textarea"
+                />
+              </ColField>
+            </ColFieldGroup>
+          ))}
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup, styles.btnMore]}>
+          <div class={['btnGroup', 'btnMore']}>
             <Button
               block
               round

+ 0 - 14
src/teacher/live-class/create-components/course-start.module.less

@@ -1,18 +1,4 @@
 .courseStart {
-  .btnGroup {
-    padding: 0 14px;
-    padding-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
-        width: 48%;
-      }
-    }
-  }
-
   .infoField {
     width: 50vw;
     font-size: 16px;

+ 72 - 16
src/teacher/live-class/create-components/course-start.tsx

@@ -12,25 +12,56 @@ import {
   Tab,
   Tabs,
   Image,
-  Icon
+  Icon,
+  Popup,
+  DatetimePicker
 } from 'vant'
 import { defineComponent } from 'vue'
 import { createState } from './createState'
 import styles from './course-start.module.less'
 import ColUpload from '@/components/col-upload'
+import { verifiyNumberInteger } from '@/helpers/toolsValidate'
+import { formatterDate } from '@/helpers/utils'
 
 import activeButtonIcon from '@common/images/icon_checkbox.png'
 import inactiveButtonIcon from '@common/images/icon_checkbox_default.png'
+import dayjs from 'dayjs'
 
 export default defineComponent({
   name: 'course-start',
+  data() {
+    return {
+      dateStatus: false,
+      currentDate: new Date(),
+      minDate: dayjs().toDate(),
+      maxDate: new Date()
+    }
+  },
+  mounted() {
+    this.maxDate = dayjs(createState.selectCourseList[0].startTime)
+      .subtract(1, 'day')
+      .toDate()
+
+    createState.live.salesStartDate = dayjs(this.minDate).format('YYYY-MM-DD')
+    createState.live.salesEndDate = dayjs(this.maxDate).format('YYYY-MM-DD')
+  },
   methods: {
     tabChange(name: number) {
       createState.tabIndex = name
     },
     selectImg(val: string) {
-      createState.lessonGroup.lessonCoverUrl = ''
-      createState.lessonGroup.lessonCoverTemplateUrl = val
+      createState.live.backgroundPic = ''
+      createState.live.backgroundPicTemplate = val
+    },
+    onFormatterInt(val: any) {
+      if (val && val >= 1) {
+        return verifiyNumberInteger(val)
+      } else {
+        return ''
+      }
+    },
+    onConfirm(val: any) {
+      this.dateStatus = false
     }
   },
   render() {
@@ -43,19 +74,30 @@ export default defineComponent({
         <ColFieldGroup>
           <ColField title="开售日期" required>
             <Field
-              v-model={createState.lessonGroup.lessonName}
-              name="lessonName"
+              v-model={createState.live.salesStartDate}
+              name="salesStartDate"
               readonly
               isLink
               placeholder="请选择停售日期"
+              onClick={() => {
+                this.currentDate = dayjs(
+                  createState.live.salesStartDate
+                ).toDate()
+                this.dateStatus = true
+              }}
               rules={[{ required: true, message: '请选择停售日期' }]}
             />
           </ColField>
           <ColField title="停售日期" required>
             <Field
-              name="lessonSubjectName"
+              v-model={createState.live.salesEndDate}
+              name="salesEndDate"
               readonly
               isLink
+              onClick={() => {
+                this.currentDate = dayjs(createState.live.salesEndDate).toDate()
+                this.dateStatus = true
+              }}
               rules={[{ required: true, message: '请选择停售日期' }]}
               placeholder="请选择停售日期"
             />
@@ -71,11 +113,12 @@ export default defineComponent({
             }}
           >
             <Field
-              v-model={createState.lessonGroup.lessonPrice}
-              name="lessonPrice"
+              v-model={createState.live.mixStudentNum}
+              name="mixStudentNum"
               placeholder="请输入最低开课人数"
               type="number"
               maxlength={8}
+              formatter={this.onFormatterInt}
               rules={[{ required: true, message: '请输入最低开课人数' }]}
               v-slots={{
                 button: () => <span>人</span>
@@ -110,12 +153,12 @@ export default defineComponent({
             <p class={styles.photoTip}>模板图片将作为改课程封面为学员展示</p>
             {createState.tabIndex === 1 ? (
               <Field
-                name="lessonCoverTemplateUrl"
+                name="backgroundPicTemplate"
                 rules={[{ required: true, message: '请选择课程声部' }]}
                 v-slots={{
                   input: () => (
                     <RadioGroup
-                      v-model={createState.lessonGroup.lessonCoverTemplateUrl}
+                      v-model={createState.live.backgroundPicTemplate}
                     >
                       <Row justify="space-between" style={{ width: '100%' }}>
                         {createState.templateList.map((item: any) => (
@@ -151,7 +194,7 @@ export default defineComponent({
             ) : null}
             {createState.tabIndex == 2 ? (
               <Field
-                name="lessonCoverUrl"
+                name="backgroundPic"
                 rules={[{ required: true, message: '请选择课程声部' }]}
                 v-slots={{
                   input: () => (
@@ -166,11 +209,10 @@ export default defineComponent({
                           }}
                           onUploadChange={(val: any) => {
                             if (val) {
-                              createState.lessonGroup.lessonCoverTemplateUrl =
-                                ''
+                              createState.live.backgroundPicTemplate = ''
                             }
                           }}
-                          v-model={createState.lessonGroup.lessonCoverUrl}
+                          v-model={createState.live.backgroundPic}
                           class={styles.imgContainer}
                         />
                       </Col>
@@ -183,14 +225,14 @@ export default defineComponent({
         </ColFieldGroup>
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup, styles.btnMore]}>
+          <div class={['btnGroup', 'btnMore']}>
             <Button
               block
               round
               type="primary"
               plain
               onClick={() => {
-                createState.active = 1
+                createState.active = 3
               }}
             >
               上一步
@@ -200,6 +242,20 @@ export default defineComponent({
             </Button>
           </div>
         </Sticky>
+
+        <Popup show={this.dateStatus} position="bottom" round>
+          <DatetimePicker
+            type="date"
+            v-model={this.currentDate}
+            minDate={this.minDate}
+            maxDate={this.maxDate}
+            formatter={formatterDate}
+            onCancel={() => {
+              this.dateStatus = false
+            }}
+            onConfirm={this.onConfirm}
+          />
+        </Popup>
       </Form>
     )
   }

+ 43 - 37
src/teacher/live-class/create-components/course.tsx

@@ -6,32 +6,24 @@ import { ActionSheet, Button, Field, Form, Sticky } from 'vant'
 import { defineComponent } from 'vue'
 import styles from './course.module.less'
 import { createState } from './createState'
-import { verifyNumberIntegerAndFloat } from '@/helpers/toolsValidate'
+import {
+  verifiyNumberInteger,
+  verifyNumberIntegerAndFloat
+} from '@/helpers/toolsValidate'
 
 export default defineComponent({
   name: 'course',
   data() {
     return {
       subjectStatus: false,
-      classTimeStatus: false,
-      actions: [
-        {
-          name: '30'
-        },
-        {
-          name: '45'
-        },
-        {
-          name: '90'
-        }
-      ]
+      classTimeStatus: false
     }
   },
   computed: {
     choiceSubjectIds() {
       // 选择的科目编号
-      let ids = createState.lessonGroup.lessonSubject
-        ? Number(createState.lessonGroup.lessonSubject)
+      let ids = createState.live.subjectId
+        ? Number(createState.live.subjectId)
         : null
       return ids ? [ids] : []
     },
@@ -42,34 +34,46 @@ export default defineComponent({
     lessonSubjectName() {
       // 选择的科目
       let tempStr = ''
-      this.subjectList.forEach((parent: any) => {
-        parent.subjects &&
-          parent.subjects.forEach((sub: any) => {
-            if (this.choiceSubjectIds.includes(sub.id)) {
-              tempStr = sub.name
-            }
-          })
+      this.subjectList.forEach((item: any) => {
+        if (this.choiceSubjectIds.includes(item.id)) {
+          tempStr = item.name
+        }
       })
       return tempStr
     },
+    calcSingleRatePrice() {
+      let rate = createState.rate || 0
+      let nums = createState.live.courseNum
+      let price = createState.live.coursePrice || 0
+      return nums ? ((price / nums) * (1 - rate / 100)).toFixed(2) : 0
+    },
     calcRatePrice() {
       // 计算手续费
       let rate = createState.rate || 0
-      let price = createState.lessonGroup.lessonPrice || 0
+      let price = createState.live.coursePrice || 0
       return (price - (rate / 100) * price).toFixed(2)
     }
   },
   async mounted() {},
   methods: {
     onChoice(id: number) {
-      // createState.lessonGroup.lessonSubject = id
+      createState.live.subjectId = id
       this.subjectStatus = false
     },
     onFormatter(val: any) {
       return verifyNumberIntegerAndFloat(val)
     },
+    onFormatterInt(val: any) {
+      if (val && val >= 1) {
+        return verifiyNumberInteger(val)
+      } else {
+        return ''
+      }
+    },
     onSelect(action: any) {
-      console.log(action)
+      createState.live.singleCourseMinutes =
+        Number(action.name || 0) + Number(action.freeMinutes || 0)
+      createState.live.singleMins = Number(action.name || 0)
     }
   },
   render() {
@@ -82,8 +86,8 @@ export default defineComponent({
         <ColFieldGroup>
           <ColField title="课程名称" required>
             <Field
-              v-model={createState.lessonGroup.lessonName}
-              name="lessonName"
+              v-model={createState.live.name}
+              name="name"
               maxlength={50}
               placeholder="请输入您的课程名称"
               rules={[{ required: true, message: '请输入您的课程名称' }]}
@@ -92,7 +96,7 @@ export default defineComponent({
           <ColField title="课程声部" required>
             <Field
               modelValue={this.lessonSubjectName}
-              name="lessonSubjectName"
+              name="subjectId"
               readonly
               isLink
               onClick={() => {
@@ -105,7 +109,8 @@ export default defineComponent({
 
           <ColField title="课程介绍" required border={false}>
             <Field
-              name="lessonDesc"
+              v-model={createState.live.courseIntroduce}
+              name="courseIntroduce"
               placeholder="请输入课程介绍"
               rows="3"
               maxlength={200}
@@ -119,10 +124,10 @@ export default defineComponent({
         <ColFieldGroup>
           <ColField title="课时数" required>
             <Field
-              v-model={createState.lessonGroup.lessonPrice}
-              name="lessonPrice"
+              v-model={createState.live.courseNum}
+              name="courseNum"
               placeholder="请输入您的课时数"
-              formatter={this.onFormatter}
+              formatter={this.onFormatterInt}
               type="number"
               maxlength={8}
               rules={[{ required: true, message: '请输入您的课时数' }]}
@@ -133,8 +138,8 @@ export default defineComponent({
           </ColField>
           <ColField title="单课时时长" required>
             <Field
-              modelValue={this.lessonSubjectName}
-              name="lessonSubjectName"
+              modelValue={createState.live.singleMins}
+              name="singleMins"
               readonly
               isLink
               onClick={() => {
@@ -146,8 +151,8 @@ export default defineComponent({
           </ColField>
           <ColField title="课程组售价" required>
             <Field
-              v-model={createState.lessonGroup.lessonPrice}
-              name="lessonPrice"
+              v-model={createState.live.coursePrice}
+              name="coursePrice"
               placeholder="请输入您的课程组售价"
               formatter={this.onFormatter}
               type="number"
@@ -163,7 +168,7 @@ export default defineComponent({
         <div class={styles['class-info-tip']}>
           <p>扣除手续费后您的课程预计收入为:</p>
           <p>
-            单课时<span>{this.calcRatePrice}</span>元/人
+            单课时<span>{this.calcSingleRatePrice}</span>元/人
           </p>
           <p>
             课程组总收入<span>{this.calcRatePrice}</span>元/人
@@ -182,6 +187,7 @@ export default defineComponent({
         <ColPopup v-model={this.subjectStatus}>
           <SubjectModel
             selectType="Radio"
+            single
             subjectList={createState.subjectList}
             choiceSubjectIds={this.choiceSubjectIds}
             onChoice={this.onChoice}

+ 27 - 6
src/teacher/live-class/create-components/createState.ts

@@ -1,5 +1,12 @@
 import { reactive } from 'vue'
 
+export const basePlan = {
+  plan: '',
+  startTime: '',
+  endTime: '',
+  classNum: 1
+}
+
 export const createState = reactive({
   subjectList: [], // 声部列表
   active: 1,
@@ -11,11 +18,25 @@ export const createState = reactive({
     'https://daya.ks3-cn-beijing.ksyun.com/202108/ShHJ1Bb.png',
     'https://daya.ks3-cn-beijing.ksyun.com/202110/Sn76BUQ.png'
   ], // 模板列表
-  lessonGroup: {
-    lessonSubject: '',
-    lessonName: '',
-    lessonPrice: null as any,
-    lessonCoverTemplateUrl: '',
-    lessonCoverUrl: ''
+  selectCourseList: [] as any, // 选择课程列表
+  coursePlanStatus: false, // 是否有锁课程
+  live: {
+    name: '',
+    subjectId: null as any,
+    courseIntroduce: '',
+    courseNum: null as any,
+    singleCourseMinutes: 0,
+    singleMins: null as any,
+    coursePrice: null as any,
+    salesStartDate: '',
+    salesEndDate: '',
+    mixStudentNum: null as any,
+    backgroundPic: '',
+    backgroundPicTemplate: '',
+    coursePlanList: [
+      {
+        ...basePlan
+      }
+    ]
   }
 })

+ 0 - 13
src/teacher/live-class/create-components/detail.module.less

@@ -1,15 +1,2 @@
 .detail {
-  .btnGroup {
-    padding: 0 14px;
-    padding-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
-        width: 48%;
-      }
-    }
-  }
 }

+ 67 - 18
src/teacher/live-class/create-components/detail.tsx

@@ -1,55 +1,104 @@
 import CoursePlanStep from '@/business-components/course-plan-step'
 import SectionDetail from '@/business-components/section-detail'
 import UserDetail from '@/business-components/user-detail'
-import { Button, Sticky } from 'vant'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import { Button, Sticky, Toast } from 'vant'
 import { defineComponent } from 'vue'
 import { createState } from './createState'
 import styles from './detail.module.less'
+import dayjs from 'dayjs'
 
 export default defineComponent({
   name: 'detail',
+  computed: {
+    userInfo() {
+      return {
+        headUrl: state.user.data?.headUrl,
+        username: state.user.data?.username,
+        startTime: createState.live.coursePlanList[0].startTime || '',
+        buyNum: 0,
+        lessonPrice: createState.live.coursePrice,
+        lessonNum: createState.live.courseNum,
+        lessonDesc: createState.live.courseIntroduce,
+        lessonCoverUrl:
+          createState.live.backgroundPic ||
+          createState.live.backgroundPicTemplate,
+        lessonName: createState.live.name
+      }
+    },
+    courseInfo() {
+      interface IProps {
+        courseTime: string
+        coursePlan: string
+        videoPosterUrl?: string
+        id?: number | string
+      }
+      let tempArr = [] as IProps[]
+      const coursePlanList = createState.live.coursePlanList || []
+      coursePlanList.forEach((item: any) => {
+        tempArr.push({
+          courseTime: `${dayjs(item.startTime).format('YYYY-MM-DD')} ${dayjs(
+            item.startTime
+          ).format('HH:mm')}~${dayjs(item.endTime).format('HH:mm')}`,
+          coursePlan: item.plan
+        })
+      })
+      return tempArr || []
+    }
+  },
+  methods: {
+    async onSubmit() {
+      try {
+        const params = {
+          ...createState.live,
+          backgroundPic:
+            createState.live.backgroundPic ||
+            createState.live.backgroundPicTemplate,
+          teacherId: state.user.data?.userId
+        }
+        await request.post('/api-teacher/courseGroup/addLiveCourse', {
+          data: params
+        })
+        Toast.success('创建成功')
+        setTimeout(() => {
+          postMessage({ api: 'back' })
+        }, 1000)
+      } catch {}
+    }
+  },
   render() {
     return (
       <div class={[styles['detail']]}>
-        <UserDetail
-          userInfo={{
-            headUrl: 'https://img.yzcdn.cn/vant/cat.jpeg',
-            username: '小酷老师',
-            lessonPrice: 0,
-            lessonCoverUrl: 'https://img.yzcdn.cn/vant/cat.jpeg',
-            lessonName: '竖笛演奏'
-          }}
-        />
+        <UserDetail userInfo={this.userInfo} />
         <SectionDetail>
-          <p class={styles.introduction}>
-            小酷老师带您零基础学习竖笛,通过4节课的学习掌握竖笛演奏的基本方式,培养娘好的吐息习惯。
-          </p>
+          <p class={styles.introduction}>{this.userInfo.lessonDesc}</p>
         </SectionDetail>
 
         <SectionDetail
-          title="课程列表"
+          title="课程安排"
           icon="courseList"
           titleShow={false}
           class={'mb12'}
           contentStyle={{ paddingTop: '0' }}
         >
-          <CoursePlanStep />
+          <CoursePlanStep courseInfo={this.courseInfo} />
         </SectionDetail>
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup, styles.btnMore]}>
+          <div class={['btnGroup', 'btnMore']}>
             <Button
               block
               round
               type="primary"
               plain
               onClick={() => {
-                createState.active = 1
+                createState.active = 5
               }}
             >
               返回编辑
             </Button>
-            <Button block round type="primary" native-type="submit">
+            <Button block round type="primary" onClick={this.onSubmit}>
               创建成功
             </Button>
           </div>

+ 58 - 49
src/teacher/teacher-cert/cert-one.tsx

@@ -1,12 +1,13 @@
-import { CellGroup, DatetimePicker, Field, Popup, Toast } from "vant"
-import { defineComponent } from "vue";
-import dayjs from "dayjs";
-import { checkIDCard } from "@/helpers/validate";
-import ColField from "@/components/col-field";
-import { teacherState } from "./teacherState";
-import styles from './cert-one.module.less';
-import ColFieldGroup from "@/components/col-field-group";
-import { state } from "@/state";
+import { CellGroup, DatetimePicker, Field, Popup, Toast } from 'vant'
+import { defineComponent } from 'vue'
+import dayjs from 'dayjs'
+import { checkIDCard } from '@/helpers/validate'
+import ColField from '@/components/col-field'
+import { teacherState } from './teacherState'
+import styles from './cert-one.module.less'
+import ColFieldGroup from '@/components/col-field-group'
+import { state } from '@/state'
+import { formatterDate } from '@/helpers/utils'
 
 export default defineComponent({
   name: 'certOne',
@@ -14,23 +15,25 @@ export default defineComponent({
     return {
       maxDate: new Date(),
       popupShow: false,
-      popupDate: new Date(),
+      popupDate: new Date()
     }
   },
   computed: {
     userAuth() {
       // 判断是否实名过
-      const users = state.user.data || {};
+      const users = state.user.data || {}
       return !!(users.idCardNo && users.realName)
     }
   },
   mounted() {
     if (this.userAuth) {
-      const users = state.user.data || {};
-      teacherState.teacherCert.realName = users.realName;
-      teacherState.teacherCert.idCardNo = users.idCardNo;
-      teacherState.teacherCert.gender = users.gender;
-      teacherState.teacherCert.birthdate = dayjs(users.birthdate).format('YYYY-MM-DD')
+      const users = state.user.data || {}
+      teacherState.teacherCert.realName = users.realName
+      teacherState.teacherCert.idCardNo = users.idCardNo
+      teacherState.teacherCert.gender = users.gender
+      teacherState.teacherCert.birthdate = dayjs(users.birthdate).format(
+        'YYYY-MM-DD'
+      )
     }
   },
   methods: {
@@ -41,8 +44,8 @@ export default defineComponent({
         return
       }
       if (!checkIDCard(idCardNo || '')) {
-        Toast('请填写正确的身份证号码');
-        return false;
+        Toast('请填写正确的身份证号码')
+        return false
       }
 
       console.log(this.getSex(idCardNo))
@@ -50,42 +53,32 @@ export default defineComponent({
       teacherState.teacherCert.gender = this.getSex(idCardNo)
     },
     getBirth(idCard: string | null) {
-      let birthday = "";
-      if (idCard != null && idCard != "") {
+      let birthday = ''
+      if (idCard != null && idCard != '') {
         if (idCard.length == 15) {
-          birthday = "19" + idCard.slice(6, 12);
+          birthday = '19' + idCard.slice(6, 12)
         } else if (idCard.length == 18) {
-          birthday = idCard.slice(6, 14);
+          birthday = idCard.slice(6, 14)
         }
-        birthday = birthday.replace(/(.{4})(.{2})/, "$1-$2-");
+        birthday = birthday.replace(/(.{4})(.{2})/, '$1-$2-')
         //通过正则表达式来指定输出格式为:1990-01-01
       }
-      return birthday;
+      return birthday
     },
     getSex(idCard: string | null): number {
-      let sex = 1;
+      let sex = 1
       if (idCard && parseInt(idCard.slice(-2, -1)) % 2 == 1) {
-        sex = 1;
+        sex = 1
       } else {
-        sex = 0;
+        sex = 0
       }
-      return sex;
+      return sex
     },
     onConfirm(_date: any) {
-      teacherState.teacherCert.birthdate = dayjs(this.popupDate).format('YYYY-MM-DD')
-      this.popupShow = false;
-    },
-    formatter(type: any, val: any) {
-      if (type === 'year') {
-        return `${val}年`;
-      }
-      if (type === 'month') {
-        return `${val}月`;
-      }
-      if (type === 'day') {
-        return `${val}日`;
-      }
-      return val;
+      teacherState.teacherCert.birthdate = dayjs(this.popupDate).format(
+        'YYYY-MM-DD'
+      )
+      this.popupShow = false
     },
     sexChange(num: number) {
       if (!this.userAuth) {
@@ -118,8 +111,24 @@ export default defineComponent({
           </ColField>
           <ColField title="性别" required border={false}>
             <div class={styles.radioGroup}>
-              <div onClick={() => this.sexChange(1)} class={[styles.radio, teacherState.teacherCert.gender === 1 ? styles.active : null]}>男</div>
-              <div onClick={() => this.sexChange(0)} class={[styles.radio, teacherState.teacherCert.gender === 0 ? styles.active : null]}>女</div>
+              <div
+                onClick={() => this.sexChange(1)}
+                class={[
+                  styles.radio,
+                  teacherState.teacherCert.gender === 1 ? styles.active : null
+                ]}
+              >
+                男
+              </div>
+              <div
+                onClick={() => this.sexChange(0)}
+                class={[
+                  styles.radio,
+                  teacherState.teacherCert.gender === 0 ? styles.active : null
+                ]}
+              >
+                女
+              </div>
             </div>
           </ColField>
           <ColField title="出生日期" required>
@@ -127,7 +136,7 @@ export default defineComponent({
               v-model={teacherState.teacherCert.birthdate}
               name="出生日期"
               disabled={this.userAuth}
-              onClick-input={() => this.popupShow = true}
+              onClick-input={() => (this.popupShow = true)}
               readonly
               isLink={!this.userAuth}
               placeholder="请选择您的出生日期"
@@ -141,12 +150,12 @@ export default defineComponent({
             type="date"
             close-on-popstate={true}
             maxDate={this.maxDate}
-            onCancel={() => this.popupShow = false}
+            onCancel={() => (this.popupShow = false)}
             onConfirm={this.onConfirm}
-            formatter={this.formatter}>
-          </DatetimePicker>
+            formatter={formatterDate}
+          ></DatetimePicker>
         </Popup>
       </ColFieldGroup>
     )
   }
-})
+})

+ 0 - 13
src/teacher/teacher-cert/index.module.less

@@ -1,16 +1,3 @@
 .teacher-cert {
   overflow: hidden;
-  .btnGroup {
-    padding: 0 14px 15px;
-    // margin-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
-        width: 48%;
-      }
-    }
-  }
 }

+ 112 - 61
src/teacher/teacher-cert/index.tsx

@@ -1,33 +1,37 @@
-
-import { Button, Sticky, Toast } from "vant";
-import { defineComponent } from "vue";
-import styles from './index.module.less';
-import CertInfo from "./cert-info";
-import ColProtocol from "@/components/col-protocol";
-import { teacherState } from "./teacherState";
-import Steps from './steps';
+import { Button, Sticky, Toast } from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+import CertInfo from './cert-info'
+import ColProtocol from '@/components/col-protocol'
+import { teacherState } from './teacherState'
+import Steps from './steps'
 import CertOne from './cert-one'
 import CertTwo from './cert-two'
-import CertThree from "./cert-three";
-import { checkIDCard } from "@/helpers/validate";
-import request from "@/helpers/request";
-import ColResult from "@/components/col-result";
-import { state } from "@/state";
-import { stat } from "fs";
+import CertThree from './cert-three'
+import { checkIDCard } from '@/helpers/validate'
+import request from '@/helpers/request'
+import ColResult from '@/components/col-result'
+import { state } from '@/state'
+import { stat } from 'fs'
 
 export default defineComponent({
   name: 'teacherCert',
   data() {
-    const query = this.$route.query;
+    const query = this.$route.query
     return {
-      agreeStatus: false,
+      agreeStatus: false
     }
   },
   async mounted() {
     try {
       // 老师入驻状态 0、未申请 UNPAALY、未申请 DOING、审核中 PASS、通过 UNPASS、不通过
       const entryStatus = state.user.data?.entryStatus || 0
-      teacherState.authStatus = entryStatus === 'DOING' || entryStatus === 'PASS' || entryStatus === 'UNPASS' ? true : false
+      teacherState.authStatus =
+        entryStatus === 'DOING' ||
+        entryStatus === 'PASS' ||
+        entryStatus === 'UNPASS'
+          ? true
+          : false
       // 如果已经认证,则不用获取声部信息
       if (teacherState.authStatus) {
         teacherState.active = teacherState.authStatus ? 4 : 1
@@ -35,7 +39,7 @@ export default defineComponent({
       }
       if (teacherState.subjectList.length <= 0) {
         const res = await request.get('/api-teacher/subject/subjectSelect')
-        teacherState.subjectList = res.data || [];
+        teacherState.subjectList = res.data || []
       }
     } catch {
       //
@@ -47,7 +51,7 @@ export default defineComponent({
     },
     userAuth() {
       // 判断是否实名过
-      const users = state.user.data || {};
+      const users = state.user.data || {}
       return !!(users.idCardNo && users.realName)
     }
   },
@@ -61,13 +65,13 @@ export default defineComponent({
       const idCardNo = teacherState.teacherCert.idCardNo
       if (!this.userAuth) {
         if (!checkIDCard(idCardNo || '')) {
-          Toast('请填写正确的身份证号码');
-          return false;
+          Toast('请填写正确的身份证号码')
+          return false
         }
       }
 
       if (!this.agreeStatus) {
-        Toast('请阅读并同意协议');
+        Toast('请阅读并同意协议')
         return
       }
 
@@ -86,7 +90,7 @@ export default defineComponent({
             }
           })
         }
-        teacherState.active = 2;
+        teacherState.active = 2
       } catch {
         //
       }
@@ -96,7 +100,7 @@ export default defineComponent({
         Toast('请选择教授科目')
         return
       }
-      teacherState.active = 3;
+      teacherState.active = 3
     },
     async onSubmit() {
       try {
@@ -104,54 +108,101 @@ export default defineComponent({
           data: teacherState.teacherCert
         })
         Toast('提交成功')
-        teacherState.active = 4;
+        teacherState.active = 4
       } catch {
         //
       }
     },
     prev() {
-      teacherState.active = teacherState.active - 1;
+      teacherState.active = teacherState.active - 1
     }
   },
   render() {
     return (
       <div class={styles['teacher-cert']}>
-        {!teacherState.authStatus ? <CertInfo /> : <div>
-          {teacherState.active != 4 ? <Steps style={{ marginBottom: '12px' }} /> : null}
-          {teacherState.active === 1 ? (
-            <>
-              <CertOne />
-              <Sticky position="bottom" offsetBottom={0}>
-                <div class={styles.btnGroup}>
-                  <ColProtocol v-model={this.agreeStatus} style={{ paddingLeft: 0, paddingRight: 0 }} />
-                  <Button block round onClick={this.next} type="primary" text="下一步" />
-                </div>
-              </Sticky>
-            </>
-          ) : null}
-          {teacherState.active === 2 ? <>
-            <CertTwo />
-            <Sticky position="bottom" offsetBottom={0}>
-              <div class={[styles.btnGroup, styles.btnMore]}>
-                <Button block round type="primary" plain onClick={this.prev}>上一步</Button>
-                <Button block round onClick={this.next2} type="primary" text="下一步" />
-              </div>
-            </Sticky>
-          </> : null}
-          {teacherState.active === 3 ? <>
-            <CertThree />
-            <Sticky position="bottom" offsetBottom={0}>
-              <div class={[styles.btnGroup, styles.btnMore]}>
-                <Button block round type="primary" plain onClick={this.prev}>上一步</Button>
-                <Button block round onClick={this.onSubmit} type="primary" text="提交审核" />
-              </div>
-            </Sticky>
-          </> : null}
+        {!teacherState.authStatus ? (
+          <CertInfo />
+        ) : (
+          <div>
+            {teacherState.active != 4 ? (
+              <Steps style={{ marginBottom: '12px' }} />
+            ) : null}
+            {teacherState.active === 1 ? (
+              <>
+                <CertOne />
+                <Sticky position="bottom" offsetBottom={0}>
+                  <div class={'btnGroup'}>
+                    <ColProtocol
+                      v-model={this.agreeStatus}
+                      style={{ paddingLeft: 0, paddingRight: 0 }}
+                    />
+                    <Button
+                      block
+                      round
+                      onClick={this.next}
+                      type="primary"
+                      text="下一步"
+                    />
+                  </div>
+                </Sticky>
+              </>
+            ) : null}
+            {teacherState.active === 2 ? (
+              <>
+                <CertTwo />
+                <Sticky position="bottom" offsetBottom={0}>
+                  <div class={['btnGroup', 'btnMore']}>
+                    <Button
+                      block
+                      round
+                      type="primary"
+                      plain
+                      onClick={this.prev}
+                    >
+                      上一步
+                    </Button>
+                    <Button
+                      block
+                      round
+                      onClick={this.next2}
+                      type="primary"
+                      text="下一步"
+                    />
+                  </div>
+                </Sticky>
+              </>
+            ) : null}
+            {teacherState.active === 3 ? (
+              <>
+                <CertThree />
+                <Sticky position="bottom" offsetBottom={0}>
+                  <div class={['btnGroup', 'btnMore']}>
+                    <Button
+                      block
+                      round
+                      type="primary"
+                      plain
+                      onClick={this.prev}
+                    >
+                      上一步
+                    </Button>
+                    <Button
+                      block
+                      round
+                      onClick={this.onSubmit}
+                      type="primary"
+                      text="提交审核"
+                    />
+                  </div>
+                </Sticky>
+              </>
+            ) : null}
 
-          {/* 提交完数据之后显示状态页 */}
-          {teacherState.active === 4 ? <ColResult tips="开通成功" /> : null}
-        </div>}
+            {/* 提交完数据之后显示状态页 */}
+            {teacherState.active === 4 ? <ColResult tips="开通成功" /> : null}
+          </div>
+        )}
       </div>
     )
   }
-})
+})

+ 0 - 14
src/teacher/video-class/class-content.module.less

@@ -51,18 +51,4 @@
       }
     }
   }
-
-  .btnGroup {
-    padding: 0 14px;
-    padding-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
-        width: 48%;
-      }
-    }
-  }
 }

+ 1 - 1
src/teacher/video-class/class-content.tsx

@@ -150,7 +150,7 @@ export default defineComponent({
         </Button>
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup, styles.btnMore]}>
+          <div class={['btnGroup', 'btnMore']}>
             <Button
               block
               round

+ 1 - 1
src/teacher/video-class/class-info.tsx

@@ -261,7 +261,7 @@ export default defineComponent({
         </ColFieldGroup>
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup]}>
+          <div class={['btnGroup']}>
             <Button block round type="primary" native-type="submit">
               下一步
             </Button>

+ 2 - 16
src/teacher/video-class/create-submit.module.less

@@ -2,22 +2,8 @@
   // margin-bottom: 12px;
 
   .introduction {
-    color: #7A7A7A;
+    color: #7a7a7a;
     line-height: 23px;
     padding-bottom: 8px;
   }
-
-  .btnGroup {
-    padding: 0 14px;
-    padding-bottom: 15px;
-  }
-  .btnMore {
-    display: flex;
-    justify-content: space-between;
-    :global {
-      .van-button {
-        width: 48%;
-      }
-    }
-  }
-}
+}

+ 50 - 34
src/teacher/video-class/create-submit.tsx

@@ -1,21 +1,20 @@
-import { defineComponent } from "vue";
-import styles from "./create-submit.module.less";
-import UserDetail from "@/business-components/user-detail";
-import SectionDetail from "@/business-components/section-detail";
-import CourseVideoItem from "@/business-components/course-video-item";
-import { Button, Sticky, Toast } from "vant";
-import { createState } from "./createState";
-import { state } from "@/state";
-import request from "@/helpers/request";
-import { postMessage } from "@/helpers/native-message";
-
+import { defineComponent } from 'vue'
+import styles from './create-submit.module.less'
+import UserDetail from '@/business-components/user-detail'
+import SectionDetail from '@/business-components/section-detail'
+import CourseVideoItem from '@/business-components/course-video-item'
+import { Button, Sticky, Toast } from 'vant'
+import { createState } from './createState'
+import { state } from '@/state'
+import request from '@/helpers/request'
+import { postMessage } from '@/helpers/native-message'
 
 export default defineComponent({
-  name: "CreateSubmit",
+  name: 'CreateSubmit',
   computed: {
     userInfo() {
-      const videoDetail = createState.lessonGroup;
-      const users = state.user.data || {};
+      const videoDetail = createState.lessonGroup
+      const users = state.user.data || {}
       return {
         username: users.username,
         headUrl: users.headUrl,
@@ -23,40 +22,42 @@ export default defineComponent({
         buyNum: 0,
         lessonDesc: videoDetail.lessonDesc,
         lessonPrice: videoDetail.lessonPrice,
-        lessonCoverUrl: videoDetail.lessonCoverTemplateUrl || videoDetail.lessonCoverUrl,
+        lessonCoverUrl:
+          videoDetail.lessonCoverTemplateUrl || videoDetail.lessonCoverUrl,
         lessonNum: createState.lessonList.length
       }
     },
     lessonList() {
-      return createState.lessonList || [];
+      return createState.lessonList || []
     }
   },
   methods: {
     async onSubmit() {
       try {
-        const videoDetail = createState.lessonGroup;
+        const videoDetail = createState.lessonGroup
         let params = {
           lessonList: this.lessonList,
           lessonGroup: {
             ...videoDetail,
-            lessonCoverUrl: videoDetail.lessonCoverTemplateUrl || videoDetail.lessonCoverUrl,
+            lessonCoverUrl:
+              videoDetail.lessonCoverTemplateUrl || videoDetail.lessonCoverUrl
           }
         }
         if (createState.groupId) {
           await request.post('/api-teacher/videoLessonGroup/update', {
             data: params
-          });
-          Toast.success('修改成功');
+          })
+          Toast.success('修改成功')
         } else {
           await request.post('/api-teacher/videoLessonGroup/add', {
             data: params
-          });
-          Toast.success('创建成功');
+          })
+          Toast.success('创建成功')
         }
         setTimeout(() => {
           postMessage({ api: 'back' })
-        }, 1000);
-      } catch { }
+        }, 1000)
+      } catch {}
     }
   },
   render() {
@@ -67,23 +68,38 @@ export default defineComponent({
           <p class={styles.introduction}>{this.userInfo.lessonDesc}</p>
         </SectionDetail>
 
-        <SectionDetail title="课程列表" icon="courseList" class='mb12'>
+        <SectionDetail title="课程列表" icon="courseList" class="mb12">
           {this.lessonList.map((item: any) => (
-            <CourseVideoItem class={'mb12'} detail={{
-              title: item.videoTitle,
-              content: item.videoContent,
-              imgUrl: item.coverUrl
-            }} />
+            <CourseVideoItem
+              class={'mb12'}
+              detail={{
+                title: item.videoTitle,
+                content: item.videoContent,
+                imgUrl: item.coverUrl
+              }}
+            />
           ))}
         </SectionDetail>
 
         <Sticky offsetBottom={0} position="bottom">
-          <div class={[styles.btnGroup, styles.btnMore]}>
-            <Button block round type="primary" plain onClick={() => { createState.active = 2 }}>返回编辑</Button>
-            <Button block round type="primary" onClick={this.onSubmit}>创建完成</Button>
+          <div class={['btnGroup', 'btnMore']}>
+            <Button
+              block
+              round
+              type="primary"
+              plain
+              onClick={() => {
+                createState.active = 2
+              }}
+            >
+              返回编辑
+            </Button>
+            <Button block round type="primary" onClick={this.onSubmit}>
+              创建完成
+            </Button>
           </div>
         </Sticky>
       </div>
     )
   }
-})
+})

+ 1 - 1
src/views/order-detail/userAuth/index.tsx

@@ -40,7 +40,7 @@ export default defineComponent({
           </ColField>
         </ColFieldGroup>
 
-        <div class={[styles.btnGroup]}>
+        <div class={['btnGroup']}>
           <Button block round type="primary" native-type="submit">
             确定
           </Button>