Browse Source

Merge branch '2023-3-21_CoursewareList-UI' into jenkins

liushengqiang 2 years ago
parent
commit
6dd895684a

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


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

@@ -1,70 +1,152 @@
-.grid {
-  :global {
-    .van-grid-item {
-      .van-grid-item__content {
-        padding: 0;
-        background: transparent;
-        &::after {
-          display: none;
-        }
+.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);
+    overflow: hidden;
+    :global{
+      .van-image__loading{
+        position: relative;
+        min-height: 130px;
+        animation: van-skeleton-blink var(--van-skeleton-duration) ease-in-out infinite;
       }
     }
   }
-  .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;
+
+  .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-cell-group--inset {
+      margin: 0;
     }
-    .title {
-      text-align: center;
-      padding: 10px;
-      color: #742c00;
-      font-size: 15px;
+
+    .van-cell-group,
+    .van-cell {
+      background: transparent;
     }
-    .subtitle{
-      font-size: 11px;
-      margin-top: 2px;
+
+    .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;
+      }
+    }
+  }
+
+  .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%);
     }
-    .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;
+
+    &.down {
+      background: linear-gradient(180deg, #80C6FF 0%, #4296FF 100%);
     }
-    .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;
+  }
+}

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

@@ -1,6 +1,21 @@
 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,
+  Image,
+  Loading,
+  showConfirmDialog,
+  showToast,
+  Skeleton,
+  SkeletonImage,
+  Space
+} from 'vant'
 import { defineComponent, onMounted, reactive, onUnmounted } from 'vue'
 import styles from './index.module.less'
 import { useRoute, useRouter } from 'vue-router'
@@ -12,11 +27,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()
@@ -24,8 +43,23 @@ export default defineComponent({
     // const catchList = store
     const data = reactive({
       loading: true,
+      detail: {
+        cover: '',
+        name: '',
+        des: ''
+      },
       list: [] as any
     })
+
+    /** 获取课件详情 */
+    const getDetail = async () => {
+      const res: any = await request.get(`${state.platformApi}/lessonCourseware/detail/${route.query.id}`)
+      if (res?.data){
+        data.detail.cover = res.data.coverImg
+        data.detail.name = res.data.name
+        data.detail.des = res.data.lessonTargetDesc
+      }
+    }
     const getList = async () => {
       data.loading = true
       if (route.query.courseScheduleId) {
@@ -56,6 +90,7 @@ export default defineComponent({
       data.loading = false
     }
     onMounted(() => {
+      getDetail()
       getList()
       listenerMessage('downloadCoursewareToCache', getProgress)
     })
@@ -185,59 +220,100 @@ 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>
 
-                  {(route.query.code == 'select' || state.platformType == 'STUDENT') &&
-                    !item.unlock && (
-                      <div class={styles.look} onClick={(e: Event) => e.stopPropagation()}>
-                        <Icon name={iconLook} /> 未解锁
+        <div class={styles.periodContent}>
+          <Image class={styles.cover} src={data.detail.cover}>
+            {{
+              loading: () => <Loading />, 
+            }}
+          </Image>
+          {/* <img class={styles.cover} src={data.detail.cover} /> */}
+          <div>
+            <div class={styles.contentTitle}>{data.detail.name}</div>
+            <div class={styles.contentLabel}>
+              教学目标:{data.detail.des}
+            </div>
+          </div>
+        </div>
+
+        <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 disabled={isLock} class={[styles.baseBtn, isLock ? styles.disable : 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


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

@@ -0,0 +1,112 @@
+.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;
+        box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.2);
+    }
+
+    .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%;
+        max-height: 140px;
+        :global{
+            .van-image__loading{
+                position: relative;
+                min-height: 130px;
+                animation: van-skeleton-blink var(--van-skeleton-duration) ease-in-out infinite;
+            }
+        }
+    }
+
+    .name {
+        width: 109%;
+        font-size: 14px;
+        font-weight: 500;
+        color: #333;
+        line-height: 20px;
+    }
+}

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

@@ -0,0 +1,59 @@
+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'
+import { Image, Loading } from 'vant'
+
+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}>
+                  <Image class={styles.coverImg} src={item.coverImg}>
+                    {{
+                      loading: () => <Loading />, 
+                    }}
+                  </Image>
+                  {/* <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>
+    )
+  }
+})

+ 5 - 66
src/views/lessonCourseware/index.module.less

@@ -1,67 +1,6 @@
-.grid {
-  :global {
-    .van-grid-item {
-      .van-grid-item__content {
-        padding: 0;
-        background: transparent;
-        &::after {
-          display: none;
-        }
-      }
-    }
-  }
-  .gridItem {
-    position: relative;
-    width: 100%;
-    height: 130px;
-    border-radius: 8px;
-    overflow: hidden;
-    background: rgba(247,203,143,1);
-    .cover {
-      position: absolute;
-      left: 0;
-      right: 0;
-      top: 0;
-      bottom: 0;
-      display: block;
-      width: 100%;
-      height: 100%;
-      object-fit: cover;
-    }
-    .title {
-      position: relative;
-      text-align: center;
-      padding: 14px;
-      color:#742C00;
-      font-size: 14px;
-    }
-    .num {
-      position: absolute;
-      left: 50%;
-      bottom: 12px;
-      transform: translateX(-50%);
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-size: 12px;
-      width: 50%;
-      height: 20px;
-      border-radius: 20px;
-      background-color: #fff;
-      color: #742c00;
-    }
-    .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;
-    }
-  }
+.lessonCourseware{
+  min-height: 100vh;
+  background-color: rgba(255, 232, 206, 1);
+  padding: 10px 0;
+  box-sizing: border-box;
 }

+ 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>
     )
   }

+ 142 - 69
src/views/unit-test/unit-create/uni-test.module.less

@@ -1,79 +1,152 @@
-.grid {
-  :global {
-    .van-grid-item {
-      .van-grid-item__content {
-        padding: 0;
-        background: transparent;
-        &::after {
-          display: none;
-        }
+.uniTest{
+  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);
+    overflow: hidden;
+    :global{
+      .van-image__loading{
+        position: relative;
+        min-height: 130px;
+        animation: van-skeleton-blink var(--van-skeleton-duration) ease-in-out infinite;
       }
     }
   }
-  .gridItem {
-    position: relative;
-    width: 100%;
-    height: 107px;
-    border-radius: 8px;
-    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;
+
+  .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-cell-group--inset {
+      margin: 0;
     }
-    .title {
-      text-align: center;
-      padding: 10px;
-      color: #742c00;
-
-      .coreTitle {
-        font-size: 16px;
-        font-weight: 600;
-        line-height: 22px;
-        margin-bottom: 4px;
-      }
+
+    .van-cell-group,
+    .van-cell {
+      background: transparent;
     }
-    .num {
-      position: absolute;
-      left: 50%;
-      bottom: 12px;
-      transform: translateX(-50%);
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-size: 12px;
-      width: 70%;
-      line-height: 20px;
-      border-radius: 20px;
-      background: linear-gradient(180deg, #ff9c7c 0%, #ff5757 100%);
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-      color: #fff;
-      .playIcon {
-        font-size: 12px;
-        margin-left: 2px;
+
+    .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;
       }
     }
-    .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;
+  }
+
+  .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%);
+    }
+
+    &.down {
+      background: linear-gradient(180deg, #80C6FF 0%, #4296FF 100%);
+    }
+
+    &.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;
+  }
+}

+ 82 - 27
src/views/unit-test/unit-create/uni-test.tsx

@@ -1,6 +1,6 @@
 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, Image, Loading, showConfirmDialog, showToast } from 'vant'
 import { defineComponent, onMounted, reactive, onUnmounted, ref } from 'vue'
 import styles from './uni-test.module.less'
 import { useRoute, useRouter } from 'vue-router'
@@ -13,7 +13,11 @@ import {
 import OEmpty from '@/components/o-empty'
 import iconLook from './image/look.svg'
 import iconCourse from '@/views/courseList/image/icon-course.png'
+import iconCourseLock from '@/views/courseList/image/icon-course-lock.png'
 import { browser } from '@/helpers/utils'
+import OSticky from '@/components/o-sticky'
+import OHeader from '@/components/o-header'
+import iconList from '@/views/courseList/image/icon-list.png'
 export default defineComponent({
   name: 'uni-test',
   setup() {
@@ -24,8 +28,23 @@ export default defineComponent({
     const forms = ref({} as any)
     const data = reactive({
       loading: true,
+      detail: {
+        cover: '',
+        name: '',
+        des: ''
+      },
       list: [] as any
     })
+
+    /** 获取课件详情 */
+    const getDetail = async () => {
+      const res: any = await request.get(`${state.platformApi}/lessonCourseware/detail/${route.query.lessonCoursewareId}`)
+      if (res?.data){
+        data.detail.cover = res.data.coverImg
+        data.detail.name = res.data.name
+        data.detail.des = res.data.lessonTargetDesc
+      }
+    }
     const getList = async () => {
       data.loading = true
       try {
@@ -47,6 +66,7 @@ export default defineComponent({
       data.loading = false
     }
     onMounted(() => {
+      getDetail()
       forms.value = { ...JSON.parse(sessionStorage.getItem('unit-create') || '{}') } as any
       getList()
     })
@@ -65,37 +85,72 @@ export default defineComponent({
     }
 
     return () => (
-      <div style={{ paddingTop: '14px' }}>
-        {data.list.length > 0 ? (
-          <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={styles.coreTitle}>{item.name}</div>
-                      {<div>已使用 {item.useNum} 次</div>}
-                    </div>
+      <div class={styles.uniTest}>
+        <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}>
+          <Image class={styles.cover} src={data.detail.cover}>
+            {{
+              loading: () => <Loading />, 
+            }}
+          </Image>
+          {/* <img class={styles.cover} src={data.detail.cover} /> */}
+          <div>
+            <div class={styles.contentTitle}>{data.detail.name}</div>
+            <div class={styles.contentLabel}>
+              教学目标:{data.detail.des}
+            </div>
+          </div>
+        </div>
 
-                    {/* <div class={styles.num}>
-                      查看
-                      <Icon name="play-circle-o" class={styles.playIcon} />
-                    </div> */}
+        <div class={styles.periodTitle}>
+          <img class={styles.pIcon} src={iconList} />
+          <div class={styles.pTitle}>课程列表</div>
+          <div class={styles.pNum}>共{data.list.length}课</div>
+        </div>
 
-                    {!item.unLockFlag && (
-                      <div class={styles.look} onClick={(e: Event) => e.stopPropagation()}>
-                        <Icon name={iconLook} /> 未解锁
+        <div class={styles.periodList}>
+          <CellGroup inset>
+            {data.list.map((item: any) => {
+              const isLock = !item.unLockFlag
+              return (
+                <Cell
+                  border
+                  center
+                  title={item.name}
+                  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>
+                    ),
+                    value: () => (
+                      <>
+                        <Button disabled={isLock} class={[styles.baseBtn, isLock ? styles.disable : styles.look]}>选择</Button>
+                      </>
+                    )
+                  }}
+                </Cell>
               )
             })}
-          </Grid>
-        ) : (
-          <OEmpty></OEmpty>
-        )}
+          </CellGroup>
+        </div>
+        {!data.loading && !data.list.length && <OEmpty tips="暂无内容" />}
       </div>
     )
   }

+ 39 - 37
src/views/unit-test/unit-create/unit-Lesson.tsx

@@ -6,6 +6,9 @@ import styles from './unit-lesson.module.less'
 import iconLook from './image/look.svg'
 import { useRoute, useRouter } from 'vue-router'
 import OEmpty from '@/components/o-empty'
+import CourseItem from '@/views/lessonCourseware/component/CourseItem'
+import OSticky from '@/components/o-sticky'
+import OHeader from '@/components/o-header'
 export default defineComponent({
   name: 'unit-Lesson',
   setup() {
@@ -16,6 +19,18 @@ 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
@@ -30,12 +45,15 @@ export default defineComponent({
           }
         )
         if (Array.isArray(res?.data)) {
-          data.list = []
-          res.data.map((item: any) => {
-            if (item.unitTestNum) {
-              data.list.push(item)
+          const list = res.data.filter((item: any) => item.unitTestNum).map((n: any) => {
+            return {
+              coverImg: n.coverImg,
+              name: n.coursewareName,
+              id: n.lessonCoursewareId,
+              courseNum: n.coursewareNum
             }
           })
+          data.list = filterData(list)
         }
       } catch (error) {
         console.log(error)
@@ -61,40 +79,24 @@ export default defineComponent({
 
     return () => (
       <div
-        style={{ paddingTop: '14px' }}
-        class={[data.list.length > 0 ? '' : 'emptyRootContainer']}
+        class={[styles.unitLesson, Object.values(data.list).length ? '' : 'emptyRootContainer']}
       >
-        {data.list.length > 0 ? (
-          <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={styles.title}>{item.name}</div>
-                    <div class={styles.num}>共{item.unitTestNum || 0}次测验</div>
-
-                    {/* {!item.enableFlag && (
-                    <div class={styles.look}>
-                      <Icon name={iconLook} /> 未解锁
-                    </div>
-                  )} */}
-                  </div>
-                </GridItem>
-              )
-            })}
-          </Grid>
-        ) : (
-          <OEmpty btnStatus={false} tips="暂无教材"></OEmpty>
-        )}
+        <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) => {
+          return <CourseItem term={key} list={data.list[key]} onItemClick={(row) => handleClick(row)} />
+        })}
+        {!data.loading && !Object.values(data.list).length && <OEmpty btnStatus={false} tips="暂无教材"></OEmpty>}
 
         {/* <Button onClick={() => {
           location.href = 'http://192.168.3.114:1000/teacher.html#/courseList?id=1610595624868495362'

+ 5 - 65
src/views/unit-test/unit-create/unit-lesson.module.less

@@ -1,66 +1,6 @@
-.grid {
-  :global {
-    .van-grid-item {
-      .van-grid-item__content {
-        padding: 0;
-        background: transparent;
-        &::after {
-          display: none;
-        }
-      }
-    }
-  }
-  .gridItem {
-    position: relative;
-    width: 100%;
-    height: 130px;
-    border-radius: 8px;
-    overflow: hidden;
-    background: rgba(247, 203, 143, 1);
-    .cover {
-      position: absolute;
-      left: 0;
-      right: 0;
-      top: 0;
-      bottom: 0;
-      display: block;
-      width: 100%;
-      height: 100%;
-      object-fit: cover;
-    }
-    .title {
-      position: relative;
-      text-align: center;
-      padding: 10px;
-      color: #742c00;
-    }
-    .num {
-      position: absolute;
-      left: 50%;
-      bottom: 12px;
-      transform: translateX(-50%);
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-size: 12px;
-      width: 75%;
-      height: 20px;
-      border-radius: 20px;
-      background-color: #fff;
-      color: #742c00;
-    }
-    .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;
-    }
-  }
+.unitLesson{
+  min-height: 100vh;
+  background-color: rgba(255, 232, 206, 1);
+  padding: 10px 0;
+  box-sizing: border-box;
 }

+ 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 = 'https://test.lexiaoya.cn'
+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/' // 刘俊驰