소스 검색

更新组件

lex 2 년 전
부모
커밋
c0e8b0258d

+ 1 - 1
auto-imports.d.ts

@@ -1,5 +1,5 @@
 // Generated by 'unplugin-auto-import'
 export {}
 declare global {
-  const ElMessage: typeof import('element-plus/es')['ElMessage']
+
 }

+ 1 - 0
components.d.ts

@@ -5,6 +5,7 @@ import '@vue/runtime-core'
 
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
+    Pagination: typeof import('./src/components/pagination/index.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
   }

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 8583 - 1
package-lock.json


+ 21 - 23
src/components/musicLIstItem/index.tsx

@@ -9,34 +9,32 @@ export default defineComponent({
   name: 'musicLIstItem',
   setup() {
     return () => (
-      <>
-        <div>
-          <div class={classes.itemWrap}>
-            <div class={classes.left}>
-              <div class={classes.imgWrap}>
-                <img src={music} alt="" />
-              </div>
-              <div class={classes.textWrap}>
-                <p>
-                  孤勇者(《英雄联盟:双城之战》主题曲) <span>作曲: 钱雷</span>
-                </p>
-                <div class={classes.authorInfo}>
-                  <img class={classes.icon} src={icon} alt="" />
-                  <span class={classes.authorName}>李佳怡</span>
-                  <div class={classes.tagList}>
-                    <div class={classes.tag}>单簧管</div>
-                    <div class={classes.tag}>圆号</div>
-                  </div>
+      <div>
+        <div class={classes.itemWrap}>
+          <div class={classes.left}>
+            <div class={classes.imgWrap}>
+              <img src={music} alt="" />
+            </div>
+            <div class={classes.textWrap}>
+              <p>
+                孤勇者(《英雄联盟:双城之战》主题曲) <span>作曲: 钱雷</span>
+              </p>
+              <div class={classes.authorInfo}>
+                <img class={classes.icon} src={icon} alt="" />
+                <span class={classes.authorName}>李佳怡</span>
+                <div class={classes.tagList}>
+                  <div class={classes.tag}>单簧管</div>
+                  <div class={classes.tag}>圆号</div>
                 </div>
               </div>
             </div>
-            <div class={classes.right}>
-              <div class={classes.touchButton}>点播</div>
-              <img class={classes.arrow} src={arrow} alt="" />
-            </div>
+          </div>
+          <div class={classes.right}>
+            <div class={classes.touchButton}>点播</div>
+            <img class={classes.arrow} src={arrow} alt="" />
           </div>
         </div>
-      </>
+      </div>
     )
   }
 })

+ 11 - 0
src/components/pagination/index.module.less

@@ -0,0 +1,11 @@
+.pagination-container {
+  background: #fff;
+  padding: 24px 16px 32px;
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+}
+.pagination-container.hidden {
+  display: none;
+}

+ 178 - 0
src/components/pagination/index.tsx

@@ -0,0 +1,178 @@
+import { ElPagination } from 'element-plus'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'pagination',
+  props: {
+    total: {
+      required: true,
+      type: Number
+    },
+    page: {
+      type: Number,
+      default: 1
+    },
+    limit: {
+      type: Number,
+      default: 10
+    },
+    pageSizes: {
+      type: Array,
+      default: [10, 20, 30, 50]
+    },
+    layout: {
+      type: String,
+      default: 'total,sizes,prev, pager, next, jumper'
+    },
+    background: {
+      type: Boolean,
+      default: true
+    },
+    autoScroll: {
+      type: Boolean,
+      default: true
+    },
+    hidden: {
+      type: Boolean,
+      default: false
+    },
+    sync: {
+      type: Boolean,
+      default: false
+    },
+    saveKey: {
+      type: String,
+      default: ''
+    }
+  },
+  methods: {
+    handleSizeChange(val: number) {
+      this.$emit('update:page', 1)
+      // this.$emit('pagination', { page: this.page, limit: val })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    },
+    handleCurrentChange(val: number) {
+      // this.$emit('pagination', { page: val, limit: this.limit })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    }
+  },
+  render() {
+    return (
+      <div
+        class={[styles['pagination-container'], this.hidden && styles.hidden]}
+      >
+        <ElPagination
+          v-model:currentPage={this.page}
+          pageSizes={this.pageSizes as any}
+          pageSize={this.limit}
+          background
+          layout={this.layout}
+          total={this.total}
+          onSise-change={this.handleSizeChange}
+          onCurrent-change={this.handleCurrentChange}
+        />
+      </div>
+    )
+  }
+})
+
+// <template>
+
+// </template>
+// <script lang="ts">
+// import { defineComponent, computed } from 'vue'
+
+// export default defineComponent({
+//   name: 'pagination',
+//   props: {
+//     total: {
+//       required: true,
+//       type: Number
+//     },
+//     page: {
+//       type: Number,
+//       default: 1
+//     },
+//     limit: {
+//       type: Number,
+//       default: 10
+//     },
+//     pageSizes: {
+//       type: Array,
+//       default: () => {
+//         return [10, 20, 30, 50]
+//       }
+//     },
+//     layout: {
+//       type: String,
+//       default: 'total,sizes,prev, pager, next, jumper'
+//     },
+//     background: {
+//       type: Boolean,
+//       default: true
+//     },
+//     autoScroll: {
+//       type: Boolean,
+//       default: true
+//     },
+//     hidden: {
+//       type: Boolean,
+//       default: false
+//     },
+//     sync: {
+//       type: Boolean,
+//       default: false
+//     },
+//     saveKey: {
+//       type: String,
+//       default: ''
+//     }
+//   },
+//   setup(props, { emit }) {
+//     let myCurrentPage = computed({
+//       get() {
+//         return props.page
+//       },
+//       set(val) {
+//         emit('update:page', val)
+//       }
+//     })
+
+//     let myLimit = computed({
+//       get() {
+//         return props.limit
+//       },
+//       set(val) {
+//         emit('update:limit', val)
+//       }
+//     })
+
+//     // 赋值回显
+//     const handleSizeChange = (val: any) => {
+//       emit('update:page', 1)
+//       emit('pagination', { page: myCurrentPage, limit: val })
+//       if (props.autoScroll) {
+//         scrollTo(0, 800)
+//       }
+//     }
+//     // 设置当前页
+//     const handleCurrentChange = (val: any) => {
+//       emit('pagination', { page: val, limit: myLimit })
+//       if (props.autoScroll) {
+//         scrollTo(0, 800)
+//       }
+//     }
+//     return {
+//       myCurrentPage,
+//       myLimit,
+//       handleSizeChange,
+//       handleCurrentChange
+//     }
+//   }
+// })
+// </script>

+ 2 - 2
src/components/videoDetailItem/index.tsx

@@ -15,10 +15,10 @@ export default defineComponent({
               <img src={icon} class={classes.itemHead} alt="" />
               <span class={classes.itemTitle}>李老师</span>
               <div class={classes.line}></div>
-              <span  class={classes.course}>12课时</span>
+              <span class={classes.course}>12课时</span>
             </div>
             <div class={classes.itemBottomR}>
-              <span  class={classes.buy} >6人购买</span>
+              <span class={classes.buy}>6人购买</span>
             </div>
           </div>
         </div>

+ 30 - 7
src/router/routes-admin.ts

@@ -1,8 +1,8 @@
 // import Auth from '@/views/layout/auth'
 
-type metaType = {
-  isRegister: boolean
-}
+// type metaType = {
+//   isRegister: boolean
+// }
 
 export default [
   {
@@ -39,10 +39,33 @@ export default [
     path: '/userInfo',
     name: 'userInfo',
     component: () => import('@/views/user-info/index'),
-    meta: {
-      title: '个人信息'
-    }
-    // children: [{}]
+    redirect: '/userInfo/practiceSetting',
+    children: [
+      {
+        path: '/userInfo/practiceSetting',
+        name: 'userInfoPracticeSetting',
+        component: () => import('@/views/user-info/practice-setting'),
+        meta: { title: '陪练课', index: 2 }
+      },
+      {
+        path: '/userInfo/liveClass',
+        name: 'userInfoLiveClass',
+        component: () => import('@/views/user-info/live-class'),
+        meta: { title: '直播课', index: 3 }
+      },
+      {
+        path: '/userInfo/videoClass',
+        name: 'userInfoVideoClass',
+        component: () => import('@/views/user-info/video-class'),
+        meta: { title: '视频课', index: 4 }
+      },
+      {
+        path: '/userInfo/musicClass',
+        name: 'userInfoMusicClass',
+        component: () => import('@/views/user-info/music-class'),
+        meta: { title: '我的曲谱', index: 5 }
+      }
+    ]
   }
   // {
   //   path: '/',

+ 4 - 0
src/style/index.css

@@ -16,4 +16,8 @@
 
 body {
   background: #F6F7F8;
+}
+
+.user-shadow {
+  box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.04);
 }

BIN
src/views/user-info/components/user-menu/images/menu_active.png


+ 49 - 0
src/views/user-info/components/user-menu/index.module.less

@@ -0,0 +1,49 @@
+.menuItem {
+  .icon1 {
+    background: url('./images/1.png') no-repeat center;
+    background-size: contain;
+  }
+  .icon2 {
+    background: url('./images/2.png') no-repeat center;
+    background-size: contain;
+  }
+  .icon3 {
+    background: url('./images/3.png') no-repeat center;
+    background-size: contain;
+  }
+  .icon4 {
+    background: url('./images/4.png') no-repeat center;
+    background-size: contain;
+  }
+  .icon5 {
+    background: url('./images/5.png') no-repeat center;
+    background-size: contain;
+  }
+  &.active,
+  &:hover {
+    background: url('./images/menu_active.png') no-repeat left center;
+    background-size: contain;
+    @apply text-white;
+
+    .icon1 {
+      background: url('./images/1-active.png') no-repeat center;
+      background-size: contain;
+    }
+    .icon2 {
+      background: url('./images/2-active.png') no-repeat center;
+      background-size: contain;
+    }
+    .icon3 {
+      background: url('./images/3-active.png') no-repeat center;
+      background-size: contain;
+    }
+    .icon4 {
+      background: url('./images/4-active.png') no-repeat center;
+      background-size: contain;
+    }
+    .icon5 {
+      background: url('./images/5-active.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+}

+ 48 - 4
src/views/user-info/components/user-menu/index.tsx

@@ -1,20 +1,64 @@
+import { ElLink } from 'element-plus'
+import { userInfo } from 'os'
 import { defineComponent } from 'vue'
+import { RouterLink } from 'vue-router'
+import styles from './index.module.less'
 
 export const getAssetsHomeFile = (fileName: string) => {
   const path = `./images/${fileName}`
   const modules = import.meta.globEager('./images/*')
   return modules[path].default
 }
+// 个人中心默认地址
+const defaultRoute = 'userInfo'
 
 export default defineComponent({
   name: 'user-menu',
+  data() {
+    return {}
+  },
+  computed: {
+    activeRoute() {
+      return this.$route.name
+    },
+    menuList() {
+      const hasRoute = this.$router.hasRoute(defaultRoute)
+      // 判断是否有个人中心的菜单
+      if (!hasRoute) {
+        return
+      }
+      const allRouter = this.$router.getRoutes()
+      const userInfoRouter = allRouter.find(item => item.name === defaultRoute)
+      const list: any = []
+      userInfoRouter?.children.forEach((item: any) => {
+        list.push(item)
+      })
+      return list
+    }
+  },
+  mounted() {
+    // console.log(this.$router.getRoutes(), this.$router.currentRoute.getRoutes())
+    // console.log(this.$router)
+    // const currentRoute = this.$router.currentRoute
+    // console.log(currentRoute, currentRoute.value.name)
+    // console.log(this.$router.hasRoute(currentRoute.value.name))
+  },
   render() {
     return (
       <div class="bg-white rounded-[6px] text-center py-6 px-[18px] flex items-center flex-col">
-        <div class="py-2 px-6 flex items-center text-base text-[#666] w-full">
-          <img class="w-7 h-7 mr-[14px]" src={getAssetsHomeFile('1.png')} />
-          帖子
-        </div>
+        {this.menuList.map((item: any) => (
+          <RouterLink
+            to={item.path}
+            class={[
+              'py-2 px-6 mb-1.5 flex items-center text-base text-[#666] w-full last:mb-0 cursor-pointer',
+              styles.menuItem,
+              item.name === this.activeRoute && styles.active
+            ]}
+          >
+            <i class={['w-7 h-7 mr-3.5', styles['icon' + item.meta.index]]}></i>
+            {item.meta.title}
+          </RouterLink>
+        ))}
       </div>
     )
   }

+ 2 - 2
src/views/user-info/components/users/index.tsx

@@ -22,10 +22,10 @@ export default defineComponent({
 
         <div class="text-[14px] text-[#666] flex items-center justify-center">
           <span class="pr-3 flex items-center justify-center leading-6">
-            粉丝<b class="text-black text-[20px] pl-1">134</b>
+            粉丝<b class="text-black text-xl pl-1 pb-[2px]">134</b>
           </span>
           <span class="flex items-center justify-center leading-6">
-            帖子<b class="text-black text-[20px] pl-1">124</b>
+            帖子<b class="text-black text-xl pl-1 pb-[2px]">124</b>
           </span>
         </div>
       </div>

+ 3 - 3
src/views/user-info/index.tsx

@@ -9,10 +9,10 @@ export default defineComponent({
     return (
       <div class="w-[1200px] mt-[30px] mb-14 min-h-full m-auto text-[#333] flex">
         <div class="w-56 mr-4">
-          <Users class="mb-3" />
-          <UserMenu />
+          <Users class="mb-3 user-shadow" />
+          <UserMenu class="user-shadow" />
         </div>
-        <div class="w-[960px] bg-white rounded-[6px]">
+        <div class="w-[960px] bg-white rounded-[6px] user-shadow">
           <RouterView></RouterView>
         </div>
       </div>

+ 12 - 0
src/views/user-info/live-class/index.module.less

@@ -0,0 +1,12 @@
+.liveClass {
+  :global {
+    .el-tabs__nav-wrap {
+      @apply px-11;
+    }
+    .el-tabs__item {
+      height: 64px;
+      line-height: 64px;
+      padding: 0 42px;
+    }
+  }
+}

+ 23 - 0
src/views/user-info/live-class/index.tsx

@@ -0,0 +1,23 @@
+import { ElButton, ElTabPane, ElTabs } from 'element-plus'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'live-class',
+  render() {
+    return (
+      <div class={[styles.liveClass, 'relative']}>
+        <ElButton round type="primary" class="absolute right-11 top-4">
+          新建直播课
+        </ElButton>
+        <ElTabs>
+          <ElTabPane label="进行中" name="ing"></ElTabPane>
+          <ElTabPane label="未上架" name="ing"></ElTabPane>
+          <ElTabPane label="销售中" name="ing"></ElTabPane>
+          <ElTabPane label="已完成" name="ing"></ElTabPane>
+          <ElTabPane label="已取消" name="ing"></ElTabPane>
+        </ElTabs>
+      </div>
+    )
+  }
+})

+ 59 - 0
src/views/user-info/model/practice-timer/index.module.less

@@ -0,0 +1,59 @@
+.timer {
+  overflow: hidden;
+  padding: 0 14px;
+}
+.tips {
+  margin: 12px 0;
+  padding: 15px 12px;
+  background: #ffffff;
+  border-radius: 10px;
+
+  .tipsTitle {
+    font-size: 18px;
+    font-weight: 500;
+    color: #000000;
+    line-height: 25px;
+  }
+
+  .tipsTime {
+    padding-top: 4px;
+    font-size: 14px;
+    color: #ff9e5a;
+    line-height: 22px;
+    span {
+      font-weight: 600;
+    }
+  }
+}
+.timerContainer {
+  background: #ffffff;
+  border-radius: 10px;
+  padding: 0 5px 9px;
+  :global {
+    .van-col {
+      margin-bottom: 5px;
+    }
+  }
+}
+
+.tag {
+  height: 28px;
+  background: #eff6f5;
+  border-radius: 4px;
+  font-size: 14px;
+  font-weight: 500;
+  color: #2dc7aa;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.active {
+  background: #2dc7aa;
+  color: #ffffff;
+}
+
+.select {
+  color: #ffffff !important;
+  background: #ffb752;
+}

+ 270 - 0
src/views/user-info/model/practice-timer/index.tsx

@@ -0,0 +1,270 @@
+import dayjs from 'dayjs'
+import { ElButton, ElCol, ElRow } from 'element-plus'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'practice-timer',
+  props: {
+    timerObject: {
+      // 传入的数据
+      type: Object,
+      default: {}
+    },
+    onClose: {
+      type: Function,
+      default: () => {}
+    },
+    onChoice: {
+      // 点击选择时间
+      type: Function,
+      default: (item: any) => {}
+    },
+    courseMinutes: {
+      // 课程时长
+      type: Number,
+      default: 25
+    },
+    freeMinutes: {
+      // 空余时长
+      type: Number,
+      default: 5
+    },
+    startSetting: {
+      // 开始设置时间
+      type: String,
+      default: '08:00'
+    },
+    endSetting: {
+      // 结束设置时间
+      type: String,
+      default: '18:00'
+    }
+  },
+  data() {
+    return {
+      timerList: [],
+      list: [] as any,
+      weekList: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
+      weekType: [
+        'monday',
+        'tuesday',
+        'wednesday',
+        'thursday',
+        'friday',
+        'saturday',
+        'sunday'
+      ]
+    }
+  },
+  mounted() {
+    this.list = this.timerInit(
+      this.startSetting,
+      this.endSetting,
+      this.courseMinutes + this.freeMinutes || 30
+    )
+    console.log(this.endSetting)
+  },
+  methods: {
+    timerInit(startTime: string, endTime: string, space: number) {
+      let start = dayjs(startTime, 'HH:mm')
+      const end = dayjs(endTime, 'HH:mm')
+
+      const timerList: any = []
+      // 生成一天的时间段
+      while (start.add(space, 'minute').isSameOrBefore(dayjs(end))) {
+        const item = {
+          startTime: start.format('HH:mm'),
+          endTime: start.add(space, 'minute').format('HH:mm'),
+          status: false
+        }
+        // 一周
+        timerList.push(item)
+        start = start.add(space, 'minute')
+      }
+      const list: any = []
+      // 生成一周的时间段
+      timerList.forEach((item: any) => {
+        const weekList: any = []
+        for (let i = 0; i < 7; i++) {
+          weekList.push({
+            ...item
+          })
+        }
+        list.push(weekList)
+      })
+
+      const tempList = this._initData(list)
+      return tempList
+    },
+    _initData(list: Array<any>) {
+      // 回显数据
+      const weekType = this.weekType
+      const timerObject = this.timerObject
+      list.forEach((item: any) => {
+        item.forEach((slot: any, slotIndex: number) => {
+          const dayList = timerObject[weekType[slotIndex]]
+          const startTime = dayjs(slot.startTime, 'HH:mm').format('HH:mm:ss')
+          const isExist = dayList?.some(
+            (course: any) => course.startTime === startTime
+          )
+          isExist && (slot.status = true)
+        })
+      })
+      return list
+    },
+    btnStatus(index: number, type: 'row' | 'col') {
+      if (type === 'row') {
+        return this.list.every((item: any) => {
+          return item[index].status
+        })
+      }
+
+      if (type == 'col') {
+        return this.list[index].every((item: any) => item.status)
+      }
+    },
+    choice(index: number, type: 'row' | 'col', status?: boolean) {
+      if (type === 'row') {
+        this.list.forEach((item: any, i: number) => {
+          const type = !status ? true : false
+          item[index].status = type
+        })
+      }
+
+      if (type == 'col') {
+        this.list[index].forEach((item: any, i: number) => {
+          const type = !status ? true : false
+          item.status = type
+        })
+      }
+    },
+    onSubmit() {
+      const list = this.list
+      const weekList = {
+        monday: [],
+        tuesday: [],
+        wednesday: [],
+        thursday: [],
+        friday: [],
+        saturday: [],
+        sunday: []
+      }
+      const weekType = this.weekType
+      let status = false
+      list.forEach((item: any, i: number) => {
+        item.forEach((times: any, j: number) => {
+          if (times.status) {
+            status = true
+            weekList[weekType[j]].push({
+              startTime: dayjs(times.startTime, 'HH:mm').format('HH:mm:ss'),
+              endTime: dayjs(times.endTime, 'HH:mm')
+                .subtract(this.freeMinutes, 'minute')
+                .format('HH:mm:ss')
+            })
+          }
+        })
+      })
+      this.onChoice && this.onChoice(weekList, status)
+    }
+  },
+  render() {
+    return (
+      <div class={styles.timer}>
+        <div class={styles.tips}>
+          <div class={styles.tipsTitle}>请选择陪练开始时间</div>
+          <div class={styles.tipsTime}>
+            陪练课单课时时长为 <span>{this.courseMinutes}</span> 分钟
+          </div>
+        </div>
+
+        <div class={[styles.timerContainer, 'mb12']}>
+          <ElRow gutter={5}>
+            <ElCol span={3} class={[styles.tag]}></ElCol>
+            {this.weekList.map((item: any) => (
+              <ElCol span={3}>
+                <span class={styles.tag}>{item}</span>
+              </ElCol>
+            ))}
+          </ElRow>
+
+          <ElRow gutter={5} class="pt-1">
+            <ElCol span={3} class={[styles.tag]}></ElCol>
+            {this.weekList.map((item: any, index: number) => (
+              <ElCol span={3}>
+                <span
+                  class={[
+                    styles.tag,
+                    'cursor-pointer',
+                    this.btnStatus(index, 'row') && styles.active
+                  ]}
+                  onClick={() =>
+                    this.choice(index, 'row', this.btnStatus(index, 'row'))
+                  }
+                >
+                  全选
+                </span>
+              </ElCol>
+            ))}
+          </ElRow>
+
+          <div class="h-72 overflow-auto">
+            {this.list.map((item: any, index: number) => (
+              <ElRow gutter={5} class="pt-1">
+                <ElCol span={3}>
+                  <span
+                    class={[
+                      styles.tag,
+                      'cursor-pointer',
+                      this.btnStatus(index, 'col') && styles.active
+                    ]}
+                    onClick={() =>
+                      this.choice(index, 'col', this.btnStatus(index, 'col'))
+                    }
+                  >
+                    全选
+                  </span>
+                </ElCol>
+                {item.map((week: any) => (
+                  <ElCol span={3}>
+                    <span
+                      class={[
+                        styles.tag,
+                        'cursor-pointer',
+                        week.status && styles.select
+                      ]}
+                      style={{ color: '#333333' }}
+                      onClick={() => (week.status = !week.status)}
+                    >
+                      {week.startTime}
+                    </span>
+                  </ElCol>
+                ))}
+              </ElRow>
+            ))}
+          </div>
+        </div>
+
+        {/* <Sticky offsetBottom={0} position="bottom"> */}
+        <div class="text-center pt-3 pb-5">
+          <ElButton
+            class="!w-40 !h-[38px]"
+            onClick={() => {
+              this.onClose()
+            }}
+          >
+            取消
+          </ElButton>
+          <ElButton
+            type="primary"
+            class="!w-40 !h-[38px]"
+            onClick={this.onSubmit}
+          >
+            保存设置
+          </ElButton>
+        </div>
+        {/* </Sticky> */}
+      </div>
+    )
+  }
+})

+ 16 - 0
src/views/user-info/music-class/index.module.less

@@ -0,0 +1,16 @@
+.liveClass {
+  :global {
+    .el-tabs__nav-wrap {
+      @apply px-11;
+    }
+    .el-tabs__item {
+      height: 64px;
+      line-height: 64px;
+      padding: 0 42px;
+    }
+  }
+
+  .musicListItem:hover {
+    box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.04);
+  }
+}

+ 53 - 0
src/views/user-info/music-class/index.tsx

@@ -0,0 +1,53 @@
+import MusicLIstItem from '@/components/musicLIstItem'
+import Pagination from '@/components/pagination'
+import { ElButton, ElPagination, ElTabPane, ElTabs } from 'element-plus'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'music-class',
+  data() {
+    return {
+      pageInfo: {
+        // 分页规则
+        limit: 10, // 限制显示条数
+        page: 1, // 当前页
+        total: 0, // 总条数
+        page_size: [10, 20, 40, 50] // 选择限制显示条数
+      }
+    }
+  },
+  methods: {
+    getList() {}
+  },
+  render() {
+    return (
+      <div class={[styles.liveClass, 'relative pb-5']}>
+        <ElButton round type="primary" class="absolute right-11 top-4">
+          新建直播课
+        </ElButton>
+        <ElTabs>
+          <ElTabPane label="已上架" name="ing"></ElTabPane>
+          <ElTabPane label="审核中" name="ing"></ElTabPane>
+          <ElTabPane label="审核失败" name="ing"></ElTabPane>
+        </ElTabs>
+
+        <div class="px-[38px]">
+          {[1, 2, 3, 4, 5, 6].map((item: any) => (
+            <MusicLIstItem
+              class={[styles.musicListItem, 'mb-2 px-[14px] rounded-xl']}
+            />
+          ))}
+        </div>
+
+        <Pagination
+          total={this.pageInfo.total}
+          v-model:page={this.pageInfo.page}
+          v-model:limit={this.pageInfo.limit}
+          pageSizes={this.pageInfo.page_size}
+          // pagination={this.getList}
+        />
+      </div>
+    )
+  }
+})

+ 11 - 0
src/views/user-info/practice-setting/index.module.less

@@ -0,0 +1,11 @@
+.setting {
+  :global {
+    .el-dialog {
+      --el-dialog-width: 485px !important;
+    }
+    .el-dialog__header,
+    .el-dialog__body {
+      padding: 0;
+    }
+  }
+}

+ 213 - 0
src/views/user-info/practice-setting/index.tsx

@@ -0,0 +1,213 @@
+import request from '@/helpers/request'
+import { teacherState } from '@/views/role-auth/teacherAuth/teacherState'
+import {
+  ElButton,
+  ElDialog,
+  ElForm,
+  ElFormItem,
+  ElInput,
+  ElOption,
+  ElOptionGroup,
+  ElRadio,
+  ElRadioButton,
+  ElRadioGroup,
+  ElSelect
+} from 'element-plus'
+import { defineComponent } from 'vue'
+import PracticeTimer from '../model/practice-timer'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'practice-setting',
+  data() {
+    return {
+      popupStatus: false,
+      chargeTypeArr: {
+        0: '否',
+        1: '是'
+      },
+      classTimeStatus: false,
+      subjectStatus: false,
+      timerStatus: false,
+      timeSetting: {
+        courseMinutes: 25,
+        freeMinutes: 5,
+        startSetting: '08:00',
+        endSetting: '18:00'
+      },
+      timerObject: {} as any,
+      form: {
+        enableFlag: 1,
+        courseMinutes: null as any,
+        freeMinutes: 0,
+        subjectIdTemp: '',
+        subjectId: [] as any[],
+        subjectPrice: [] as any[],
+        skipHolidayFlag: 1,
+        setting: ''
+      },
+      minutes: [] as any,
+      rate: 0
+    }
+  },
+  async mounted() {
+    try {
+      // 获取手续费和分钟数
+      let config = await request.get(
+        '/api-website/sysConfig/queryByParamNameList',
+        {
+          params: {
+            paramNames:
+              'practice_times_setting,practice_service_fee,course_start_setting,course_end_setting'
+          }
+        }
+      )
+      let configData = config.data || []
+      configData.forEach((item: any) => {
+        if (item.paramName === 'practice_times_setting') {
+          let mins = item.paramValue ? JSON.parse(item.paramValue) : []
+          let tempArr = [] as any
+          mins.forEach((item: any) => {
+            tempArr.push({
+              ...item,
+              name: item.courseMinutes
+            })
+          })
+          this.minutes = [...tempArr]
+        }
+        if (item.paramName === 'practice_service_fee') {
+          this.rate = item.paramValue
+        }
+        if (item.paramName === 'course_start_setting') {
+          this.timeSetting.startSetting = item.paramValue
+        }
+        if (item.paramName === 'course_end_setting') {
+          this.timeSetting.endSetting = item.paramValue
+        }
+      })
+      console.log(this.minutes)
+      if (teacherState.subjectList.length <= 0) {
+        const res = await request.get('/api-website/subject/subjectSelect')
+        teacherState.subjectList = res.data || []
+      }
+    } catch {}
+  },
+  methods: {
+    onChoiceTimer() {}
+  },
+  render() {
+    return (
+      <div class={styles.setting}>
+        <div class="text-base text-[#333] leading-none px-6 py-5 border-b border-b-[#E5E5E5]">
+          陪练课设置
+        </div>
+
+        <ElForm
+          labelPosition="left"
+          labelWidth={'140px'}
+          size="large"
+          model={this.form}
+          ref="form"
+          class="px-44 py-5"
+        >
+          <ElFormItem
+            label="是否开启陪练"
+            prop="enableFlag"
+            rules={[
+              {
+                required: true,
+                message: '请选择是否开启陪练'
+              }
+            ]}
+          >
+            <ElSelect class="w-full" v-model={this.form.enableFlag}>
+              <ElSelect.Option value={1} label={'是'}>
+                是
+              </ElSelect.Option>
+              <ElSelect.Option value={0} label={'否'}>
+                否
+              </ElSelect.Option>
+            </ElSelect>
+          </ElFormItem>
+          <ElFormItem label="可教授声部" prop={'subjectId'} rules={[{}]}>
+            <ElSelect
+              multiple
+              filterable
+              placeholder="请选择可教授声部"
+              class="w-full"
+              multipleLimit={5}
+              v-model={this.form.subjectId}
+            >
+              {teacherState.subjectList.map((group: any) => (
+                <ElOptionGroup key={group.id} label={group.name}>
+                  {group.subjects &&
+                    group.subjects.map((item: any) => (
+                      <ElOption
+                        key={item.id}
+                        value={item.id}
+                        label={item.name}
+                      />
+                    ))}
+                </ElOptionGroup>
+              ))}
+            </ElSelect>
+          </ElFormItem>
+          <ElFormItem label="单课时长">
+            <ElSelect
+              class="w-full"
+              placeholder="请选择单课时时长"
+              v-model={this.form.courseMinutes}
+            ></ElSelect>
+          </ElFormItem>
+          <ElFormItem label="单簧管声部陪练价格">
+            <ElInput
+              v-slots={{
+                append: () => <span class="text-base text-[#333]">元</span>
+              }}
+            />
+          </ElFormItem>
+          <ElFormItem label="是否跳过节假日">
+            <ElRadioGroup v-model={this.form.skipHolidayFlag}>
+              <ElRadioButton label="1">是</ElRadioButton>
+              <ElRadioButton label="0">否</ElRadioButton>
+            </ElRadioGroup>
+          </ElFormItem>
+          <ElFormItem label="陪练时间段">
+            <ElInput
+              readonly
+              class="cursor-pointer"
+              v-model={this.form.setting}
+              placeholder="请选择陪练时间段"
+              suffixIcon={'ArrowDown'}
+            />
+          </ElFormItem>
+        </ElForm>
+
+        <div class="border-t border-t-[#E5E5E5] text-center pt-6 pb-7">
+          <ElButton class="!w-40 !h-[38px]">重围</ElButton>
+          <ElButton type="primary" class="!w-40 !h-[38px]">
+            保存设置
+          </ElButton>
+        </div>
+
+        <ElDialog
+          modelValue={this.popupStatus}
+          onUpdate:modelValue={val => (this.popupStatus = val)}
+          showClose
+        >
+          <PracticeTimer
+            onChoice={this.onChoiceTimer}
+            onClose={() => {
+              this.popupStatus = false
+            }}
+            timerObject={this.timerObject}
+            courseMinutes={Number(this.timeSetting.courseMinutes)}
+            freeMinutes={Number(this.timeSetting.freeMinutes)}
+            startSetting={this.timeSetting.startSetting}
+            endSetting={this.timeSetting.endSetting}
+          />
+        </ElDialog>
+      </div>
+    )
+  }
+})

+ 12 - 0
src/views/user-info/video-class/index.module.less

@@ -0,0 +1,12 @@
+.liveClass {
+  :global {
+    .el-tabs__nav-wrap {
+      @apply px-11;
+    }
+    .el-tabs__item {
+      height: 64px;
+      line-height: 64px;
+      padding: 0 42px;
+    }
+  }
+}

+ 28 - 0
src/views/user-info/video-class/index.tsx

@@ -0,0 +1,28 @@
+import VideoDetailItem from '@/components/videoDetailItem'
+import { ElButton, ElTabPane, ElTabs } from 'element-plus'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'video-class',
+  render() {
+    return (
+      <div class={[styles.liveClass, 'relative']}>
+        {/* 审核状态(DOING:待审核 PASS:通过 */}
+        {/* UNPASS:未通过),可用值:UNPAALY,DOING,PASS,UNPASS */}
+        <ElButton round type="primary" class="absolute right-11 top-4">
+          新建直播课
+        </ElButton>
+        <ElTabs>
+          <ElTabPane label="进行中" name="ing"></ElTabPane>
+          <ElTabPane label="未上架" name="ing"></ElTabPane>
+          <ElTabPane label="销售中" name="ing"></ElTabPane>
+          <ElTabPane label="已完成" name="ing"></ElTabPane>
+          <ElTabPane label="已取消" name="ing"></ElTabPane>
+        </ElTabs>
+
+        <VideoDetailItem />
+      </div>
+    )
+  }
+})

+ 20 - 0
yarn.lock

@@ -2192,6 +2192,13 @@
     "domhandler" "^4.2.0"
     "entities" "^2.0.0"
 
+"dom7@^4.0.4":
+  "integrity" "sha512-DSSgBzQ4rJWQp1u6o+3FVwMNnT5bzQbMb+o31TjYYeRi05uAcpF8koxdfzeoe5ElzPmua7W7N28YJhF7iEKqIw=="
+  "resolved" "https://registry.npmjs.org/dom7/-/dom7-4.0.4.tgz"
+  "version" "4.0.4"
+  dependencies:
+    "ssr-window" "^4.0.0"
+
 "domelementtype@^2.0.1", "domelementtype@^2.2.0":
   "integrity" "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
   "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz"
@@ -4651,6 +4658,11 @@
   "resolved" "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz"
   "version" "1.1.0"
 
+"ssr-window@^4.0.0", "ssr-window@^4.0.2":
+  "integrity" "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
+  "resolved" "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz"
+  "version" "4.0.2"
+
 "strict-uri-encode@^2.0.0":
   "integrity" "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
   "resolved" "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz"
@@ -4765,6 +4777,14 @@
   "resolved" "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz"
   "version" "1.0.0"
 
+"swiper@^8.2.4":
+  "integrity" "sha512-TPq64KiZUt8lZY5ZEg75RjToT+RwfLomfKIpcFLy6+UCUp2kL7hHWslLxjFtcFeiwfG67RHFYbJnq6tsothcJQ=="
+  "resolved" "https://registry.npmjs.org/swiper/-/swiper-8.2.4.tgz"
+  "version" "8.2.4"
+  dependencies:
+    "dom7" "^4.0.4"
+    "ssr-window" "^4.0.2"
+
 "systemjs@^6.12.1":
   "integrity" "sha512-hqTN6kW+pN6/qro6G9OZ7ceDQOcYno020zBQKpZQLsJhYTDMCMNfXi/Y8duF5iW+4WWZr42ry0MMkcRGpbwG2A=="
   "resolved" "https://registry.npmjs.org/systemjs/-/systemjs-6.12.1.tgz"

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.