Browse Source

课件列表UI改版

liushengqiang 2 years ago
parent
commit
49d4354e27

BIN
src/views/courseList/image/icon-course-lock.png


BIN
src/views/courseList/image/icon-course.png


BIN
src/views/courseList/image/icon-list.png


+ 134 - 60
src/views/courseList/index.module.less

@@ -1,70 +1,144 @@
-.grid {
+.courseList {
+  min-height: 100vh;
+  background-color: #fff;
+  background-image: linear-gradient(180deg, #FFE8CE 0%, rgba(251, 233, 213, 0) 198px);
+  padding: 20px 0;
+}
+
+.periodContent {
+  display: flex;
+  padding: 20px;
+
+  .cover {
+    width: 107px;
+    margin-right: 30px;
+    border-radius: 4px 8px 8px 4px;
+    box-shadow: 0px 2px 6px 0px rgba(221, 168, 133, 0.67);
+  }
+
+  .contentTitle {
+    font-size: 16px;
+    font-weight: 500;
+    color: #333;
+    line-height: 22px;
+    padding-bottom: 8px;
+  }
+
+  .contentLabel {
+    font-size: 12px;
+    font-weight: 400;
+    color: rgb(96, 96, 96);
+    line-height: 20px;
+  }
+}
+
+
+.periodTitle {
+  display: flex;
+  align-items: center;
+  padding: 20px 20px 0;
+
+  .pIcon {
+    width: 20px;
+    height: 20px;
+    margin-right: 6px;
+  }
+
+  .pTitle {
+    font-size: 16px;
+    font-weight: 600;
+    color: rgba(124, 61, 18, 1);
+    margin-right: 8px;
+  }
+
+  .pNum {
+    font-size: 12px;
+    font-weight: 400;
+    color: #000;
+  }
+}
+
+.periodList {
   :global {
-    .van-grid-item {
-      .van-grid-item__content {
-        padding: 0;
-        background: transparent;
-        &::after {
-          display: none;
+    .van-cell-group--inset {
+      margin: 0;
+    }
+
+    .van-cell-group,
+    .van-cell {
+      background: transparent;
+    }
+
+    .van-cell {
+      padding: 18px 20px;
+      &::after{
+        left: 20px;
+        right: 20px;
+        border-color: rgba(242, 242, 242, 1);
+        transform: none;
+      }
+      .van-cell__title {
+        padding-right: 8px;
+
+        span {
+          font-size: 15px;
+          font-weight: 600;
+          color: #333333;
+          line-height: 21px;
+          word-break: break-all;
+        }
+
+        .van-cell__label {
+          font-size: 12px;
+          font-weight: 400;
+          color: #AAAAAA;
+          line-height: 17px;
+          margin: 0;
         }
       }
+
+      .van-cell__value {
+        flex: inherit;
+        flex-shrink: 0;
+      }
     }
   }
-  .gridItem {
-    position: relative;
-    width: 100%;
-    height: 107px;
-    border-radius: 10px;
-    overflow: hidden;
-    .cover {
-      position: absolute;
-      left: 0;
-      right: 0;
-      top: 0;
-      bottom: 0;
-      z-index: -1;
-      display: block;
-      width: 100%;
-      height: 100%;
-      object-fit: cover;
+
+  .baseBtn {
+    width: 73px;
+    height: 26px;
+    line-height: 26px;
+    color: #fff;
+    font-size: 13px;
+    font-weight: 500;
+    border: 0;
+    border-radius: 13px;
+    flex-shrink: 0;
+
+    &.look {
+      background: linear-gradient(180deg, #FFAB71 0%, #FF6E45 100%);
     }
-    .title {
-      text-align: center;
-      padding: 10px;
-      color: #742c00;
-      font-size: 15px;
+
+    &.down {
+      background: linear-gradient(180deg, #80C6FF 0%, #4296FF 100%);
     }
-    .subtitle{
-      font-size: 11px;
-      margin-top: 2px;
-    }
-    .num {
-      position: absolute;
-      left: 50%;
-      bottom: 12px;
-      transform: translateX(-50%);
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-size: 12px;
-      width: 70%;
-      height: 20px;
-      border-radius: 20px;
-      background: linear-gradient(180deg, #ff9c7c 0%, #ff5757 100%);
-      color: #fff;
-    }
-    .look {
-      position: absolute;
-      left: 0;
-      right: 0;
-      top: 0;
-      bottom: 0;
-      background-color: rgba(0, 0, 0, 0.6);
-      z-index: 10;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      color: #fff;
+
+    &.disable {
+      opacity: 1;
+      background: linear-gradient(180deg, #D3D3D3 0%, #8F8F8F 100%);
     }
   }
 }
+
+.periodItem {
+  width: 36px;
+  height: 40px;
+  margin-right: 8px;
+  flex-shrink: 0;
+
+  img {
+    width: 100%;
+    height: 100%;
+    display: block;
+  }
+}

+ 104 - 53
src/views/courseList/index.tsx

@@ -1,6 +1,17 @@
 import request from '@/helpers/request'
 import { state } from '@/state'
-import { Button, Empty, Grid, GridItem, Icon, showConfirmDialog, showToast } from 'vant'
+import {
+  Button,
+  Cell,
+  CellGroup,
+  Empty,
+  Grid,
+  GridItem,
+  Icon,
+  showConfirmDialog,
+  showToast,
+  Space
+} from 'vant'
 import { defineComponent, onMounted, reactive, onUnmounted } from 'vue'
 import styles from './index.module.less'
 import { useRoute, useRouter } from 'vue-router'
@@ -12,11 +23,15 @@ import {
 } from '@/helpers/native-message'
 import iconLook from './image/look.svg'
 import iconCourse from './image/icon-course.png'
+import iconCourseLock from './image/icon-course-lock.png'
 import { browser } from '@/helpers/utils'
 import OEmpty from '@/components/o-empty'
 import { handleCheckVip } from '../hook/useFee'
+import iconList from './image/icon-list.png'
+import OSticky from '@/components/o-sticky'
+import OHeader from '@/components/o-header'
 export default defineComponent({
-  name: 'lessonCourseware',
+  name: 'courseList',
   setup() {
     const route = useRoute()
     const router = useRouter()
@@ -185,59 +200,95 @@ export default defineComponent({
       } catch (error) {}
     }
     return () => (
-      <div style={{ paddingTop: '14px' }}>
-        <Grid gutter={14} columnNum={3} class={styles.grid}>
-          {data.list.map((item: any) => {
-            return (
-              <GridItem>
-                <div class={styles.gridItem} onClick={() => handleClick(item)}>
-                  <img src={iconCourse} class={styles.cover} />
-                  <div class={styles.title}>
-                    <div class="van-multi-ellipsis--l2">{item.coursewareDetailName}</div>
-                    {!browserInfo.isStudent && (
-                      <div class={styles.subtitle}>已使用 {item.useNum} 次</div>
-                    )}
-                  </div>
-                  {route.query.code !== 'select' ? (
-                    <>
-                      {!!item.knowledgePointList && (
-                        <>
-                          {item.hasCache ? (
-                            <div class={styles.num}>
-                              查看
-                              <Icon name="play-circle-o" />
-                            </div>
-                          ) : (
-                            <>
-                              {item.downloadStatus === 1 ? (
-                                <div class={styles.num}>下载中 {item.progress || 0}%</div>
-                              ) : item.downloadStatus === 2 ? (
-                                <div class={styles.num}>下载成功</div>
-                              ) : item.downloadStatus === 3 ? (
-                                <div class={styles.num}>重新下载</div>
-                              ) : (
-                                <div class={styles.num}>下载</div>
-                              )}
-                            </>
-                          )}
-                        </>
-                      )}
-                    </>
-                  ) : (
-                    <div class={styles.num}>选择</div>
-                  )}
+      <div class={styles.courseList}>
+        <OSticky
+          onGetHeight={(height: number) => {
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader
+            border={false}
+            background="transparent"
+            color="rgba(124, 61, 18, 1)"
+            title="我的教材"
+          />
+        </OSticky>
+
+        <div class={styles.periodContent}>
+          <img class={styles.cover} src={'https://gyt.ks3-cn-beijing.ksyuncs.com/courseware/1678340522843.png'} />
+          <div>
+            <div class={styles.contentTitle}>小号第三学期 (上册)</div>
+            <div class={styles.contentLabel}>
+              教学目标:让学生了解小号乐器的组成,学习呼吸的方式,学习基础的嘴形以及乐理知识。让学生了解小号乐器的组成。
+            </div>
+          </div>
+        </div>
 
-                  {(route.query.code == 'select' || state.platformType == 'STUDENT') &&
-                    !item.unlock && (
-                      <div class={styles.look} onClick={(e: Event) => e.stopPropagation()}>
-                        <Icon name={iconLook} /> 未解锁
+        <div class={styles.periodTitle}>
+          <img class={styles.pIcon} src={iconList} />
+          <div class={styles.pTitle}>课程列表</div>
+          <div class={styles.pNum}>共{data.list.length}课</div>
+        </div>
+
+        <div class={styles.periodList}>
+          <CellGroup inset>
+            {data.list.map((item: any) => {
+              const isLock =
+                (route.query.code == 'select' || state.platformType == 'STUDENT') &&
+                !item.unlock &&
+                true
+              const isSelect = route.query.code === 'select'
+              return (
+                <Cell
+                  border
+                  center
+                  title={item.coursewareDetailName}
+                  label={`已使用${item.useNum}次`}
+                  onClick={() => !isLock && handleClick(item)}
+                >
+                  {{
+                    icon: () => (
+                      <div class={styles.periodItem}>
+                        <div class={styles.periodItemModel}>
+                          <img src={isLock ? iconCourseLock : iconCourse} />
+                        </div>
                       </div>
-                    )}
-                </div>
-              </GridItem>
-            )
-          })}
-        </Grid>
+                    ),
+                    value: () => (
+                      <>
+                        {isSelect ? (
+                          <Button class={[styles.baseBtn, styles.look]}>选择</Button>
+                        ) : item.knowledgePointList ? (
+                          <>
+                            {item.hasCache ? (
+                              <Button class={[styles.baseBtn, styles.look]}>查看</Button>
+                            ) : (
+                              <Button
+                                disabled={isLock}
+                                class={[styles.baseBtn, isLock ? styles.disable : styles.down]}
+                              >
+                                {item.downloadStatus === 1
+                                  ? `下载中 ${item.progress || 0}%`
+                                  : item.downloadStatus === 2
+                                  ? '下载成功'
+                                  : item.downloadStatus === 3
+                                  ? '重新下载'
+                                  : '下载'}
+                              </Button>
+                            )}
+                          </>
+                        ) : (
+                          ''
+                        )}
+                      </>
+                    )
+                  }}
+                </Cell>
+              )
+            })}
+          </CellGroup>
+        </div>
+
         {!data.loading && !data.list.length && <OEmpty tips="暂无内容" />}
       </div>
     )

BIN
src/views/lessonCourseware/component/CourseItem/image/icon-lock.png


BIN
src/views/lessonCourseware/component/CourseItem/image/icon-top.png


+ 105 - 0
src/views/lessonCourseware/component/CourseItem/index.module.less

@@ -0,0 +1,105 @@
+.content{
+    padding: 12px;
+}
+.wrap {
+    position: relative;
+    background: rgba(253,243,231,1);
+    border-radius: 10px;
+    border: 2px solid #FFFFFF;
+    min-height: 220px;
+    display: flex;
+    flex-wrap: wrap;
+    padding-top: 22px;
+    padding-bottom: 20px;
+    box-sizing: border-box;
+
+    div {
+        box-sizing: border-box;
+    }
+
+    .icon {
+        position: absolute;
+        left: 50%;
+        top: -6px;
+        width: 126px;
+        padding: 5px 10px;
+        transform: translate(-50%, 0);
+        z-index: 10;
+        background-image: url('./image/icon-top.png');
+        background-repeat: no-repeat;
+        background-size: contain;
+        text-align: center;
+        color: #fff;
+        font-size: 16px;
+        font-weight: 500;
+        line-height: 22px;
+        img{
+            display: block;
+            width: 100%;
+            height: 100%;
+        }
+    }
+}
+
+.item {
+    margin: 20px 0 0 0;
+    padding: 0 30px;
+    width: 50%;
+
+    .cover {
+        position: relative;
+        border-radius: 4px 8px 8px 4px;
+        overflow: hidden;
+        margin-bottom: 8px;
+    }
+
+    .model {
+        position: absolute;
+        left: 0;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        background-color: rgba(0, 0, 0, 0.4);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: #fff;
+        font-size: 12px;
+        line-height: 18px;
+
+        img {
+            width: 12px;
+            height: 12px;
+            margin-right: 4px;
+        }
+    }
+
+    .coverNum {
+        position: absolute;
+        bottom: 12px;
+        left: 50%;
+        transform: translateX(-50%);
+        border-radius: 20px;
+        color: rgba(116, 44, 0, 1);
+        background-color: #fff;
+        padding: 2px 6px;
+        line-height: 16px;
+        font-size: 12px;
+        z-index: 1;
+    }
+
+    .coverImg {
+        display: block;
+        width: 100%;
+        box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.2);
+        max-height: 140px;
+    }
+
+    .name {
+        width: 109%;
+        font-size: 14px;
+        font-weight: 500;
+        color: #333;
+        line-height: 20px;
+    }
+}

+ 53 - 0
src/views/lessonCourseware/component/CourseItem/index.tsx

@@ -0,0 +1,53 @@
+import { defineComponent, PropType } from 'vue'
+import styles from './index.module.less'
+import iconTop from './image/icon-top.png'
+import iconLock from './image/icon-lock.png'
+
+export default defineComponent({
+  name: 'CourseItem',
+  props: {
+    list: {
+      type: Array as PropType<any[]>,
+      default: () => []
+    },
+    term: {
+      type: Number,
+      defaut: 0
+    }
+  },
+  emits: ['itemClick'],
+  setup(prop, { emit }) {
+    const schoolTerm = {
+      1: '一',
+      2: '二',
+      3: '三',
+      4: '四',
+      5: '五',
+      6: '六'
+    }
+    return () => (
+      <div class={styles.content}>
+        <div class={styles.wrap}>
+          <div class={styles.icon}>
+            <div>第{schoolTerm[prop.term as any]}学期</div>
+          </div>
+          {prop.list.map((item: any, index: number) => {
+            return (
+              <div class={styles.item} onClick={() => emit('itemClick', item)}>
+                <div class={styles.cover}>
+                  <img class={styles.coverImg} src={item.coverImg} />
+                  {/* {item.delFlag && <div class={styles.model}>
+                    <img src={iconLock} />
+                    <div>未解锁</div>
+                </div>} */}
+                  <div class={styles.coverNum}>共{item.courseNum}课</div>
+                </div>
+                <div class={[styles.name, 'van-ellipsis']}>{item.name}</div>
+              </div>
+            )
+          })}
+        </div>
+      </div>
+    )
+  }
+})

+ 6 - 0
src/views/lessonCourseware/index.module.less

@@ -1,3 +1,9 @@
+.lessonCourseware{
+  min-height: 100vh;
+  background-color: rgba(255, 232, 206, 1);
+  padding: 10px 0;
+  box-sizing: border-box;
+}
 .grid {
   :global {
     .van-grid-item {

+ 35 - 33
src/views/lessonCourseware/index.tsx

@@ -6,6 +6,9 @@ import styles from './index.module.less'
 import iconLook from './image/look.svg'
 import { useRoute, useRouter } from 'vue-router'
 import OEmpty from '@/components/o-empty'
+import OSticky from '@/components/o-sticky'
+import OHeader from '@/components/o-header'
+import CourseItem from './component/CourseItem'
 export default defineComponent({
   name: 'lessonCourseware',
   setup() {
@@ -15,6 +18,17 @@ export default defineComponent({
       loading: true,
       list: [] as any
     })
+    const filterData = (list: any[]) => {
+      const schoolTerm = {}
+      for(let i = 0; i < list.length; i++){
+        if (schoolTerm[list[i].sortNo]){
+          schoolTerm[list[i].sortNo].push(list[i])
+        } else {
+          schoolTerm[list[i].sortNo] = [list[i]]
+        }
+      }
+      return schoolTerm
+    }
     const getList = async () => {
       data.loading = true
       if (route.query.code === 'select') {
@@ -23,7 +37,7 @@ export default defineComponent({
             state.platformApi + `/courseSchedule/getCourseware/${route.query.courseScheduleId}`
           )
           if (Array.isArray(res?.data)) {
-            data.list = res.data.map((n: any) => {
+            const data = res.data.map((n: any) => {
               return {
                 coverImg: n.coverImg,
                 name: n.coursewareName,
@@ -31,13 +45,14 @@ export default defineComponent({
                 courseNum: n.coursewareNum
               }
             })
+            data.list = filterData(data)
           }
         } catch (error) {}
       } else {
         try {
           const res: any = await request.post(state.platformApi + '/courseSchedule/myCourseware')
           if (Array.isArray(res?.data)) {
-            data.list = res.data
+            data.list = filterData(res.data)
           }
         } catch (error) {}
       }
@@ -66,37 +81,24 @@ export default defineComponent({
     }
 
     return () => (
-      <div
-        style={{ paddingTop: '14px', boxSizing: 'border-box' }}
-        class={!data.list.length && 'emptyRootContainer'}
-      >
-        <Grid gutter={14} columnNum={3} class={styles.grid}>
-          {data.list.map((item: any) => {
-            return (
-              <GridItem>
-                <div
-                  class={styles.gridItem}
-                  style={{
-                    background: item.coverImg
-                      ? ''
-                      : `hsla(${Math.floor(Math.random() * 360)},50%,50%,.8)`
-                  }}
-                  onClick={() => handleClick(item)}
-                >
-                  <img src={item.coverImg} class={styles.cover} />
-                  {/* <div class={['van-multi-ellipsis--l3', styles.title]}>{item.name}</div> */}
-                  <div class={styles.num}>共{item.courseNum}课</div>
-                  {/* {item.delFlag && (
-                    <div class={styles.look}>
-                      <Icon name={iconLook} /> 未解锁
-                    </div>
-                  )} */}
-                </div>
-              </GridItem>
-            )
-          })}
-        </Grid>
-        {!data.loading && !data.list.length && <OEmpty tips="没有课件" />}
+      <div class={[styles.lessonCourseware, !Object.values(data.list).length && 'emptyRootContainer']}>
+        <OSticky
+          onGetHeight={(height: number) => {
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader
+            border={false}
+            background="rgba(255, 232, 206, 1)"
+            color="rgba(124, 61, 18, 1)"
+            title="我的教材"
+          />
+        </OSticky>
+        {Object.keys(data.list).map((key: any) => {
+          console.error(key)
+          return <CourseItem term={key} list={data.list[key]} onItemClick={(row) => handleClick(row)} />
+        })}
+        {!data.loading && !Object.values(data.list).length && <OEmpty tips="没有课件" />}
       </div>
     )
   }

+ 2 - 2
vite.config.ts

@@ -11,8 +11,8 @@ function resolve(dir: string) {
 }
 // https://vitejs.dev/config/
 // https://github.com/vitejs/vite/issues/1930 .env
-// const proxyUrl = 'https://mstutest.dayaedu.com/';
-const proxyUrl = 'http://47.98.131.38:8989/'
+const proxyUrl = 'https://test.lexiaoya.cn/';
+// const proxyUrl = 'http://47.98.131.38:8989/'
 // const proxyUrl = 'http://192.168.3.20:8989/' // 邹旋
 // const proxyUrl = 'http://192.168.3.143:8989/' // 尚科
 // const proxyUrl = 'http://192.168.3.26:8989/' // 刘俊驰