lex-xin 2 月之前
父節點
當前提交
95203bb2ac

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

@@ -25,6 +25,14 @@ export const router: RouteRecordRaw[] = [
     }
   },
   {
+    path: '/courseListSearch',
+    name: 'courseListSearch',
+    component: () => import('@/views/courseListSearch/index'),
+    meta: {
+      title: '搜索'
+    }
+  },
+  {
     path: '/coursewarePlay',
     name: 'coursewarePlay',
     component: () => import('@/views/coursewarePlay'),

二進制
src/views/courseList/image/icon-search.png


+ 37 - 3
src/views/courseList/index.module.less

@@ -1,8 +1,8 @@
 .courseList {
   min-height: 100vh;
-  background-color: #fff;
+  background-color: #F8F8F8;
   background-image: linear-gradient(180deg, #FFE8CE 0%, rgba(251, 233, 213, 0) 198px);
-  padding: 10px 0;
+  padding: 0;
   box-sizing: border-box;
 }
 
@@ -69,11 +69,45 @@
   }
 }
 
+.periodSection {
+  flex: 1;
+  background: #FFFFFF;
+  border-radius: 20px 20px 0px 0px;
+  // min-height: 40vh;
+}
+
+.periodHeader {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 20px 20px 12px;
+  .searchGroup {
+    padding: 3px 10px 3px 7px;
+    border-radius: 19px;
+    border: 1px solid rgba(255,128,87,0.5);
+    font-size: 14px;
+    color: rgba(0,0,0,0.4);
+    line-height: 20px;
+    display: flex;
+    align-items: center;
+    cursor: pointer;
+    .iconSearch {
+      // width: 20px;
+      flex-shrink: 0;
+      margin-right: 5px;
+      height: 12px;
+    }
+    span {
+      flex-shrink: 0;
+    }
+  }
+}
+
 
 .periodTitle {
   display: flex;
   align-items: center;
-  padding: 20px 20px 0;
+  padding: 0; // 20px 20px 0;
 
   .pIcon {
     width: 20px;

+ 128 - 107
src/views/courseList/index.tsx

@@ -28,6 +28,7 @@ import iconCachePoint from './image/icon-cache-point.png'
 import iconCourse from './image/icon-course.png'
 import iconCourseLock from './image/icon-course-lock.png'
 import iconTip from './image/iconTip.png'
+import iconSearch from './image/icon-search.png'
 import { browser } from '@/helpers/utils'
 import OEmpty from '@/components/o-empty'
 import { handleCheckVip } from '../hook/useFee'
@@ -328,124 +329,144 @@ export default defineComponent({
     })
     return () => (
       <div class={styles.courseList}>
-        <OHeader
-          border={false}
-          background={`rgba(255,255,255, ${data.titleOpacity})`}
-          color="rgba(124, 61, 18, 1)"
-          title="教材详情"
-        />
-        <div class={styles.periodContent}>
-          <div class={styles.cover}>
-            <img
-              src={data.detail.cover}
-              onLoad={(e: Event) => {
-                if (e.target) {
-                  ;(e.target as any).style.opacity = 1
-                }
-              }}
-            />
-          </div>
-          <div>
-            <div class={styles.contentTitle}>{data.detail.name}</div>
-            <div class={styles.contentLabel}>教学目标:{data.detail.des}</div>
+        <OSticky position='top'>
+          <OHeader
+            border={false}
+            background={`rgba(255,255,255, ${data.titleOpacity})`}
+            color="rgba(124, 61, 18, 1)"
+            title="教材详情"
+          />
+        </OSticky>
+        <div style="height: calc(100vh - var(--header-height, 0px)); overflow-x: hidden; overflow-y: auto;display:flex; flex-direction: column;">
+          <div class={styles.periodContent}>
+            <div class={styles.cover}>
+              <img
+                src={data.detail.cover}
+                onLoad={(e: Event) => {
+                  if (e.target) {
+                    ;(e.target as any).style.opacity = 1
+                  }
+                }}
+              />
+            </div>
+            <div>
+              <div class={styles.contentTitle}>{data.detail.name}</div>
+              <div class={styles.contentLabel}>教学目标:{data.detail.des}</div>
+            </div>
           </div>
-        </div>
 
-        <TransitionGroup name="van-fade">
-          {!data.loading && (
-            <>
-              <div key="periodTitle" 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.periodSection}>
+            <TransitionGroup name="van-fade">
+              {!data.loading && (
+                <>
+                  <div class={styles.periodHeader}>
+                    <div key="periodTitle" 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.searchGroup} onClick={() => {
+                      router.push({
+                        path: '/courseListSearch',
+                        query: {
+                          id: route.query.id,
+                          courseScheduleId: route.query.courseScheduleId
+                        }
+                      })
+                    }}>
+                      <img src={iconSearch} class={styles.iconSearch} />
+                      <span class={styles.searchContent}>搜索素材</span>
+                    </div>
+                  </div>
+                  
 
-              <div key="list" class={styles.periodList}>
-                <CellGroup inset>
-                  {data.list.map((item: any) => {
-                    const isLock =
-                      item.lockFlag ||
-                      ((route.query.code == 'select' || state.platformType == 'STUDENT') &&
-                        !item.unlock)
-                    const isSelect = route.query.code === 'select'
-                    return (
-                      <Cell
-                        border
-                        center
-                        title={item.coursewareDetailName}
-                        label={!browserInfo.isStudent ? `已使用${item.useNum || 0}次` : ''}
-                        onClick={() => !isLock && handleClick(item)}
-                      >
-                        {{
-                          icon: () => (
-                            <div class={styles.periodItem}>
-                              <div class={styles.periodItemModel}>
-                                <img src={isLock ? iconCourseLock : iconCourse} />
-                                {!isLock && String(item.accessScope) === '0' && (
-                                  <img class={styles.periodTip} src={iconTip} />
-                                )}
+                  <div key="list" class={styles.periodList}>
+                    <CellGroup inset>
+                      {data.list.map((item: any) => {
+                        const isLock =
+                          item.lockFlag ||
+                          ((route.query.code == 'select' || state.platformType == 'STUDENT') &&
+                            !item.unlock)
+                        const isSelect = route.query.code === 'select'
+                        return (
+                          <Cell
+                            border
+                            center
+                            title={item.coursewareDetailName}
+                            label={!browserInfo.isStudent ? `已使用${item.useNum || 0}次` : ''}
+                            onClick={() => !isLock && handleClick(item)}
+                          >
+                            {{
+                              icon: () => (
+                                <div class={styles.periodItem}>
+                                  <div class={styles.periodItemModel}>
+                                    <img src={isLock ? iconCourseLock : iconCourse} />
+                                    {!isLock && String(item.accessScope) === '0' && (
+                                      <img class={styles.periodTip} src={iconTip} />
+                                    )}
 
-                                {item.hasCache ? (
-                                  <img class={styles.iconCachePoint} src={iconCachePoint} />
-                                ) : (
-                                  ''
-                                )}
-                                {item.downloadStatus === 1 && (
-                                  <div class={styles.downloading}>{`${item.progress || 0}%`}</div>
-                                )}
-                              </div>
-                            </div>
-                          ),
-                          value: () => (
-                            <>
-                              {isSelect ? (
-                                <Button
-                                  disabled={isLock}
-                                  class={[styles.baseBtn, isLock ? styles.disable : styles.look]}
-                                >
-                                  选择
-                                </Button>
-                              ) : item.knowledgePointList ? (
+                                    {item.hasCache ? (
+                                      <img class={styles.iconCachePoint} src={iconCachePoint} />
+                                    ) : (
+                                      ''
+                                    )}
+                                    {item.downloadStatus === 1 && (
+                                      <div class={styles.downloading}>{`${item.progress || 0}%`}</div>
+                                    )}
+                                  </div>
+                                </div>
+                              ),
+                              value: () => (
                                 <>
-                                  {item.hasCache ? (
+                                  {isSelect ? (
                                     <Button
-                                      class={[
-                                        styles.baseBtn,
-                                        isLock ? styles.disable : styles.look
-                                      ]}
+                                      disabled={isLock}
+                                      class={[styles.baseBtn, isLock ? styles.disable : styles.look]}
                                     >
-                                      查看
+                                      选择
                                     </Button>
+                                  ) : item.knowledgePointList ? (
+                                    <>
+                                      {item.hasCache ? (
+                                        <Button
+                                          class={[
+                                            styles.baseBtn,
+                                            isLock ? styles.disable : styles.look
+                                          ]}
+                                        >
+                                          查看
+                                        </Button>
+                                      ) : (
+                                        <Button
+                                          // disabled={item.downloadStatus === 1 ? true : false}
+                                          class={[
+                                            styles.baseBtn,
+                                            isLock ? styles.disable : styles.down,
+                                            item.downloadStatus ? styles.downing : ''
+                                          ]}
+                                        >
+                                          {item.downloadStatus === 1 ? `取消下载` : '查看'}
+                                        </Button>
+                                      )}
+                                    </>
                                   ) : (
-                                    <Button
-                                      // disabled={item.downloadStatus === 1 ? true : false}
-                                      class={[
-                                        styles.baseBtn,
-                                        isLock ? styles.disable : styles.down,
-                                        item.downloadStatus ? styles.downing : ''
-                                      ]}
-                                    >
-                                      {item.downloadStatus === 1 ? `取消下载` : '查看'}
-                                    </Button>
+                                    ''
                                   )}
                                 </>
-                              ) : (
-                                ''
-                              )}
-                            </>
-                          )
-                        }}
-                      </Cell>
-                    )
-                  })}
-                </CellGroup>
-              </div>
-            </>
-          )}
-        </TransitionGroup>
-        {data.loading && <OLoading />}
-        {!data.loading && !data.list.length && <OEmpty tips="暂无内容" />}
-
+                              )
+                            }}
+                          </Cell>
+                        )
+                      })}
+                    </CellGroup>
+                  </div>
+                </>
+              )}
+            </TransitionGroup>
+            {data.loading && <OLoading />}
+            {!data.loading && !data.list.length && <OEmpty tips="暂无内容" />}
+          </div>
+        </div>
         <Popup v-model:show={data.catchStatus} class={styles.courseDialog}>
           <i class={styles.iconClose} onClick={() => (data.catchStatus = false)}></i>
           <div class={styles.title}>下载提醒</div>

+ 120 - 0
src/views/courseListSearch/child-node.tsx

@@ -0,0 +1,120 @@
+import { defineComponent } from "vue";
+import styles from './index.module.less'
+import { Cell, Collapse, CollapseItem } from "vant";
+import iconVideo from './image/icon-video.png'
+import iconSong from './image/icon-song.png'
+import iconImage from './image/icon-image.png'
+import { useRouter } from "vue-router";
+
+// 获取对应图片
+export const getImage = (item: any) => {
+  if (item.typeCode === 'VIDEO') {
+    return iconVideo;
+  } else if (['IMAGE', 'IMG'].includes(item.typeCode)) {
+    return iconImage;
+  } else if (item.typeCode === 'SONG') {
+    return iconSong;
+  } else {
+    return iconVideo;
+  }
+};
+
+const ChildNode = defineComponent({
+  name: 'child-node',
+  props: {
+    id: {
+      type: String,
+      default: ''
+    },
+    search: {
+      type: String,
+      default: ''
+    },
+    list: {
+      type: Array,
+      default: () => []
+    },
+    collapse: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['update:collapse', 'handleClick'],
+  setup(props, { emit }) {
+    const toDetail = (item: any) => {
+      emit("handleClick", item)
+    }
+
+    const formatName = (name: string) => {
+      if(!name || !props.search) return name
+      const search: any = props.search
+      return name.replace(search, `<span style="color: #F67146;">${search}</span>`)
+    }
+
+    console.log(props.collapse, "collapse")
+    return () => (
+      <Collapse
+        modelValue={props.collapse}
+        onUpdate:modelValue={(val: any) => {
+          emit('update:collapse', val);
+        }}
+        border={false}
+        accordion>
+        {props.list?.map((point: any) => (
+          <CollapseItem
+            clickable={false}
+            center
+            border={false}
+            class={styles.collapseChild}
+            name={point.id}>
+            {{
+              title: () => (
+                <div
+                  class={[
+                    styles.itemTitle,
+                    Array.isArray(point?.materialList) && point?.materialList.length > 0 ? styles.materialTitle : ''
+                  ]}>
+                  {point.name}
+                </div>
+              ),
+              default: () => (
+                <>
+                  {Array.isArray(point?.materialList) &&
+                    point.materialList.map((n: any) => (
+                      <Cell center isLink border={false} clickable={false} onClick={() => toDetail(n)}>
+                        {{
+                          title: () => <div class={styles.materialSection}>
+                            <img src={getImage(n)} class={styles.iconMaterial} />
+                            <div v-html={formatName(n.name)}></div>
+                          </div>
+                        }}
+                      </Cell>
+                    ))}
+                  {Array.isArray(point?.children) && (
+                    <ChildNode
+                      search={props.search}
+                      id={props.id}
+                      list={point.children}
+                      collapse={point.collapse}
+                      onUpdate:collapse={val => {
+                        point.collapse = val;
+                      }}
+                      onHandleClick={(item:any) => {
+                        toDetail(item)
+                      }}
+                    />
+                  )}
+                </>
+              ),
+              'right-icon': () => (
+                  <i class={[styles.arrow, props.collapse === point.id ? styles.arrowActive : '']}></i>
+              )
+            }}
+          </CollapseItem>
+        ))}
+      </Collapse>
+    );
+  }
+});
+
+export default ChildNode;

二進制
src/views/courseListSearch/image/icon-arrow-down.png


二進制
src/views/courseListSearch/image/icon-arrow-up.png


二進制
src/views/courseListSearch/image/icon-image.png


二進制
src/views/courseListSearch/image/icon-menu.png


二進制
src/views/courseListSearch/image/icon-song.png


二進制
src/views/courseListSearch/image/icon-video.png


+ 145 - 0
src/views/courseListSearch/index.module.less

@@ -0,0 +1,145 @@
+.courseListSearch {
+  min-height: 100vh;
+  background-color: #F8F8F8;
+  // background: linear-gradient(180deg, #7defe6 0%, rgba(255, 255, 255, 0) 170px);
+  background: linear-gradient( 180deg, #FCE5FA 0%, rgba(255,255,255,0) 170px), linear-gradient( 180deg, #FFE8CE 0%, rgba(251,233,213,0) 170px);
+  box-sizing: border-box;
+
+  :global {
+    .van-nav-bar__title {
+      width: 100%;
+      max-width: 100%;
+      margin-left: 46px;
+    }
+    .van-nav-bar__right {
+      display: none;
+    }
+    .van-search {
+      padding-left: 0;
+      // .van-search__content {
+      //   background-color: #fff !important;
+      // }
+    }
+
+    .o-result-container {
+      height: 90vh;
+    }
+  }
+}
+
+.collapseParent {
+  padding-top: 12px;
+
+  
+  :global {
+    .parentCollapse__item {
+      margin: 0 14px 12px;
+      &::after {
+        display: none;
+      }
+  
+      & >  .van-collapse-item__wrapper {
+        margin: 0 14px 12px;
+      }
+    }
+    .van-cell {
+      padding: 14px;
+      font-weight: 600;
+    }
+
+    .van-collapse-item {
+      background-color: #fff;
+      border-radius: 12px;
+      overflow: hidden;
+      
+    }
+
+    .van-collapse-item--border:after {
+      left: 0;
+      right: 0;
+    }
+
+    .van-collapse-item__content {
+      padding-top: 0;
+      padding-bottom: 0;
+      padding-right: 0;
+      padding-left: 0;
+    }
+  }
+}
+
+.collapseChild {
+  // margin: 0 !important;
+  :global {
+    .van-cell {
+      padding: 12px 0;
+      font-weight: 400;
+      font-size: 15px;
+      color: #333333;
+      line-height: 21px;  
+    }
+    .van-collapse-item__content {
+      // padding-left: 22px;
+
+      .van-cell {
+        padding: 12px 0;
+      }
+
+      .van-cell__title {
+        flex: 1 auto;
+      }
+
+      .van-cell__value {
+        flex-shrink: 0;
+        flex: 1 auto;
+      }
+    }
+  }
+}
+.materialSection {
+  display: flex;
+  align-items: center;
+  color: #333333;
+  padding-left: 10px;
+  .iconMaterial {
+    width: 32px;
+    height: 32px;
+    margin-right: 10px;
+  }
+}
+
+
+.itemTitle {
+  display: flex;
+  align-items: center;
+  font-size: 15px;
+  color: #333333;
+  line-height: 21px;
+  .iconMenu {
+    width: 36px;
+    height: 40px;
+    margin-right: 8px;
+  }
+
+  &.materialTitle::before {
+    content: '';
+    width: 4px;
+    height: 4px;
+    background: #F67146;
+    border-radius: 50%;
+    display: inline-block;
+    margin-right: 6px;
+  }
+}
+.arrow {
+  width: 16px;
+  height: 17px;
+  display: inline-block;
+  background: url('./image/icon-arrow-down.png');
+  background-size: contain;
+
+  &.arrowActive {
+    background: url('./image/icon-arrow-up.png');
+    background-size: contain;
+  }
+}

+ 309 - 0
src/views/courseListSearch/index.tsx

@@ -0,0 +1,309 @@
+import { computed, defineComponent, reactive, TransitionGroup, watch } from 'vue'
+import styles from './index.module.less'
+import OHeader from '@/components/o-header'
+import OSearch from '@/components/o-search'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import { useRoute, useRouter } from 'vue-router'
+import OLoading from '@/components/o-loading'
+import OEmpty from '@/components/o-empty'
+import { Cell, Collapse, CollapseItem } from 'vant'
+import ChildNode, { getImage } from './child-node'
+import { usePageVisibility } from '@vant/use'
+import iconMenu from './image/icon-menu.png'
+import OSticky from '@/components/o-sticky'
+import { browser } from "@/helpers/utils";
+import {  postMessage } from '@/helpers/native-message';
+import { handleCheckVip } from '../hook/useFee'
+
+export default defineComponent({
+  name: 'course-list-search',
+  setup() {
+    const route = useRoute()
+    const router = useRouter()
+    const browserInfo = browser()
+    const data = reactive({
+      titleOpacity: 0,
+      loading: true,
+      list: [] as any,
+      search: '' as string | undefined,
+      parentCollapse: '' as any
+      // childrenCollapse: '' as any
+    })
+    const formatDataList = (list: any = []) => {
+      const tempList: any = []
+      list.forEach((item: any) => {
+        let tempChild: any = {}
+        item.collapse = ''
+        tempChild = item
+        if (Array.isArray(item.children)) {
+          tempChild.children = formatDataList(item.children)
+        }
+        tempList.push({
+          ...tempChild
+        })
+      })
+      return tempList
+    }
+
+    const formatSelectFirstChild = (list: any = []): any => {
+      for (let i = 0; i < list.length; i++) {
+        if (Array.isArray(list[i].materialList) && list[i].materialList.length > 0) {
+          const materialItem = list[i].materialList[0] || {}
+          if (materialItem) {
+            return materialItem
+          }
+        } else {
+          return formatSelectFirstChild(list[i].children || [])
+        }
+      }
+    }
+
+    //
+    function selectFirstChild(pointList: any[], ids: any[]): any[] {
+      return pointList.map((point) => {
+        if (point.children) {
+          let id = ''
+          point.children.map((item: any) => {
+            if (!id) {
+              id = ids.includes(item.id) ? item.id : ''
+            }
+          })
+          point.collapse = id
+          return Object.assign(point, {
+            children: selectFirstChild(point.children, ids)
+          })
+        } else {
+          return Object.assign(point, {
+            materialList: point.materialList
+          })
+        }
+      })
+    }
+
+    function filterPointList(
+      pointList: any[],
+      parentData?: { ids: string[]; name: string }
+    ): any[] {
+      // 设置父级及以上id数组和父级name
+      return pointList.map((point) => {
+        if (point.children) {
+          return Object.assign(point, {
+            children: filterPointList(point.children, {
+              ids: [...(parentData?.ids || []), point.id],
+              name: point.name
+            })
+          })
+        } else {
+          return Object.assign(point, {
+            materialList: point.materialList.map((item: any) => {
+              item.parentData = {
+                ids: [...(parentData?.ids || []), point.id],
+                name: point.name
+              }
+              return item
+            })
+          })
+        }
+      })
+    }
+
+    const getList = async (search?: string) => {
+      data.loading = true
+        try {
+          const res: any = await request.post(
+            state.platformApi + '/courseSchedule/myCoursewareDetail/' + route.query.id, {
+              data: {
+                search,
+                searchFlag: true
+              }
+            }
+          )
+          if (Array.isArray(res?.data)) {
+            const _list = res.data
+            data.search = search;
+            _list.forEach((item: any) => {
+              item.children = item.knowledgePointList || [];
+              item.id = item.courseScheduleId;
+              item.name = item.coursewareDetailName;
+              formatDataList(item.children);
+            });
+            let list = filterPointList(_list)
+            const firstItem = formatSelectFirstChild(list)
+            list = selectFirstChild(list, firstItem?.parentData?.ids || [])
+            list.forEach((item: any) => {
+              if (item.id === firstItem.parentData?.ids[0]) {
+                data.parentCollapse = item.id
+              }
+            })
+            data.list = list
+          }
+        } catch (error) {}
+      
+      data.loading = false
+    }
+    getList()
+
+    // 获取子节点数据
+    const getKnowledgeMaterials = (list: any = []) => {
+      const tempList: any = []
+      list.forEach((item: any) => {
+        if (item.materialList && item.materialList.length > 0) {
+          tempList.push(...(item.materialList || []))
+        }
+
+        if (item.children && item.children.length > 0) {
+          tempList.push(...getKnowledgeMaterials(item.children || []))
+        }
+      })
+      return tempList
+    }
+
+    const handleClick = (item: any) => {
+      const ids = item.parentData?.ids || null
+      if(ids) {
+        let parentItem: any = {}
+        data.list.forEach((item: any) => {
+          if (item.id === ids[0]) {
+            parentItem = item
+          }
+        })
+        // 判断是否为VIP
+        if(parentItem.courseScheduleId) {
+          const hasFree = String(parentItem.accessScope) === '0'
+          if (!hasFree) {
+            const hasVip = handleCheckVip()
+            if (!hasVip) return
+          }
+        }
+      }
+      
+      if (browser().isApp) {
+        postMessage({
+          api: 'openWebView',
+          content: {
+            url: `${location.origin}${location.pathname}#/coursewarePlay?lessonId=${route.query.id}&source=search&kId=${item.id}&search=${encodeURIComponent(data.search)}`,
+            orientation: 0,
+            isHideTitle: true,
+            statusBarTextColor: false,
+            isOpenLight: true,
+            showLoadingAnim: true
+          }
+        });
+      } else {
+        router.push({
+          path: '/coursewarePlay',
+          query: {
+            lessonId: route.query.id,
+            kId: item.id,
+            search: data.search,
+            source: 'search'
+          }
+        });
+      }
+    }
+
+    return () => (
+      <div class={styles.courseListSearch}>
+        <OSticky position="top">
+          <OHeader background={`rgba(255,255,255, ${data.titleOpacity})`} border={false}>
+            {{
+              title: () => (
+                <div class={styles.title}>
+                  <OSearch
+                    inputBackground="white"
+                    background="transparent"
+                    placeholder="请输入素材关键词"
+                    onSearch={(val: string) => {
+                      getList(val)
+                    }}
+                  />
+                </div>
+              )
+            }}
+          </OHeader>
+        </OSticky>
+
+        <div style="height: calc(100vh - var(--header-height)); overflow-x: hidden; overflow-y: auto;">
+          <TransitionGroup name="van-fade">
+            {!data.loading && (
+              <Collapse
+                key="courseListSearch"
+                modelValue={data.parentCollapse}
+                onUpdate:modelValue={(val: any) => {
+                  data.parentCollapse = val
+                  // data.childrenCollapse = ''; // 重置子项选择
+                }}
+                class={styles.collapseParent}
+                border={false}
+                accordion
+              >
+                {data.list.map((item: any) => (
+                  <CollapseItem
+                    center
+                    border={true}
+                    name={item.courseScheduleId}
+                    clickable={false}
+                    class={['parentCollapse__item']}
+                  >
+                    {{
+                      title: () => (
+                        <div class={[styles.itemTitle]}>
+                          <img src={iconMenu} class={styles.iconMenu} />
+                          {item.coursewareDetailName}
+                        </div>
+                      ),
+                      default: () => (
+                        <>
+                          {Array.isArray(item?.materialList) &&
+                            item.materialList.map((n: any) => (
+                              <Cell center isLink clickable={false}>
+                                {{
+                                  title: () => (
+                                    <div class={styles.materialSection}>
+                                      <img src={getImage(n)} class={styles.iconMaterial} />
+                                      {n.name}
+                                    </div>
+                                  )
+                                }}
+                              </Cell>
+                            ))}
+                          {Array.isArray(item?.children) && (
+                            <ChildNode
+                              id={route.query.id as any}
+                              search={data.search}
+                              list={item.children}
+                              collapse={item.collapse}
+                              onUpdate:collapse={(val: any) => {
+                                item.collapse = val
+                              }}
+                              onHandleClick={(item: any) => {
+                                handleClick(item)
+                              }}
+                            />
+                          )}
+                        </>
+                      ),
+                      'right-icon': () => (
+                        <i
+                          class={[
+                            styles.arrow,
+                            data.parentCollapse === item.lessonCoursewareDetailId
+                              ? styles.arrowActive
+                              : ''
+                          ]}
+                        ></i>
+                      )
+                    }}
+                  </CollapseItem>
+                ))}
+              </Collapse>
+            )}
+          </TransitionGroup>
+          {data.loading && <OLoading />}
+          {!data.loading && !data.list.length && <OEmpty tips="暂无搜索结果" />}
+        </div>
+      </div>
+    )
+  }
+})

+ 23 - 0
src/views/coursewarePlay/component/point.module.less

@@ -25,10 +25,33 @@
     padding-top: 1px;
   }
 }
+.pointHeadSearch {
+  :global {
+    .van-search {
+      padding-top: 17px;
+      padding-left: 20px;
+      padding-right: 20px;
+
+      input {
+        color: rgba(255,255,255, 1);
+      }
+    }
+  }
+}
 .content {
   flex: 1;
   overflow-y: auto;
   padding: 0 20px;
+  .lading {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 14px;
+    .loadingText {
+      padding-left: 8px;
+      color: rgba(255, 255, 255, 0.8);
+    }
+  }
 }
 .collapse {
   &.childActive {

+ 322 - 0
src/views/coursewarePlay/component/points-search.tsx

@@ -0,0 +1,322 @@
+import { defineComponent, reactive, watch } from 'vue';
+import styles from './point.module.less';
+import { iconArrow } from '../image/icons.json';
+import {
+  iconImage,
+  iconImageActive,
+  iconVideo,
+  iconVideoActive,
+  iconSong,
+  iconSongActive
+} from '../image/icons.json';
+import { Collapse, CollapseItem, Image, Loading } from 'vant';
+import PlayLoading from './play-loading';
+import OSearch from '@/components/o-search';
+// import OLoading from '@/components/o-loading';
+import OEmpty from '@/components/o-empty';
+export default defineComponent({
+  name: 'points-list',
+  props: {
+    data: {
+      type: Array,
+      default: () => []
+    },
+    tabActive: {
+      type: String,
+      default: ''
+    },
+    itemActive: {
+      type: String,
+      default: ''
+    },
+    search: {
+      type: String,
+      default: ''
+    },
+    loading: {
+      type: Boolean,
+      default: false
+    },
+    open: {
+      type: Boolean,
+      default: false,
+    }
+  },
+  emits: ['handleSelect', 'handleSearch'],
+  setup(props, { emit }) {
+    const pointData = reactive({
+      search: props.search,
+      isSearch: false, // 判断是否搜索过
+      active: props.tabActive[0] || '',
+      childActive: props.tabActive[1] || '',
+      liftChildActive: props.tabActive[2] || '',
+    });
+    console.log(props.tabActive, "tabActive ------------");
+    watch(
+      () => props.tabActive,
+      () => {
+        pointData.active = props.tabActive[0] || '';
+        pointData.childActive = props.tabActive[1] || '';
+        pointData.liftChildActive = props.tabActive[2] || '';
+      }
+    );
+    
+    watch(() => props.open, () => {
+      pointData.search = props.search
+    })
+
+    // 获取对应图片
+    const getImage = (item: any) => {
+      if (item.typeCode === 'VIDEO') {
+        return props.itemActive == item.id ? iconVideoActive : iconVideo;
+      } else if (['IMAGE', 'IMG'].includes(item.typeCode)) {
+        return props.itemActive == item.id ? iconImageActive : iconImage;
+      } else if (item.typeCode === 'SONG') {
+        return props.itemActive == item.id ? iconSongActive : iconSong;
+      } else {
+        return props.itemActive == item.id ? iconVideoActive : iconVideo;
+      }
+    };
+
+    function formatName(name: string) {
+      if (!name || !pointData.search) return name
+      const search: any = pointData.search
+      return name.replace(search, `<span style="color: #F67146;">${search}</span>`)
+   }
+    return () => (
+      <div class={styles.container}>
+        <div class={styles.pointHeadSearch}>
+          <OSearch placeholder='请输入素材关键词' modelValue={pointData.search} background='transparent' inputBackground="transparent" onSearch={(val: any) => {
+            // 
+            if(props.loading) return
+            pointData.isSearch = true
+            pointData.search = val
+            emit('handleSearch', {
+              search: val
+            })
+          }} />
+        </div>
+        <div class={styles.content}>
+        {props.loading && <div class={styles.lading}>
+            <Loading size={24} color='rgba(255, 255, 255, 0.8)' /> <span class={styles.loadingText}>加载中...</span>
+          </div>}
+          
+          {/* {props.loading && <OLoading />} */}
+          {!props.loading && !props.data.length && <OEmpty tips="暂无搜索结果" />}
+          {props.data.length > 0 ? <Collapse
+            class={styles.collapse}
+            modelValue={pointData.active}
+            onUpdate:modelValue={(val: any) => {
+              pointData.active = val;
+            }}
+            accordion>
+            {props.data.map((item: any, index: number) => {
+              return (
+                <CollapseItem
+                  center
+                  border={false}
+                  class={index > 0 ? styles.borderTop : ''}
+                  isLink={false}
+                  title={item.name}
+                  name={item.id}>
+                  {{
+                    default: () => (
+                      <>
+                        {Array.isArray(item?.materialList) &&
+                          item.materialList.map((n: any) => {
+                            return (
+                              <div
+                                class={[
+                                  styles.item,
+                                  props.itemActive == n.id
+                                    ? styles.itemActive
+                                    : ''
+                                ]}
+                                onClick={() => {
+                                  emit('handleSelect', {
+                                    isSearch: pointData.isSearch,
+                                    itemActive: n.id,
+                                    tabActive: item.id,
+                                    tabName: item.name
+                                  });
+                                  pointData.isSearch = false
+                                }}>
+                                <Image
+                                  src={getImage(n)}
+                                  class={styles.itemImage}
+                                />
+                                <span
+                                  style={{ width: '80%' }}
+                                  class="van-ellipsis">
+                                  {n.name}
+                                </span>
+                                {/* <Icon name={iconZhibo} /> */}
+                                <div class={styles.playLoading}>
+                                  <PlayLoading />
+                                </div>
+                              </div>
+                            );
+                          })}
+
+                        {Array.isArray(item?.children) && (
+                          <Collapse
+                            class={[
+                              styles.collapse,
+                              pointData.active === item.id
+                                ? styles.childActive
+                                : ''
+                            ]}
+                            modelValue={pointData.childActive}
+                            onUpdate:modelValue={(val: any) => {
+                              pointData.childActive = val;
+                            }}
+                            accordion>
+                            {item?.children.map((child: any) => {
+                              return (
+                                <CollapseItem
+                                  center
+                                  border={false}
+                                  isLink={false}
+                                  title={child.name}
+                                  name={child.id}
+                                  class={styles.childCollapseItem}>
+                                  {{
+                                    default: () => (
+                                      <>
+                                        {Array.isArray(child?.materialList) &&
+                                          child.materialList.map((n: any) => {
+                                            return (
+                                              <div
+                                                class={[
+                                                  styles.item,
+                                                  props.itemActive == n.id
+                                                    ? styles.itemActive
+                                                    : ''
+                                                ]}
+                                                onClick={() => {
+                                                  emit('handleSelect', {
+                                                    isSearch: pointData.isSearch,
+                                                    itemActive: n.id,
+                                                    tabActive: child.id,
+                                                    tabName: child.name
+                                                  });
+                                                  pointData.isSearch = false
+                                                }}>
+                                                <Image
+                                                  src={getImage(n)}
+                                                  class={styles.itemImage}
+                                                />
+                                                <span
+                                                  style={{ width: '73%' }}
+                                                  class="van-ellipsis" v-html={formatName(n.name)}>
+                                                  {/* {n.name} */}
+                                                </span>
+                                                {/* <Icon name={iconZhibo} /> */}
+                                                <div class={styles.playLoading}>
+                                                  <PlayLoading />
+                                                </div>
+                                              </div>
+                                            );
+                                          })}
+
+                                          {Array.isArray(child?.children) && (
+                                            <Collapse
+                                              class={[
+                                                styles.collapse,
+                                                pointData.liftChildActive === child.id
+                                                  ? styles.childActive
+                                                  : ''
+                                              ]}
+                                              modelValue={pointData.liftChildActive}
+                                              onUpdate:modelValue={(val: any) => {
+                                                pointData.liftChildActive = val;
+                                              }}
+                                              accordion>
+                                              {child?.children.map((liftChild: any) => {
+                                                return (
+                                                  <CollapseItem
+                                                    center
+                                                    border={false}
+                                                    isLink={false}
+                                                    title={liftChild.name}
+                                                    name={liftChild.id}
+                                                    class={styles.childCollapseItem}>
+                                                    {{
+                                                      default: () => (
+                                                        <>
+                                                          {Array.isArray(liftChild?.materialList) &&
+                                                            liftChild.materialList.map((n: any) => {
+                                                              return (
+                                                                <div
+                                                                  class={[
+                                                                    styles.item,
+                                                                    props.itemActive == n.id
+                                                                      ? styles.itemActive
+                                                                      : ''
+                                                                  ]}
+                                                                  onClick={() => {
+                                                                    emit('handleSelect', {
+                                                                      isSearch: pointData.isSearch,
+                                                                      itemActive: n.id,
+                                                                      tabActive: liftChild.id,
+                                                                      tabName: liftChild.name
+                                                                    });
+                                                                    pointData.isSearch = false
+                                                                  }}>
+                                                                  <Image
+                                                                    src={getImage(n)}
+                                                                    class={styles.itemImage}
+                                                                  />
+                                                                  <span
+                                                                    style={{ width: '73%' }}
+                                                                    class="van-ellipsis" v-html={formatName(n.name)}>
+                                                                    {/* {n.name} */}
+                                                                  </span>
+                                                                  {/* <Icon name={iconZhibo} /> */}
+                                                                  <div class={styles.playLoading}>
+                                                                    <PlayLoading />
+                                                                  </div>
+                                                                </div>
+                                                              );
+                                                            })}
+                                                        </>
+                                                      ),
+                                                      icon: () => (
+                                                        <img
+                                                          class={styles.arrow}
+                                                          src={iconArrow}
+                                                        />
+                                                      )
+                                                    }}
+                                                  </CollapseItem>
+                                                );
+                                              })}
+                                            </Collapse>
+                                          )}
+                                      </>
+                                    ),
+                                    icon: () => (
+                                      <img
+                                        class={styles.arrow}
+                                        src={iconArrow}
+                                      />
+                                    )
+                                  }}
+                                </CollapseItem>
+                              );
+                            })}
+                          </Collapse>
+                        )}
+                      </>
+                    ),
+                    icon: () => <img class={styles.arrow} src={iconArrow} />
+                  }}
+                </CollapseItem>
+              );
+            })}
+          </Collapse>: ""}
+        </div>
+      </div>
+    );
+  }
+});

File diff suppressed because it is too large
+ 0 - 0
src/views/coursewarePlay/image/icons.json


+ 278 - 28
src/views/coursewarePlay/index.tsx

@@ -23,7 +23,7 @@ import qs from 'query-string'
 import MusicScore from './component/musicScore'
 // import iconDian from './image/icon-dian.svg'
 // import iconPoint from './image/icon-point.svg'
-import { iconUp, iconDown, iconPen, iconTouping, iconMenu, iconCourseType } from './image/icons.json'
+import { iconUp, iconDown, iconPen, iconTouping, iconMenu, iconCourseType, iconSearch } from './image/icons.json'
 import Points from './component/points'
 import { browser } from '@/helpers/utils'
 import { Vue3Lottie } from 'vue3-lottie'
@@ -42,6 +42,7 @@ import CoursewareType from './component/courseware-type'
 import CoursewareTips from './component/courseware-tips'
 import GlobalTools from '@/components/globalTools'
 import { isPlay, penShow, toolOpen, whitePenShow } from '@/components/globalTools/globalTools'
+import PointsSearch from './component/points-search'
 
 export default defineComponent({
   name: 'CoursewarePlay',
@@ -118,7 +119,13 @@ export default defineComponent({
     const route = useRoute()
     const headeRef = ref()
     const isCurrentCoursewareMenu = shallowRef(true) // 是否为当前选的课程类型
+    const detailTempSearchList = shallowRef<any[]>()
+    const detailList = shallowRef<any[]>()// 搜索来的所有数据 
     const data = reactive({
+      source: route.query.source as any, // 来源 search  搜索
+      searchLoading: false, // 搜索加载状态
+      search: route.query.search as any, // 默认的搜索条件 - 
+      searchTemp: route.query.search as any, // 默认的搜索条件 - 
       currentId: route.query.id as any,
       detail: null as any,
       knowledgePointList: [] as any,
@@ -352,6 +359,184 @@ export default defineComponent({
       }
     }
 
+    const getSearchItemList = async (knowledgePointList: any[]) => {
+      const list: any = [];
+
+      for (let i = 0; i < knowledgePointList.length; i++) {
+        const item = knowledgePointList[i];
+        if (item.materialList && item.materialList.length > 0) {
+          const tempList = await getTempList(item.materialList, item.name);
+          list.push(...tempList);
+        }
+
+        // 第二层级
+        if (item.children && item.children.length > 0) {
+          const childrenList = item.children || [];
+          for (let j = 0; j < childrenList.length; j++) {
+            const childItem = childrenList[j];
+            const tempList = await getTempList(
+              childItem.materialList,
+              childItem.name
+            );
+            list.push(...tempList);
+          }
+        }
+      }
+
+      return list
+    };
+
+
+    /** 从搜索页面来的 */
+    const getSearchDetail = async (params: { type?: string, id?: any, search?: string }) => {
+      try {
+        const res = await request.post(
+          state.platformApi +
+            `/courseSchedule/myCoursewareDetail/${params.id || route.query.lessonId}`,
+          {
+            hideLoading: true,
+            data: {
+              detailFlag: "1",
+              search: params.search
+            }
+          }
+        );
+        const result = res.data || []
+        const allList: any[] = []
+        for(let i = 0; i < result.length; i++) {
+          const itemResult = result[i];
+          itemResult.name = itemResult.coursewareDetailName;
+          itemResult.id = itemResult.courseScheduleId;
+          itemResult.lessonTargetDesc = itemResult.lessonTargetDesc ? itemResult.lessonTargetDesc.replace(/\n/g, "<br />") : ""
+          if (Array.isArray(itemResult?.knowledgePointList)) {
+            let index = 0;
+            itemResult.children = itemResult.knowledgePointList.map(
+              (n: any) => {
+                if (Array.isArray(n.materialList)) {
+                  n.materialList = n.materialList.map((item: any) => {
+                    index++;
+                    const materialRefs = item.materialRefs
+                      ? item.materialRefs
+                      : [];
+                    const materialMusicId =
+                      materialRefs.length > 0
+                        ? materialRefs[0].resourceIdStr
+                        : null;
+                    const useStatus = materialRefs.length > 0
+                    ? materialRefs[0]?.extend?.useStatus : null
+                    const isLock = useStatus === 'LOCK' && state.platformType === "STUDENT" ? true : false
+                    return {
+                      ...item,
+                      isLock,
+                      materialMusicId,
+                      content: item.content,
+                      coursewareDetailId: itemResult.courseScheduleId,
+                      knowledgePointId: [itemResult.courseScheduleId, item.knowledgePointId],
+                      materialId: item.id,
+                      id: (i * 1000 + '') + index + ''
+                    };
+                  });
+                }
+                if (Array.isArray(n.children)) {
+                  n.children = n.children.map((cn: any) => {
+                    cn.materialList = cn.materialList.map((item: any) => {
+                      index++;
+                      const materialRefs = item.materialRefs
+                        ? item.materialRefs
+                        : [];
+                      const materialMusicId =
+                        materialRefs.length > 0
+                          ? materialRefs[0].resourceIdStr
+                          : null;
+                      const useStatus = materialRefs.length > 0
+                      ? materialRefs[0]?.extend?.useStatus : null
+                      const isLock = useStatus === 'LOCK' && state.platformType === "STUDENT" ? true : false
+                      return {
+                        ...item,
+                        isLock,
+                        materialMusicId,
+                        coursewareDetailId: itemResult.courseScheduleId,
+                        content: item.content,
+                        knowledgePointId: [itemResult.courseScheduleId, n.id, item.knowledgePointId],
+                        materialId: item.id,
+                        id: (i * 1000 + '') + index + ''
+                      };
+                    });
+                    return cn;
+                  });
+                }
+                return n;
+              }
+            );
+            itemResult.knowledgePointList = null // 去掉不要的
+            itemResult.list = await getSearchItemList(itemResult.children);
+
+            allList.push(...itemResult.list)
+          }
+        }
+        if(params.type === 'pointSearch') {
+          detailTempSearchList.value = result
+
+          // 初始化选中的数据 临时
+          popupData.tempTabActive = allList.length > 0 ? allList[0].knowledgePointId : []
+          popupData.tempItemActive = "-1"
+          data.searchTemp = params.search
+          return
+        }
+        detailList.value = result
+        detailTempSearchList.value = result
+
+        if(!params.type) {
+          let _firstIndex = allList.findIndex(
+            (n: any) =>
+              n.knowledgePointMaterialRelationId == route.query.kId ||
+              n.materialId == route.query.kId
+          );
+          _firstIndex = _firstIndex > -1 ? _firstIndex : 0;
+          const item = allList[_firstIndex];
+          // console.log(item, 'item')
+          // console.log(_firstIndex, '_firstIndex', route.query.kId, 'route.query.kId', item)
+          // 是否自动播放
+          if (activeData.isAutoPlay) {
+            item.autoPlay = true;
+          }
+
+          popupData.activeIndex = _firstIndex;
+          popupData.playIndex = _firstIndex;
+          popupData.tabName = item.tabName;
+          popupData.tabActive = item.knowledgePointId;
+          popupData.itemActive = item.id;
+          popupData.itemName = item.name;
+          data.detail = detailList.value?.find((child: any) => child.coursewareDetailId === item.coursewareDetailId)
+        }
+        
+        nextTick(() => {
+          data.itemList = allList;
+          checkedAnimation(popupData.activeIndex);
+          postMessage({
+            api: 'courseLoading',
+            content: {
+              show: false,
+              type: 'fullscreen'
+            }
+          });
+
+          if (data.disableScreenRecordingFlag === '1') {
+            // 检测是否录屏
+            handleLimitScreenRecord();
+          }
+          setTimeout(() => {
+            data.animationState = 'end';
+          }, 500);
+        });
+
+        
+        return true
+      } catch (error) {
+        console.log(error);
+      }
+    }
+
     const onTitleTip = (type: "phaseGoals" | "checkItem", text: string) => {
       handleStop()
       popupData.pointOpen = true
@@ -488,11 +673,15 @@ export default defineComponent({
       if (state.platformType === 'STUDENT') {
         await getLookVideoData()
       }
-      // 只有老师有 课程类型 切换
-      if(state.platformType === "TEACHER") {
-        await getRefLevel()
+      if(data.source === 'search') {
+        await getSearchDetail({search: data.search})
+      } else {
+        // 只有老师有 课程类型 切换
+        if(state.platformType === "TEACHER") {
+          await getRefLevel()
+        }
+        await getDetail()
       }
-      await getDetail()
       const hasFree = String(data.detail?.accessScope) === '0'
       if (!hasFree) {
         const hasVip = handleCheckVip()
@@ -557,6 +746,8 @@ export default defineComponent({
       open: false,
       activeIndex: 0,
       playIndex: 0,
+      tempTabActive: '', // 临时选中
+      tempItemActive: "", // 临时编号
       tabActive: '',
       tabName: '',
       itemActive: '',
@@ -712,6 +903,17 @@ export default defineComponent({
     const acitveTimer = ref()
     // 轮播切换
     const handleSwipeChange = async (index: number) => {
+      if(data.source === 'search') {
+        const item = data.itemList[index];
+        data.detail = detailList.value?.find((child: any) => child.coursewareDetailId === item.coursewareDetailId)
+        popupData.tabActive = item.knowledgePointId;
+        popupData.itemActive = item.id;
+        popupData.itemName = item.name;
+        popupData.tabName = item.tabName;
+        if (item.typeCode == 'SONG') {
+          activeData.model = true;
+        }
+      }
       // 如果是当前正在播放 或者是视频最后一个
       if (popupData.activeIndex == index) return
       await handleStop()
@@ -1201,20 +1403,34 @@ export default defineComponent({
             {activeData.model && (
               <div class={styles.leftFixedBtns} onClick={(e: Event) => e.stopPropagation()}>
                 <div class={[styles.btnsWrap, styles.prePoint]}>
-                  {state.platformType === 'TEACHER' && <div class={styles.fullBtn} onClick={() => {
-                    popupData.coursewareOpen = true
-                    handleStop()
-                  }}>
-                    <img src={iconCourseType} />
-                  </div>}
+                {data.source === 'search' ? 
+                    <div class={styles.fullBtn} onClick={() => {
+                      handleStop()
+                      detailTempSearchList.value = detailList.value
+                      popupData.tempItemActive = ""
+                      popupData.tempTabActive = ""
+                      data.searchTemp = ""
+                      // data.searchTemp = JSON.parse(JSON.stringify(data.search))
+                      popupData.open = true
+                    }}>
+                      <img src={iconSearch} />
+                    </div> : <>
+                    {state.platformType === 'TEACHER' && <div class={styles.fullBtn} onClick={() => {
+                      popupData.coursewareOpen = true
+                      handleStop()
+                    }}>
+                      <img src={iconCourseType} />
+                    </div>}
+                    
+                    <div class={styles.fullBtn} onClick={() => {
+                      popupData.open = true
+                      handleStop()
+                    }}>
+                      <img src={iconMenu} />
+                      {/* <span>知识点</span> */}
+                    </div>
+                  </>}
                   
-                  <div class={styles.fullBtn} onClick={() => {
-                    popupData.open = true
-                    handleStop()
-                  }}>
-                    <img src={iconMenu} />
-                    {/* <span>知识点</span> */}
-                  </div>
                     <div
                       class={[styles.fullBtn, !(popupData.activeIndex != 0) && styles.disabled]}
                       onClick={() => {
@@ -1330,16 +1546,50 @@ export default defineComponent({
           v-model:show={popupData.open}
           onClose={handleClosePopup}
         >
-          <Points
-            data={data.knowledgePointList}
-            tabActive={popupData.tabActive}
-            itemActive={popupData.itemActive}
-            onHandleSelect={(res: any) => {
-              // onChangeSwiper('change', res.itemActive)
-              popupData.open = false
-              toggleMaterial(res.itemActive)
-            }}
-          />
+          {data.source === 'search' ? 
+              <PointsSearch
+                data={detailTempSearchList.value}
+                search={data.searchTemp || data.search}
+                loading={data.searchLoading}
+                tabActive={popupData.tempTabActive || popupData.tabActive}
+                itemActive={popupData.tempItemActive || popupData.itemActive}
+                open={popupData.open}
+                onHandleSelect={(res: any) => {
+                  popupData.open = false;
+                  if(res.isSearch) {
+                    detailList.value = detailTempSearchList.value
+                    const tempList: any[] = []
+                    detailTempSearchList.value?.forEach((item: any) => {
+                      if(Array.isArray(item.list)) {
+                        tempList.push(...item.list)
+                      }
+                    })
+                    data.itemList = tempList || []
+                    data.search = data.searchTemp ? JSON.parse(JSON.stringify(data.searchTemp)) : ''
+                  }
+                  toggleMaterial(res.itemActive);
+                }}
+                onHandleSearch={async (val: any) => {
+                  data.searchLoading = true
+                  detailTempSearchList.value = []
+                  await getSearchDetail({
+                    type: 'pointSearch',
+                    search: val.search
+                  })
+                  data.searchTemp = val.search;
+                  data.searchLoading = false
+                }} /> : 
+                <Points
+                data={data.knowledgePointList}
+                tabActive={popupData.tabActive}
+                itemActive={popupData.itemActive}
+                onHandleSelect={(res: any) => {
+                  // onChangeSwiper('change', res.itemActive)
+                  popupData.open = false
+                  toggleMaterial(res.itemActive)
+                }}
+              />}
+          
         </Popup>
 
         <Popup

+ 1 - 1
vite.config.ts

@@ -12,7 +12,7 @@ function resolve(dir: string) {
 // https://vitejs.dev/config/
 // https://github.com/vitejs/vite/issues/1930 .env
 // const proxyUrl = 'https://online.lexiaoya.cn/';
-const proxyUrl = 'https://test.lexiaoya.cn/'
+const proxyUrl = 'https://dev.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/' // 尚科

Some files were not shown because too many files changed in this diff