Browse Source

更新优化组件

lex-xin 2 years ago
parent
commit
a4f7fbe0fa
33 changed files with 494 additions and 216 deletions
  1. 9 1
      README.md
  2. 44 0
      src/business-components/course-video-item/index.module.less
  3. 52 0
      src/business-components/course-video-item/index.tsx
  4. 21 0
      src/business-components/section-detail/index.module.less
  5. 41 0
      src/business-components/section-detail/index.tsx
  6. 72 0
      src/business-components/user-detail/index.module.less
  7. 12 7
      src/business-components/user-detail/index.tsx
  8. BIN
      src/common/images/icon_course_introduction.png
  9. BIN
      src/common/images/icon_course_list.png
  10. BIN
      src/common/images/icon_video_stop.png
  11. 6 6
      src/components/col-popup/index.tsx
  12. 5 1
      src/components/col-upload/index.tsx
  13. 0 8
      src/router/routes-common.ts
  14. 0 6
      src/teacher/music-cert/index.module.less
  15. 6 5
      src/teacher/music-cert/index.tsx
  16. 0 6
      src/teacher/teacher-cert/cert-info.module.less
  17. 6 4
      src/teacher/teacher-cert/cert-info.tsx
  18. 0 8
      src/teacher/teacher-cert/cert-two.tsx
  19. 27 21
      src/teacher/teacher-cert/index.tsx
  20. 14 0
      src/teacher/video-class/class-content.module.less
  21. 9 2
      src/teacher/video-class/class-content.tsx
  22. 13 7
      src/teacher/video-class/class-info.module.less
  23. 86 8
      src/teacher/video-class/class-info.tsx
  24. 20 0
      src/teacher/video-class/create-submit.module.less
  25. 26 1
      src/teacher/video-class/create-submit.tsx
  26. 0 14
      src/teacher/video-class/create.module.less
  27. 10 21
      src/teacher/video-class/create.tsx
  28. 13 0
      src/teacher/video-class/createState.tsx
  29. 0 55
      src/views/module/user-detail/index.module.less
  30. 0 10
      src/views/video-detail/index.module.less
  31. 0 25
      src/views/video-detail/index.tsx
  32. 1 0
      tsconfig.json
  33. 1 0
      vite.config.ts

+ 9 - 1
README.md

@@ -39,7 +39,15 @@ See [Configuration Reference](https://vitejs.dev/config/).
 /src/teacher -- 老师端页面目录
 /src/teacher -- 老师端页面目录
 /src/views 两端共用页面,路由最好配置到 routes-common 文件中
 /src/views 两端共用页面,路由最好配置到 routes-common 文件中
 
 
-/src/views/module -- 公用组件
+/src/components -- 公用组件
+1、图片上传
+2、图片裁切
+3、图形验证码
+4、协议
+5、视屏上传
+
+/src/business-components -- 业务组件
+1、详情头部
 ```
 ```
 
 
 ### 公用尺寸
 ### 公用尺寸

+ 44 - 0
src/business-components/course-video-item/index.module.less

@@ -0,0 +1,44 @@
+.videoSection {
+  padding: 0 !important;
+  .videoImg {
+    width: 100px;
+    height: 70px;
+    position: relative;
+    border-radius: 4px;
+    overflow: hidden;
+    :global {
+      .van-image {
+        width: inherit;
+        height: inherit;
+      }
+    }
+
+    .videoStop {
+      position: absolute;
+      top: 0;
+      right: 0;
+      left: 0;
+      bottom: 0;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+
+  .videoTitle {
+    padding-left: 8px;
+    font-size: 13px;
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    justify-content: space-around;
+    .videoTitleText {
+      font-size: 15px;
+      color: #000;
+    }
+    .videoTitleContent {
+      color: #7A7A7A;
+      line-height: 18px;
+    }
+  }
+}

+ 52 - 0
src/business-components/course-video-item/index.tsx

@@ -0,0 +1,52 @@
+import { defineComponent, PropType } from "vue";
+import styles from './index.module.less';
+import { Cell, Icon, Image } from "vant";
+
+import videoStop from '@common/images/icon_video_stop.png';
+
+/**
+ * @description: 课程视频列表项
+ * @param {title} 视频标题
+ * @param {imgUrl} 视频封面图
+ * @param {content} 视频内容
+ */
+interface IDetail {
+  id: number;
+  title: string;
+  content?: string;
+  imgUrl?: string;
+}
+
+export default defineComponent({
+  name: "CourseVideoItem",
+  props: {
+    detail: {
+      type: Object as PropType<IDetail>,
+      required: true
+    },
+    onPlay: {
+      type: Function as PropType<(detail: IDetail) => void>,
+      default: () => {}
+    }
+  },
+  render() {
+    return (
+      <Cell class={styles.videoSection} onClick={() => this.onPlay(this.detail)} v-slots={{
+        icon: () => (
+          <div class={styles.videoImg}>
+            <Image src={this.detail.imgUrl} fit="cover" />
+            <Icon class={styles.videoStop} name={videoStop} size={26} />
+          </div>
+        ),
+        title: () => (
+          <div class={styles.videoTitle}>
+            <p class={styles.videoTitleText}>{this.detail.title}</p>
+            <p class={[styles.videoTitleContent, 'van-multi-ellipsis--l2']}>
+              {this.detail.content}
+            </p>
+          </div>
+        )
+      }}></Cell>
+    )
+  }
+})

+ 21 - 0
src/business-components/section-detail/index.module.less

@@ -0,0 +1,21 @@
+.section-detail {
+  position: relative;
+  margin: 12px 14px 0;
+  border-radius: 12px;
+  background-color: #fff;
+  overflow: hidden;
+
+  .name {
+    font-size: 16px;
+    color: #333333;
+    font-weight: 500;
+    padding-left: 8px;
+  }
+
+  :global {
+    .van-cell {
+      padding: 10px 12px;
+      font-size: 14px;
+    }
+  }
+}

+ 41 - 0
src/business-components/section-detail/index.tsx

@@ -0,0 +1,41 @@
+import { Cell, CellGroup, Icon } from "vant";
+import { defineComponent, PropType } from "vue";
+import styles from './index.module.less';
+
+import courseIntroduction from '@common/images/icon_course_introduction.png';
+import courseList from '@common/images/icon_course_list.png';
+
+type IconType = 'courseIntroduction' | 'courseList';
+
+export default defineComponent({
+  name: "SectionDetail",
+  props: {
+    icon: {
+      type: String as PropType<IconType>,
+      default: 'courseIntroduction'
+    },
+    title: {
+      type: String,
+      default: '课程介绍'
+    },
+    border: {
+      type: Boolean,
+      default: true
+    }
+  },
+  render() {
+    return (
+      <div class={styles['section-detail']}>
+        <CellGroup>
+          <Cell center border={this.border} v-slots={{
+            icon: () => (<Icon name={this.icon === 'courseIntroduction' ? courseIntroduction : courseList} size="18" />),
+            title: () => (<div class={styles.name}>{this.title}</div>),
+          }}></Cell>
+          <Cell center>
+            {this.$slots.default && this.$slots.default()}
+          </Cell>
+        </CellGroup>
+      </div>
+    )
+  }
+})

+ 72 - 0
src/business-components/user-detail/index.module.less

@@ -0,0 +1,72 @@
+.userDetail {
+  .banner {
+    width: 100%;
+    height: 210px;
+    overflow: hidden;
+    vertical-align: middle;
+  }
+
+  .userInfo {
+    overflow: hidden;
+
+    .avatar {
+      width: 24px;
+      height: 24px;
+      border-radius: 50%;
+      overflow: hidden;
+    }
+
+    .name {
+      padding-left: 8px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #333333;
+      line-height: 22px;
+      display: flex;
+      align-items: center;
+    }
+
+    .buyNum {
+      color: #FF802C;
+      font-size: 14px;
+      display: flex;
+      align-items: center;
+      &::before {
+        content: ' ';
+        display: inline-block;
+        width: 1px;
+        height: 12px;
+        margin: 0 8px;
+        background: #d3d3d3;
+      }
+    }
+
+    .info {
+      font-size: 16px;
+      font-weight: 400;
+      color: var(--van-primary);
+      line-height: 17px;
+    }
+
+    .userTitle {
+      font-size: 18px;
+      color: #1a1a1a;
+      font-weight: 500;
+    }
+    :global {
+      .van-cell {
+        padding: 14px;
+      }
+
+      .van-cell__title,
+      .van-cell__value {
+        display: flex;
+        align-items: center;
+      }
+
+      .van-cell__value {
+        justify-content: flex-end;
+      }
+    }
+  }
+}

+ 12 - 7
src/views/module/user-detail/index.tsx → src/business-components/user-detail/index.tsx

@@ -22,26 +22,31 @@ export default defineComponent({
   },
   },
   render() {
   render() {
     return (
     return (
-      <>
+      <div class={styles.userDetail}>
         <Image class={[styles.banner]} src="https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png" fit="cover" />
         <Image class={[styles.banner]} src="https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png" fit="cover" />
         <CellGroup class={styles.userInfo}>
         <CellGroup class={styles.userInfo}>
+          <Cell title="从0开始学竖笛视频课" titleClass={styles.userTitle} />
           <Cell v-slots={{
           <Cell v-slots={{
             icon: () => <Image class={styles.avatar} src="https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png" />,
             icon: () => <Image class={styles.avatar} src="https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png" />,
-            title: () => (<div class={styles.name}>张星</div>),
-            value: () => (<div class={styles.info}>开课时间:2月28日 19:30</div>),
+            title: () => (<div class={styles.name}>张星
+
+              <div class={styles.buyNum}>6人已购买</div>
+              {/* <Tag style={{ marginLeft: '8px' }} color="#FFF1DE" textColor="#FF9300">12课时</Tag> */}
+            </div>),
+            value: () => (<div class={styles.info}>¥120/4课时</div>),
           }}></Cell>
           }}></Cell>
-          <Cell v-slots={{
+          {/* <Cell v-slots={{
             title: () => (<div class={styles.price}>
             title: () => (<div class={styles.price}>
               <div class={styles.number}>
               <div class={styles.number}>
                 <span class={styles.priceText}>¥</span>
                 <span class={styles.priceText}>¥</span>
                 <span class={styles.priceNum}>99</span>
                 <span class={styles.priceNum}>99</span>
               </div>
               </div>
-              <Tag color="#FFF1DE" textColor="#FF9300">12课时</Tag>
+              
             </div>),
             </div>),
             value: () => (<div class={styles.info}>已购 6 人</div>),
             value: () => (<div class={styles.info}>已购 6 人</div>),
-          }}></Cell>
+          }}></Cell> */}
         </CellGroup>
         </CellGroup>
-      </>
+      </div>
     )
     )
   }
   }
 })
 })

BIN
src/common/images/icon_course_introduction.png


BIN
src/common/images/icon_course_list.png


BIN
src/common/images/icon_video_stop.png


+ 6 - 6
src/components/col-popup/index.tsx

@@ -5,7 +5,7 @@ import qs from 'query-string';
 export default defineComponent({
 export default defineComponent({
   name: 'col-popup',
   name: 'col-popup',
   props: {
   props: {
-    popupStatus: {
+    modelValue: {
       type: Boolean,
       type: Boolean,
       default: false
       default: false
     }
     }
@@ -16,7 +16,7 @@ export default defineComponent({
     }
     }
   },
   },
   watch: {
   watch: {
-    popupStatus(val) {
+    modelValue(val) {
       this.hashState()
       this.hashState()
     }
     }
   },
   },
@@ -28,15 +28,15 @@ export default defineComponent({
   },
   },
   methods: {
   methods: {
     onHash() {
     onHash() {
-      this.$emit("update:popupStatus", false);
+      this.$emit("update:modelValue", false);
     },
     },
     onPopupClose(val: boolean) {
     onPopupClose(val: boolean) {
-      this.$emit("update:popupStatus", val);
+      this.$emit("update:modelValue", val);
       this.hashState();
       this.hashState();
     },
     },
     hashState() {
     hashState() {
       // 打开弹窗
       // 打开弹窗
-      if (this.popupStatus) {
+      if (this.modelValue) {
         const splitUrl = window.location.hash.slice(1).split('?');
         const splitUrl = window.location.hash.slice(1).split('?');
         const query = qs.parse(splitUrl[1]);
         const query = qs.parse(splitUrl[1]);
         let times = 0
         let times = 0
@@ -60,7 +60,7 @@ export default defineComponent({
   },
   },
   render() {
   render() {
     return (
     return (
-      <Popup ref="protocolPopup" show={this.popupStatus} transitionAppear={true} position="bottom" style={{ height: '100%' }}>
+      <Popup ref="protocolPopup" show={this.modelValue} transitionAppear={true} position="bottom" style={{ height: '100%' }}>
         {this.$slots.default && this.$slots.default()}
         {this.$slots.default && this.$slots.default()}
       </Popup>
       </Popup>
     )
     )

+ 5 - 1
src/components/col-upload/index.tsx

@@ -21,6 +21,10 @@ export default defineComponent({
     cropper: { // 是否进行裁切
     cropper: { // 是否进行裁切
       type: Boolean,
       type: Boolean,
       default: false
       default: false
+    },
+    options: { // 裁切需要参数
+      type: Object,
+      default: {}
     }
     }
   },
   },
   mounted() {
   mounted() {
@@ -80,7 +84,7 @@ export default defineComponent({
             <Icon name={iconUploader} size="32" />
             <Icon name={iconUploader} size="32" />
             <p class={styles.uploaderText}>{this.tips}</p>
             <p class={styles.uploaderText}>{this.tips}</p>
           </div>}
           </div>}
-          <ColCropper getFile={this.getFile} />
+          <ColCropper option={this.options} getFile={this.getFile} />
         </div> : (
         </div> : (
           // @ts-ignore
           // @ts-ignore
           <Uploader afterRead={this.afterRead} beforeRead={this.beforeRead} beforeDelete={this.beforeDelete}
           <Uploader afterRead={this.afterRead} beforeRead={this.beforeRead} beforeDelete={this.beforeDelete}

+ 0 - 8
src/router/routes-common.ts

@@ -1,14 +1,6 @@
 // 需要登录的路由
 // 需要登录的路由
 export const router = [
 export const router = [
   {
   {
-    path: '/videoDetail',
-    name: 'videoDetail',
-    component: () => import('@/views/video-detail/index'),
-    meta: {
-      title: '视频课'
-    }
-  },
-  {
     path: '/orderDetail',
     path: '/orderDetail',
     name: 'orderDetail',
     name: 'orderDetail',
     component: () => import('@/views/order-detail/index'),
     component: () => import('@/views/order-detail/index'),

+ 0 - 6
src/teacher/music-cert/index.module.less

@@ -2,7 +2,6 @@
   background-color: #fff;
   background-color: #fff;
   padding: 12px;
   padding: 12px;
   position: relative;
   position: relative;
-  padding-bottom: 75px;
 
 
   h2 {
   h2 {
     font-size: 16px;
     font-size: 16px;
@@ -27,11 +26,6 @@
   }
   }
 
 
   .btn-group {
   .btn-group {
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    padding: 12px;
     background-color: #fff;
     background-color: #fff;
   }
   }
 }
 }

+ 6 - 5
src/teacher/music-cert/index.tsx

@@ -1,5 +1,5 @@
 import { defineComponent } from "vue";
 import { defineComponent } from "vue";
-import { Button, Image, Toast } from 'vant';
+import { Button, Image, Sticky, Toast } from 'vant';
 import styles from './index.module.less';
 import styles from './index.module.less';
 import request from "@/helpers/request";
 import request from "@/helpers/request";
 import { state } from "@/state";
 import { state } from "@/state";
@@ -56,10 +56,11 @@ export default defineComponent({
             <p class={styles['cert-img']}>
             <p class={styles['cert-img']}>
               <Image src="https://daya.ks3-cn-beijing.ksyun.com/202110/Sn76BUQ.png" width="100%" height="150px" fit="cover" />
               <Image src="https://daya.ks3-cn-beijing.ksyun.com/202110/Sn76BUQ.png" width="100%" height="150px" fit="cover" />
             </p>
             </p>
-
-            <div class={styles["btn-group"]}>
-              <Button round block type="primary" disabled={this.authStatus === '1'} onClick={this.onClick}>立即认证</Button>
-            </div>
+            <Sticky position="bottom" offsetBottom={0}>
+              <div class={styles["btn-group"]}>
+                <Button round block type="primary" disabled={this.authStatus === '1'} onClick={this.onClick}>立即认证</Button>
+              </div>
+            </Sticky>
           </div>
           </div>
         }
         }
 
 

+ 0 - 6
src/teacher/teacher-cert/cert-info.module.less

@@ -3,7 +3,6 @@
   padding: 12px;
   padding: 12px;
   min-height: 100vh;
   min-height: 100vh;
   position: relative;
   position: relative;
-  padding-bottom: 75px;
 
 
   h2 {
   h2 {
     font-size: 16px;
     font-size: 16px;
@@ -28,11 +27,6 @@
   }
   }
 
 
   .btn-group {
   .btn-group {
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    right: 0;
     padding: 12px;
     padding: 12px;
-    background-color: #fff;
   }
   }
 }
 }

+ 6 - 4
src/teacher/teacher-cert/cert-info.tsx

@@ -1,4 +1,4 @@
-import { Button, Image } from "vant";
+import { Button, Image, Sticky } from "vant";
 import { defineComponent, Transition } from "vue";
 import { defineComponent, Transition } from "vue";
 import styles from './cert-info.module.less';
 import styles from './cert-info.module.less';
 import { teacherState } from "./teacherState";
 import { teacherState } from "./teacherState";
@@ -55,9 +55,11 @@ export default defineComponent({
           在艺术的殿堂中,为他人照亮前进的道路,用自己的经验和点拨,传播艺术的种子,获取硕果。
           在艺术的殿堂中,为他人照亮前进的道路,用自己的经验和点拨,传播艺术的种子,获取硕果。
         </p>
         </p>
 
 
-        <div class={styles["btn-group"]}>
-          <Button round block type="primary" disabled={teacherState.authStatus} onClick={this.onClick}>立即认证</Button>
-        </div>
+        <Sticky position="bottom" offsetBottom={0}>
+          <div class={styles["btn-group"]}>
+            <Button round block type="primary" disabled={teacherState.authStatus} onClick={this.onClick}>立即认证</Button>
+          </div>
+        </Sticky>
       </div>
       </div>
     )
     )
   }
   }

+ 0 - 8
src/teacher/teacher-cert/cert-two.tsx

@@ -26,7 +26,6 @@ export default defineComponent({
       return ids
       return ids
     },
     },
     subjectList() { // 学科列表
     subjectList() { // 学科列表
-      console.log(teacherState.subjectList)
       return teacherState.subjectList || []
       return teacherState.subjectList || []
     },
     },
     choiceSubject() { // 选择的科目
     choiceSubject() { // 选择的科目
@@ -43,13 +42,6 @@ export default defineComponent({
   },
   },
   methods: {
   methods: {
     onChoice(item: any) {
     onChoice(item: any) {
-      // this.subjectList.forEach((parent: any) => {
-      //   parent.subjects && parent.subjects.forEach((sub: any) => {
-      //     if (item.includes(sub.id)) {
-      //       this.choiceSubject.push(sub as never)
-      //     }
-      //   })
-      // })
       teacherState.teacherCert.subjectId = item.join(',') || ''
       teacherState.teacherCert.subjectId = item.join(',') || ''
 
 
       this.subjectStatus = false
       this.subjectStatus = false

+ 27 - 21
src/teacher/teacher-cert/index.tsx

@@ -1,5 +1,5 @@
 
 
-import { Button, Toast } from "vant";
+import { Button, Sticky, Toast } from "vant";
 import { defineComponent } from "vue";
 import { defineComponent } from "vue";
 import styles from './index.module.less';
 import styles from './index.module.less';
 import CertInfo from "./cert-info";
 import CertInfo from "./cert-info";
@@ -30,7 +30,7 @@ export default defineComponent({
       teacherState.authStatus = entryStatus === 1 || entryStatus === 2 ? true : false
       teacherState.authStatus = entryStatus === 1 || entryStatus === 2 ? true : false
       console.log(teacherState.authStatus)
       console.log(teacherState.authStatus)
       // 如果已经认证,则不用获取声部信息
       // 如果已经认证,则不用获取声部信息
-      if(teacherState.authStatus) {
+      if (teacherState.authStatus) {
         teacherState.active = teacherState.authStatus ? 4 : 1
         teacherState.active = teacherState.authStatus ? 4 : 1
         return
         return
       }
       }
@@ -55,7 +55,7 @@ export default defineComponent({
   methods: {
   methods: {
     async next() {
     async next() {
       const realName = teacherState.teacherCert.realName
       const realName = teacherState.teacherCert.realName
-      if(!realName) {
+      if (!realName) {
         Toast('请填写真实姓名')
         Toast('请填写真实姓名')
         return
         return
       }
       }
@@ -70,7 +70,7 @@ export default defineComponent({
         return
         return
       }
       }
 
 
-      if(!teacherState.teacherCert.birthdate) {
+      if (!teacherState.teacherCert.birthdate) {
         Toast('请选择出生日期')
         Toast('请选择出生日期')
         return
         return
       }
       }
@@ -89,7 +89,7 @@ export default defineComponent({
       teacherState.active = 2;
       teacherState.active = 2;
     },
     },
     next2() {
     next2() {
-      if(!teacherState.teacherCert.subjectId) {
+      if (!teacherState.teacherCert.subjectId) {
         Toast('请选择教授科目')
         Toast('请选择教授科目')
         return
         return
       }
       }
@@ -118,29 +118,35 @@ export default defineComponent({
           {teacherState.active === 1 ? (
           {teacherState.active === 1 ? (
             <>
             <>
               <CertOne />
               <CertOne />
-              <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 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 }
+          ) : null}
           {teacherState.active === 2 ? <>
           {teacherState.active === 2 ? <>
             <CertTwo />
             <CertTwo />
-            <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>
-          </> : null }
+            <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 ? <>
           {teacherState.active === 3 ? <>
             <CertThree />
             <CertThree />
-            <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>
-          </> : null }
+            <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.active === 4 ? <ColResult tips="开通成功" /> : null }
+          {teacherState.active === 4 ? <ColResult tips="开通成功" /> : null}
         </div>}
         </div>}
       </div>
       </div>
     )
     )

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

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

+ 9 - 2
src/teacher/video-class/class-content.tsx

@@ -2,7 +2,7 @@ import ColField from "@/components/col-field";
 import ColFieldGroup from "@/components/col-field-group";
 import ColFieldGroup from "@/components/col-field-group";
 import ColUpload from "@/components/col-upload";
 import ColUpload from "@/components/col-upload";
 import ColUploadVideo from "@/components/col-upload-video";
 import ColUploadVideo from "@/components/col-upload-video";
-import { Button, Col, Dialog, Field, Icon, Row } from "vant";
+import { Button, Col, Dialog, Field, Icon, Row, Sticky } from "vant";
 import { defineComponent } from "vue";
 import { defineComponent } from "vue";
 import styles from './class-content.module.less';
 import styles from './class-content.module.less';
 
 
@@ -10,7 +10,7 @@ export default defineComponent({
   name: "ClassContent",
   name: "ClassContent",
   data() {
   data() {
     return {
     return {
-      dataList: [1, 2]
+      dataList: [1]
     }
     }
   },
   },
   methods: {
   methods: {
@@ -68,6 +68,13 @@ export default defineComponent({
         ))}
         ))}
 
 
         <Button class={styles['add-item']} block icon="add-o" onClick={this.addItem}>添加课程</Button>
         <Button class={styles['add-item']} block icon="add-o" onClick={this.addItem}>添加课程</Button>
+
+        <Sticky offsetBottom={0} position="bottom">
+            <div class={[styles.btnGroup, styles.btnMore]}>
+              <Button block round type="primary" plain>上一步</Button>
+              <Button block round type="primary">提交</Button>
+            </div>
+          </Sticky>
       </div>
       </div>
     )
     )
   }
   }

+ 13 - 7
src/teacher/video-class/class-info.module.less

@@ -1,5 +1,18 @@
 .classInfo {
 .classInfo {
   margin-top: 12px;
   margin-top: 12px;
+
+  .imgContainer {
+    width: 150px;
+    height: 100px;
+    border-radius: 10px;
+    overflow: hidden;
+    margin: 0 0 12px;
+  }
+
+  .btnGroup {
+    padding: 0 14px;
+    padding-bottom: 15px;
+  }
 }
 }
 
 
 .class-info-tip {
 .class-info-tip {
@@ -20,10 +33,3 @@
   padding: 5px 0 12px;
   padding: 5px 0 12px;
 }
 }
 
 
-.imgContainer {
-  width: 150px;
-  height: 100px;
-  border-radius: 10px;
-  overflow: hidden;
-  margin: 0 0 12px;
-}

+ 86 - 8
src/teacher/video-class/class-info.tsx

@@ -1,32 +1,88 @@
 import ColField from "@/components/col-field";
 import ColField from "@/components/col-field";
 import ColFieldGroup from "@/components/col-field-group";
 import ColFieldGroup from "@/components/col-field-group";
+import ColPopup from "@/components/col-popup";
 import ColUpload from "@/components/col-upload";
 import ColUpload from "@/components/col-upload";
-import { Col, Field, Form, Image, Row } from "vant";
+import request from "@/helpers/request";
+import { create } from "domain";
+import { Button, Col, Field, Form, Image, Row, Sticky } from "vant";
 import { defineComponent } from "vue";
 import { defineComponent } from "vue";
+import SubjectModel from "../teacher-cert/module/subject-model";
 import styles from "./class-info.module.less";
 import styles from "./class-info.module.less";
+import { createState } from './createState'
 
 
 export default defineComponent({
 export default defineComponent({
   name: "ClassInfo",
   name: "ClassInfo",
   data() {
   data() {
     return {
     return {
-      url: ''
+      subjectStatus: false
     }
     }
   },
   },
+  computed: {
+    choiceSubjectIds() { // 选择的科目编号
+      let ids = createState.createVideo.subjectIds ? createState.createVideo.subjectIds.split(',') : [];
+      ids = ids.map((item: any) => Number(item))
+      return ids
+    },
+    subjectList() { // 学科列表
+      return createState.subjectList || []
+    },
+    choiceSubject() { // 选择的科目
+      let tempArr: any[] = []
+      this.subjectList.forEach((parent: any) => {
+        parent.subjects && parent.subjects.forEach((sub: any) => {
+          if (this.choiceSubjectIds.includes(sub.id)) {
+            tempArr.push(sub as never)
+          }
+        })
+      })
+      return tempArr
+    }
+  },
+  async mounted() {
+    try {
+      if (createState.subjectList.length <= 0) {
+        const res = await request.get('/api-teacher/subject/queryPageTree', {
+          params: {
+            rows: 100,
+            page: 1
+          }
+        })
+        createState.subjectList = res.data.rows || [];
+      }
+    } catch {
+      //
+    }
+  },
+  methods: {
+    onSubmit(values: any) {
+      console.log(values)
+    },
+    onChoice(item: any) {
+      createState.createVideo.subjectIds = item.join(',') || ''
+
+      this.subjectStatus = false
+    },
+  },
   render() {
   render() {
     return (
     return (
-      <Form class={styles.classInfo}>
+      <Form class={styles.classInfo} onSubmit={this.onSubmit}>
         <ColFieldGroup>
         <ColFieldGroup>
           <ColField title="课程名称" required>
           <ColField title="课程名称" required>
             <Field
             <Field
-              name="课程名称"
+              v-model={createState.createVideo.courseName}
+              name="courseName"
               placeholder="请输入您的课程名称"
               placeholder="请输入您的课程名称"
+              rules={[{ required: true, message: '请输入您的课程名称' }]}
             />
             />
           </ColField>
           </ColField>
           <ColField title="课程声部" required>
           <ColField title="课程声部" required>
             <Field
             <Field
-              name="课程声部"
+              v-model={createState.createVideo.subjectIds}
+              name="subjectIds"
               readonly
               readonly
               isLink
               isLink
+              onClick={() => { this.subjectStatus = true }}
+              rules={[{ required: true, message: '请选择课程声部' }]}
               placeholder="请选择课程声部"
               placeholder="请选择课程声部"
             />
             />
           </ColField>
           </ColField>
@@ -35,10 +91,12 @@ export default defineComponent({
         <ColFieldGroup>
         <ColFieldGroup>
           <ColField title="课程介绍" required border={false}>
           <ColField title="课程介绍" required border={false}>
             <Field
             <Field
-              name="课程介绍"
+              v-model={createState.createVideo.courseRemark}
+              name="courseRemark"
               placeholder="请输入课程介绍"
               placeholder="请输入课程介绍"
               rows="3"
               rows="3"
               autosize
               autosize
+              rules={[{ required: true, message: '请选择课程声部' }]}
               type="textarea"
               type="textarea"
             />
             />
           </ColField>
           </ColField>
@@ -47,8 +105,11 @@ export default defineComponent({
         <ColFieldGroup>
         <ColFieldGroup>
           <ColField title="课程组售价" required>
           <ColField title="课程组售价" required>
             <Field
             <Field
-              name="课程组售价"
+              v-model={createState.createVideo.coursePrice}
+              name="coursePrice"
               placeholder="请输入您的课程组售价"
               placeholder="请输入您的课程组售价"
+              type="number"
+              rules={[{ required: true, message: '请选择课程声部' }]}
               v-slots={{
               v-slots={{
                 button: () => (<span>元</span>)
                 button: () => (<span>元</span>)
               }}
               }}
@@ -67,6 +128,9 @@ export default defineComponent({
             <p class={styles.photoTip}>模板图片将作为改课程封面为学员展示</p>
             <p class={styles.photoTip}>模板图片将作为改课程封面为学员展示</p>
 
 
             <Field
             <Field
+              v-model={createState.createVideo.courseImg}
+              name="courseImg"
+              rules={[{ required: true, message: '请选择课程声部' }]}
               v-slots={{
               v-slots={{
                 input: () => (
                 input: () => (
                   <Row justify="space-between">
                   <Row justify="space-between">
@@ -80,7 +144,11 @@ export default defineComponent({
                       <Image class={styles.imgContainer} src="https://daya.ks3-cn-beijing.ksyun.com/202201/Sv7wlrW.png" />
                       <Image class={styles.imgContainer} src="https://daya.ks3-cn-beijing.ksyun.com/202201/Sv7wlrW.png" />
                     </Col>
                     </Col>
                     <Col span={12} class={styles.imgContainer}>
                     <Col span={12} class={styles.imgContainer}>
-                      <ColUpload cropper v-model={this.url} class={styles.imgContainer} />
+                      <ColUpload cropper options={{
+                        fixedNumber: [3 , 2],
+                        autoCropWidth: 750,
+                        autoCropHeight: 500,
+                      }} v-model={createState.createVideo.courseImg} class={styles.imgContainer} />
                     </Col>
                     </Col>
                   </Row>
                   </Row>
                 )
                 )
@@ -88,6 +156,16 @@ export default defineComponent({
             />
             />
           </ColField>
           </ColField>
         </ColFieldGroup>
         </ColFieldGroup>
+
+        <Sticky offsetBottom={0} position="bottom">
+          <div class={[styles.btnGroup]}>
+            <Button block round type="primary" native-type="submit">下一步</Button>
+          </div>
+        </Sticky>
+
+        <ColPopup v-model={this.subjectStatus}>
+          <SubjectModel max={1} subjectList={this.subjectList} choiceSubjectIds={this.choiceSubjectIds} onChoice={this.onChoice} />
+        </ColPopup>
       </Form>
       </Form>
     )
     )
   }
   }

+ 20 - 0
src/teacher/video-class/create-submit.module.less

@@ -1,3 +1,23 @@
 .createSubmit {
 .createSubmit {
   // margin-bottom: 12px;
   // margin-bottom: 12px;
+
+  .introduction {
+    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%;
+      }
+    }
+  }
 }
 }

+ 26 - 1
src/teacher/video-class/create-submit.tsx

@@ -1,6 +1,10 @@
 import { defineComponent } from "vue";
 import { defineComponent } from "vue";
 import styles from "./create-submit.module.less";
 import styles from "./create-submit.module.less";
-import UserDetail from "@/views/module/user-detail";
+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 } from "vant";
+
 
 
 export default defineComponent({
 export default defineComponent({
   name: "CreateSubmit",
   name: "CreateSubmit",
@@ -8,6 +12,27 @@ export default defineComponent({
     return (
     return (
       <div class={[styles.createSubmit, 'mb12']}>
       <div class={[styles.createSubmit, 'mb12']}>
         <UserDetail />
         <UserDetail />
+        <SectionDetail>
+          <p class={styles.introduction}>小酷老师带您零基础学习竖笛,通过4节课的学习掌握竖笛演奏的基本方式,培养娘好的吐息习惯。</p>
+        </SectionDetail>
+
+        <SectionDetail title="课程列表" icon="courseList">
+          { [1,2,3,1,2,3,1,2,3].map(item => (
+            <CourseVideoItem class={'mb12'} detail={{
+              id: 1,
+              title: "竖笛演奏基础",
+              content: "使学生初步了解竖笛的构造,学会吹奏姿势掌握基本呼吸掌握基本呼吸掌握基本呼吸方法。",
+              imgUrl: 'https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png'
+            }} />
+          )) }
+        </SectionDetail>
+
+        <Sticky offsetBottom={0} position="bottom">
+            <div class={[styles.btnGroup, styles.btnMore]}>
+              <Button block round type="primary" plain>返回编辑</Button>
+              <Button block round type="primary">创建完成</Button>
+            </div>
+          </Sticky>
       </div>
       </div>
     )
     )
   }
   }

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

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

+ 10 - 21
src/teacher/video-class/create.tsx

@@ -1,5 +1,5 @@
 import ColUpload from "@/components/col-upload";
 import ColUpload from "@/components/col-upload";
-import { Button, Grid, GridItem, Icon } from "vant";
+import { Button, Grid, GridItem, Icon, Sticky } from "vant";
 import { defineComponent } from "vue";
 import { defineComponent } from "vue";
 import styles from './create.module.less';
 import styles from './create.module.less';
 import ClassInfo from "./class-info";
 import ClassInfo from "./class-info";
@@ -14,13 +14,13 @@ export default defineComponent({
   name: 'Create',
   name: 'Create',
   data() {
   data() {
     return {
     return {
-      active: 3,
+      active: 1,
     }
     }
   },
   },
   render() {
   render() {
     return (
     return (
       <div class={styles['video-create']}>
       <div class={styles['video-create']}>
-        { this.active <= 2 ? <Grid style={{ paddingTop: '15px' }} direction="horizontal" columnNum="2">
+        {this.active <= 2 ? <Grid style={{ paddingTop: '15px' }} direction="horizontal" columnNum="2">
           <GridItem v-slots={{
           <GridItem v-slots={{
             default: () => (
             default: () => (
               <>
               <>
@@ -37,30 +37,19 @@ export default defineComponent({
               </>
               </>
             )
             )
           }} />
           }} />
-        </Grid> : null }
+        </Grid> : null}
         {/* 课程信息 */}
         {/* 课程信息 */}
-        { this.active === 1 ? <>
+        {this.active === 1 ? <>
           <ClassInfo />
           <ClassInfo />
-          <div class={[styles.btnGroup]}>
-            <Button block round type="primary">下一步</Button>
-          </div>
-        </> : null }
+        </> : null}
         {/* 课程内容 */}
         {/* 课程内容 */}
-        { this.active === 2 ? <>
+        {this.active === 2 ? <>
           <ClassContent />
           <ClassContent />
-          <div class={[styles.btnGroup, styles.btnMore]}>
-            <Button block round type="primary" plain>上一步</Button>
-            <Button block round type="primary">提交</Button>
-          </div>
-        </> : null }
+        </> : null}
         {/* 预览 */}
         {/* 预览 */}
-        { this.active === 3 ? <>
+        {this.active === 3 ? <>
           <CreateSubmit />
           <CreateSubmit />
-          <div class={[styles.btnGroup, styles.btnMore]}>
-            <Button block round type="primary" plain>返回编辑</Button>
-            <Button block round type="primary">创建完成</Button>
-          </div>
-        </> : null }
+        </> : null}
 
 
       </div>
       </div>
     )
     )

+ 13 - 0
src/teacher/video-class/createState.tsx

@@ -0,0 +1,13 @@
+import { reactive } from "vue";
+
+export const createState = reactive({
+  active: 1,
+  subjectList: [], // 声部列表
+  createVideo: {
+    courseName: '',
+    subjectIds: null as any,
+    courseRemark: '',
+    coursePrice: null,
+    courseImg: '',
+  }
+})

+ 0 - 55
src/views/module/user-detail/index.module.less

@@ -1,55 +0,0 @@
-.banner {
-  width: 100%;
-  height: 210px;
-  overflow: hidden;
-  vertical-align: middle;
-}
-
-.userInfo {
-  overflow: hidden;
-
-  .avatar {
-    width: 24px;
-    height: 24px;
-    border-radius: 50%;
-    overflow: hidden;
-  }
-  .name {
-    padding-left: 8px;
-    font-size: 16px;
-    font-weight: 500;
-    color: #333333;
-    line-height: 22px;
-  }
-
-  .info {
-    font-size: 12px;
-    font-weight: 400;
-    color: #6A6A6A;
-    line-height: 17px;
-  }
-  .price {
-    display: flex;
-    align-items: center;
-    .number {
-      padding-right: 12px;
-      color: #FA6400;
-      font-size: 18px;
-    }
-    .priceText {
-      font-size: 12px;
-    }
-  }
-  :global {
-    .van-cell {
-      padding: 14px;
-    }
-    .van-cell__title, .van-cell__value {
-      display: flex;
-      align-items: center;
-    }
-    .van-cell__value {
-      justify-content: flex-end;
-    }
-  }
-}

+ 0 - 10
src/views/video-detail/index.module.less

@@ -1,10 +0,0 @@
-.video-detail {
-  padding: 12px;
-  .banner {
-    width: 100%;
-    height: 145px;
-    border-radius: 12px;
-    overflow: hidden;
-  }
-
-}

+ 0 - 25
src/views/video-detail/index.tsx

@@ -1,25 +0,0 @@
-import { defineComponent } from "vue";
-import { Cell, CellGroup, Icon, Image } from "vant";
-import styles from './index.module.less';
-
-import UserDetail from "../module/user-detail";
-
-export default defineComponent({
-  name: "VideoDetail",
-  render() {
-    return (
-      <div class={styles['video-detail']}>
-        <Image class={[styles.banner, 'mb12']} src="https://daya.ks3-cn-beijing.ksyun.com/202201/SvB6tqR.png" fit="cover" />
-
-        <UserDetail class='mb12' />
-
-        <CellGroup>
-          <Cell v-slots={{
-            icon: () => (<Icon name="close" size="22" />),
-            title: () => (<div class={styles.name}>张星</div>),
-          }}></Cell>
-      </CellGroup>
-      </div>
-    )
-  }
-})

+ 1 - 0
tsconfig.json

@@ -23,6 +23,7 @@
       "@/*": ["src/*"],
       "@/*": ["src/*"],
       "@common/*": ["src/common/*"],
       "@common/*": ["src/common/*"],
       "@components/*": ["src/components/*"],
       "@components/*": ["src/components/*"],
+      "@business-components/*": ["src/business-components/*"],
       "@store/*": ["src/store/*"],
       "@store/*": ["src/store/*"],
       "@views/*": ["src/views/*"],
       "@views/*": ["src/views/*"],
     }
     }

+ 1 - 0
vite.config.ts

@@ -37,6 +37,7 @@ export default defineConfig({
       '@': resolve('./src'),
       '@': resolve('./src'),
       '@common': resolve('./src/common'),
       '@common': resolve('./src/common'),
       '@components': resolve('./src/components'),
       '@components': resolve('./src/components'),
+      '@business-components': resolve('./src/business-components'),
       '@store': resolve('./src/store'),
       '@store': resolve('./src/store'),
       '@views': resolve('./src/views')
       '@views': resolve('./src/views')
     }
     }