Browse Source

feat: 家园共育下载

lvkun996 1 year ago
parent
commit
342346dc9f

+ 24 - 19
README.md

@@ -1,20 +1,25 @@
-# zd-app-web
-
-
-
-## 访问url
-
-  https://zaojiao.net/app_web/learn-plan.html#/blue-light-tip 学习计划
-
-  https://zaojiao.net/app_web/section-audition.html#/et1WkdUu7ILvQFK 课程小节试听
-
-  https://zaojiao.net/app_web/lab.html#/ 蚂蚁抄丘与弗雷德一起探案
-
-  https://zaojiao.net/app_web/download-app.html#/  下载逻辑狗
-
-  https://zaojiao.net/app_web/course.html#/  家园共育app -> 园所端 -> 分享出来的课程详情页 
-
-  https://zaojiao.net/app_web/lp.html#/  动画课程试听试看
-
-## NODE 版本
+# zd-app-web
+
+
+
+## 访问url
+
+  https://zaojiao.net/app_web/learn-plan.html#/blue-light-tip 学习计划
+
+  https://zaojiao.net/app_web/section-audition.html#/et1WkdUu7ILvQFK 课程小节试听
+
+  https://zaojiao.net/app_web/lab.html#/ 蚂蚁抄丘与弗雷德一起探案
+
+  https://zaojiao.net/app_web/download-app.html#/  下载逻辑狗-一起成长
+
+  https://zaojiao.net/app_web/download-app-parent.html#/  下载逻辑狗-家园共育
+
+  https://zaojiao.net/app_web/course.html#/  家园共育app -> 园所端 -> 分享出来的课程详情页 
+
+  https://zaojiao.net/app_web/lp.html#/  动画课程试听试看
+
+
+  https://zaojiao.net/app_web/pay.html#/  公共的支付页面
+
+## NODE 版本
   14.19.0

BIN
dist.zip


+ 14 - 14
src/pages/Course/main.ts

@@ -1,14 +1,14 @@
-import { createApp } from 'vue'
-import App from './App.vue'
-import router from './router'
-import 'lib-flexible'
-import 'normalize.css'
-import * as Pinia from 'pinia'
-import VConsole from 'vconsole'
-import '@/utils/vant'
-
-// const vconsole = new VConsole()
-
-// import store from './store'
-
-createApp(App).use(router).use(Pinia.createPinia()).mount('#course')
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+import 'lib-flexible'
+import 'normalize.css'
+import * as Pinia from 'pinia'
+import VConsole from 'vconsole'
+import '@/utils/vant'
+
+// const vconsole = new VConsole()
+
+// import store from './store'
+
+createApp(App).use(router).use(Pinia.createPinia()).mount('#course')

+ 536 - 536
src/pages/Course/views/index.vue

@@ -1,536 +1,536 @@
-<template>
-  <div calss="course-detail" >
-    <!-- 课程详情 -->
-    <div class="course" >
-    <div class="cover">
-      <img :src="state.imgCover" alt="">
-    </div>
-    <div class="desc" >
-      <div class="price" >
-        <div class="current-price" >{{state.price}}</div>
-        <div class="discount-price" >原价:¥{{state.markingPrice}}</div>
-      </div>
-      <div class="title" >{{state.name}}</div>
-      <div class="subtitle" >{{state.simpleDescription}}</div>
-      <div class="sub-desc" >
-        <div class="tag" >
-          <div class="tag-item" >{{state.suitAge}}岁</div>
-          <div class="tag-item" >{{state.chapterList.length}}讲</div>
-        </div>
-        <div class="buy" >
-          <img :src="require('@/pages/Course/assets/learn_count.png')" alt="">
-          <div>{{state.courseCount}}人学过</div>
-        </div>
-      </div>
-    </div>
-    </div>
-    <!-- 目录 -->
-    <div class='meun-section' >
-      <div class="tabs" :style="{top: currentVideo ? '210px' : '0px' }">
-        <div
-          :class="['tabs-item', curTabRef === item.id ? 'tabs-item-active' : '']"
-          v-for="item in tabs"
-          :key="item.id"
-          @click="changeTabs(item.id)"
-        >
-          {{item.name}}
-        </div>
-        <div class="line" :style="{left: curTabRef === 0 ? '80px' : '268px'}" ></div>
-      </div>
-      <div class="course-desc"  v-if="curTabRef === 0" >
-        <div v-html="state.description" ></div>
-      </div>
-      <div class="course-meun" v-if="curTabRef === 1"  >
-        <!-- 小分类 -->
-        <div class='course-meun-tabs'  >
-          <div :class="['course-meun-tabs-item', chapterIdRef === item.id ? 'course-meun-tabs-item-active' : '']" @click="changeChapter(index, item.id)" v-for="(item, index) in state.chapterList" :key="item.id">
-            {{item.name}}
-          </div>
-        </div>
-        <div
-          class="course-meun-item"
-          v-for="_ in  currentMediaList"
-          :key="_.id"
-        >
-          <div class='cover' @click="playCourse(_)">
-            <div class="overlay" v-if="_.payType === 0" >
-              <img class="lock" :src="require('@/pages/Course/assets/lock.png')" alt="">
-            </div>
-            <img  :src="_.imgCover" alt="">
-          </div>
-          <div class="course-meun-item-intro"  >
-            <div class="title-container" >
-              <div class="title">{{_.name}}</div>
-              <div class="try-see" v-if="_.payType !== 0" >试看</div>
-            </div>
-            <div class="intro" >
-              <div class="intro-item" v-if="mediaType === 0" ><img :src="require('@/pages/Course/assets/time.png')" alt=""><div>{{getDuration(_.video.duration)}}</div></div>
-              <div class="intro-item" ><img :src="require('@/pages/Course/assets/play.png')" alt=""><div>{{_.readCountStr}}</div></div>
-              <div class="intro-item" @click="openTeachingMaterial(_)" ><van-icon name="description" style="margin-right: 5px;margin-top: 2px;" /><div>资料</div></div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-
-  <video
-    v-if="currentVideo"
-    :style="{zIndex: currentVideo? 30 : 1}"
-    :src="currentVideo"
-    controls
-    autoplay
-    playsinline
-  >
-  </video>
-
-  <!-- 打开app的按钮 如果没有app,就去应用市场 -->
-  <div class="btn" >
-    <!-- <div class="open-app-btn" >
-      加入学习解锁全部课程
-    </div> -->
-    <!-- <OpenApp appid='wxe87236d542cd0f94'   /> -->
-    <OpenApp appid='wxf6e96c65ba6116d4' text="加入学习解锁全部课程" :extinfo="'/course/pipeline?course_id=' + skuId"  />
-  </div>
-</template>
-
-<script setup lang="ts">
-import { getAICourse } from '@/api/course'
-import { getParentWXSignature } from '@/api/common'
-import { onMounted, ref } from 'vue'
-import OpenApp from '@/components/OpenApp/index.vue'
-import { registerWxopenButton } from '@/utils/utils'
-import { useRoute, useRouter } from 'vue-router'
-
-const userAgent = navigator.userAgent
-
-// 判断是否在微信中
-// var isInWeChat = /MicroMessenger/.test(userAgent)
-
-const route = useRoute()
-
-const router = useRouter()
-
-const skuId = route.query.skuId
-
-const tabs = [
-  {
-    name: '详情',
-    id: 0
-  },
-  {
-    name: '目录',
-    id: 1
-  }
-]
-
-const curTabRef = ref(0)
-
-const state = ref({
-  chapterList: []
-})
-
-const currentVideo = ref('')
-
-const currentMediaList = ref([])
-
-const chapterIdRef = ref('')
-
-const openTeachingMaterial = (record: any) => {
-  if (record.payType == 0) return
-  window.open(record.teachingMaterial.fileUrl)
-}
-
-const changeChapter = (index: number, id: string) => {
-  currentMediaList.value = state.value.chapterList[index].itemList
-  chapterIdRef.value = id
-}
-
-const getDuration = (count: any) => {
-  const m = Math.floor(Number(count).toFixed(0) / 60)
-  const s = Number(count).toFixed(0) % 60
-  return (m > 10 ? m : '0' + m) + ':' + (s > 10 ? s : '0' + s)
-}
-
-// 0  视频  2 图文 1 音频
-const mediaType = ref(0)
-
-const playCourse = (record) => {
-  if (record.payType === 0) return
-  if (mediaType.value === 0) {
-    currentVideo.value = record.video.videoUrl
-  } else if (mediaType.value === 2) {
-    router.push({
-      path: '/media',
-      query: { id: record.id }
-    })
-  }
-}
-
-const changeTabs = (id: number) => {
-  curTabRef.value = id
-}
-
-// 获取课程
-const _getAICourse = async () => {
-  const { data } = await getAICourse({ skuId: skuId as string, hasWork: '' })
-  state.value = data
-  mediaType.value = data.mediaType
-  currentMediaList.value = data.chapterList[0].itemList
-  chapterIdRef.value = data.chapterList[0].id
-}
-
-onMounted(() => {
-  _getAICourse()
-  registerWxopenButton(getParentWXSignature)
-})
-
-</script>
-
-<style lang="scss" scoped >
-.course-detail {
-  width: 100vw;
-  min-height: 100vh;
-  background-color: #F6F6F6;
-}
-.course {
-  .cover {
-    width: 375px;
-    height: 231px;
-    background-color: deepskyblue;
-    position: relative;
-    z-index: 1;
-
-    img {
-      width: 100%;
-      height: 100%;
-      display: block;
-      object-fit: cover;
-      position: absolute;
-      top: 0;
-      left: 0;
-      z-index: 2;
-    }
-  }
-  .desc {
-    width: 375px;
-    height: 185px;
-    background: #FFFFFF;
-    box-shadow: 0px 6px 11px 4px rgba(231,237,241,0.6);
-    border-radius: 22px 22px 0px 0px;
-    margin-top: -22px;
-    padding: 16px;
-    box-sizing: border-box;
-    position: relative;
-    z-index: 2;
-    .price {
-      display: flex;
-      align-items: center;
-      .current-price {
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 600;
-        font-size: 26px;
-        color: #FF1F1F;
-        line-height: 37px;
-        text-align: left;
-        font-style: normal;
-        margin-right: 12px;
-      }
-      .discount-price {
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 400;
-        font-size: 12px;
-        color: #999999;
-        line-height: 17px;
-        text-align: left;
-        font-style: normal;
-        text-decoration-line: line-through;
-      }
-    }
-    .title {
-      font-family: PingFangSC, PingFang SC;
-      font-weight: 600;
-      font-size: 18px;
-      color: #333333;
-      line-height: 25px;
-      text-align: left;
-      font-style: normal;
-      margin-top: 6px;
-    }
-    .subtitle {
-      font-family: PingFangSC, PingFang SC;
-      font-weight: 400;
-      font-size: 13px;
-      color: #797979;
-      line-height: 20px;
-      text-align: justify;
-      font-style: normal;
-      margin-top: 5px;
-    }
-    .sub-desc {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      margin-top: 16px;
-      .tag {
-        display: flex;
-        .tag-item {
-          width: 60px;
-          height: 23px;
-          background: #FFF2E8;
-          margin-right: 14px;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          font-family: PingFangSC, PingFang SC;
-          font-weight: 400;
-          font-size: 11px;
-          color: #FF7422;
-          font-style: normal;
-        }
-      }
-      .buy {
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 400;
-        font-size: 12px;
-        color: #999999;
-        line-height: 23px;
-        text-align: left;
-        font-style: normal;
-        display: flex;
-        align-items: center;
-        img {
-          width: 11px;
-          height: 11px;
-          margin-right: 4px;
-        }
-      }
-    }
-  }
-}
-
-.meun-section {
-  margin-top: 20px;
-  background-color: #F6F6F6;
-
-    .tabs {
-      width: 100vw;
-      height: 58px;
-      display: flex;
-      align-items: center;
-      justify-content: space-around;
-      background-color: #fff;
-      position: sticky;
-      top: 210px;
-      z-index: 4;
-      .tabs-item {
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 500;
-        font-size: 16px;
-        color: #999999;
-        line-height: 22px;
-        text-align: left;
-        font-style: normal;
-      }
-      .tabs-item-active {
-        font-weight: 600;
-        font-size: 17px;
-        color: #333333;
-        line-height: 24px;
-      }
-      .line {
-        width: 30px;
-        height: 6px;
-        background-color: #0B57C7;
-        border-radius: 10px;
-        position: absolute;
-        top: 44px;
-        left: 80px;
-      }
-    }
-    .course-desc {
-      width: 100vw;
-      height: 42vh;
-      padding: 16px;
-      box-sizing: border-box;
-      font-weight: 600;
-      font-size: 16px;
-      color: #636161;
-      line-height: 18px;
-    }
-    .course-meun {
-      width: 100vw;
-      padding: 16px;
-      padding-left: 26px;
-      box-sizing: border-box;
-      padding-bottom: 100px;
-      .course-meun-tabs {
-        margin-bottom: 20px;
-        width: calc(100vw - 32px);
-        overflow: hidden;
-        overflow-x: scroll;
-        display: flex;
-        align-items: center;
-        .course-meun-tabs-item {
-          background: #F6F6F6;
-          border-radius: 18px;
-          padding: 8px 20px;
-          box-sizing: border-box;
-          font-family: PingFangSC, PingFang SC;
-          font-weight: 500;
-          font-size: 15px;
-          color: #9B9B9B;
-          line-height: 21px;
-          height: 36px;
-          margin-right: 20px;
-          background-color: #fff;
-        }
-        .course-meun-tabs-item-active {
-          border: 1px solid #0B57C7;
-          color: #0B57C7
-        }
-      }
-      .course-meun-item {
-        display: flex;
-        align-items: center;
-        margin-bottom: 20px;
-        .cover {
-          width: 107px;
-          height: 60px;
-          margin-right: 14px;
-          position: relative;
-          .overlay {
-            width: 107px;
-            height: 60px;
-            background-color: rgba( 0, 0, 0, 0.6);
-            position: absolute;
-            top: 0;
-            left: 0;
-            z-index: 3;
-            display: flex;
-            justify-content: center;
-            align-items: start;
-            border-radius: 20px;
-            .lock {
-              width: 17px;
-              height: 16px;
-              display: block;
-              position: absolute;
-              top: 50%;
-              left: 50%;
-              transform: translate(-50%, -50%);
-            }
-          }
-          img {
-            width: 107px;
-            height: 60px;
-            border-radius: 20px;
-            display: block;
-            object-fit: cover;
-            position: absolute;
-            top: 0;
-            left: 0;
-            z-index: 2;
-          }
-        }
-        .course-meun-item-intro {
-          .title-container {
-            display: flex;
-            align-items: center;
-            width: 220px;
-            .title {
-              max-width: 180px;
-              font-family: PingFangSC, PingFang SC;
-              font-weight: 500;
-              font-size: 15px;
-              color: #333333;
-              line-height: 21px;
-              text-align: left;
-              font-style: normal;
-              white-space: nowrap;
-              overflow: hidden;
-              text-overflow: ellipsis;
-              margin-right: 6px;
-            }
-            .try-see {
-              width: 39px;
-              height: 18px;
-              background: linear-gradient( 279deg, #FF9055 0%, #FFB856 100%);
-              border-radius: 9px;
-              display: flex;
-              justify-content: center;
-              align-items: center;
-              font-size: 12px;
-              line-height: 18px;
-            }
-          }
-
-          .intro {
-            display: flex;
-            font-family: PingFangSC, PingFang SC;
-            font-weight: 400;
-            font-size: 12px;
-            color: #BEBEBE;
-            line-height: 17px;
-            text-align: left;
-            font-style: normal;
-            margin-top: 10px;
-            .intro-item {
-              margin-right: 16px;
-              display: flex;
-              align-items: center;
-              img {
-                width: 13px;
-                height: 13px;
-                display: block;
-                margin-right: 2px;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  video {
-      width: 100%;
-      height: 210px;
-      display: block;
-      object-fit: cover;
-      position: fixed;
-      top: 0;
-      left: 0;
-      z-index: 1;
-    }
-
-.btn {
-  width: 375px;
-  height: 87px;
-  background: #FFFFFF;
-  box-shadow: 0px -4px 34px 0px rgba(0,0,0,0.06);
-  position: fixed;
-  bottom: -2px;
-  left: 0%;
-  z-index: 100;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  .open-app-btn {
-    width: 343px;
-    height: 46px;
-    background: linear-gradient( 306deg, #FF9A59 0%, #FF4747 100%);
-    border-radius: 23px;
-    font-family: PingFangSC, PingFang SC;
-    font-weight: 500;
-    font-size: 18px;
-    color: #FFFFFF;
-    line-height: 25px;
-    text-align: left;
-    font-style: normal;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-}
-
-</style>
+<template>
+  <div calss="course-detail" >
+    <!-- 课程详情 -->
+    <div class="course" >
+    <div class="cover">
+      <img :src="state.imgCover" alt="">
+    </div>
+    <div class="desc" >
+      <div class="price" >
+        <div class="current-price" >{{state.price}}</div>
+        <div class="discount-price" >原价:¥{{state.markingPrice}}</div>
+      </div>
+      <div class="title" >{{state.name}}</div>
+      <div class="subtitle" >{{state.simpleDescription}}</div>
+      <div class="sub-desc" >
+        <div class="tag" >
+          <div class="tag-item" >{{state.suitAge}}岁</div>
+          <div class="tag-item" >{{state.chapterList.length}}讲</div>
+        </div>
+        <div class="buy" >
+          <img :src="require('@/pages/Course/assets/learn_count.png')" alt="">
+          <div>{{state.courseCount}}人学过</div>
+        </div>
+      </div>
+    </div>
+    </div>
+    <!-- 目录 -->
+    <div class='meun-section' >
+      <div class="tabs" :style="{top: currentVideo ? '210px' : '0px' }">
+        <div
+          :class="['tabs-item', curTabRef === item.id ? 'tabs-item-active' : '']"
+          v-for="item in tabs"
+          :key="item.id"
+          @click="changeTabs(item.id)"
+        >
+          {{item.name}}
+        </div>
+        <div class="line" :style="{left: curTabRef === 0 ? '80px' : '268px'}" ></div>
+      </div>
+      <div class="course-desc"  v-if="curTabRef === 0" >
+        <div v-html="state.description" ></div>
+      </div>
+      <div class="course-meun" v-if="curTabRef === 1"  >
+        <!-- 小分类 -->
+        <div class='course-meun-tabs'  >
+          <div :class="['course-meun-tabs-item', chapterIdRef === item.id ? 'course-meun-tabs-item-active' : '']" @click="changeChapter(index, item.id)" v-for="(item, index) in state.chapterList" :key="item.id">
+            {{item.name}}
+          </div>
+        </div>
+        <div
+          class="course-meun-item"
+          v-for="_ in  currentMediaList"
+          :key="_.id"
+        >
+          <div class='cover' @click="playCourse(_)">
+            <div class="overlay" v-if="_.payType === 0" >
+              <img class="lock" :src="require('@/pages/Course/assets/lock.png')" alt="">
+            </div>
+            <img  :src="_.imgCover" alt="">
+          </div>
+          <div class="course-meun-item-intro"  >
+            <div class="title-container" >
+              <div class="title">{{_.name}}</div>
+              <div class="try-see" v-if="_.payType !== 0" >试看</div>
+            </div>
+            <div class="intro" >
+              <div class="intro-item" v-if="mediaType === 0 && _.video" ><img :src="require('@/pages/Course/assets/time.png')" alt=""><div>{{getDuration(_.video.duration)}}</div></div>
+              <div class="intro-item" ><img :src="require('@/pages/Course/assets/play.png')" alt=""><div>{{_.readCountStr}}</div></div>
+              <div class="intro-item" @click="openTeachingMaterial(_)" ><van-icon name="description" style="margin-right: 5px;margin-top: 2px;" /><div>资料</div></div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <video
+    v-if="currentVideo"
+    :style="{zIndex: currentVideo? 30 : 1}"
+    :src="currentVideo"
+    controls
+    autoplay
+    playsinline
+  >
+  </video>
+
+  <!-- 打开app的按钮 如果没有app,就去应用市场 -->
+  <div class="btn" >
+    <!-- <div class="open-app-btn" >
+      加入学习解锁全部课程
+    </div> -->
+    <!-- <OpenApp appid='wxe87236d542cd0f94'   /> -->
+    <OpenApp appid='wxf6e96c65ba6116d4' text="加入学习解锁全部课程" :extinfo="'/course/pipeline?course_id=' + skuId"  />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { getAICourse } from '@/api/course'
+import { getParentWXSignature } from '@/api/common'
+import { onMounted, ref } from 'vue'
+import OpenApp from '@/components/OpenApp/index.vue'
+import { registerWxopenButton } from '@/utils/utils'
+import { useRoute, useRouter } from 'vue-router'
+
+const userAgent = navigator.userAgent
+
+// 判断是否在微信中
+// var isInWeChat = /MicroMessenger/.test(userAgent)
+
+const route = useRoute()
+
+const router = useRouter()
+
+const skuId = route.query.skuId
+
+const tabs = [
+  {
+    name: '详情',
+    id: 0
+  },
+  {
+    name: '目录',
+    id: 1
+  }
+]
+
+const curTabRef = ref(0)
+
+const state = ref({
+  chapterList: []
+})
+
+const currentVideo = ref('')
+
+const currentMediaList = ref([])
+
+const chapterIdRef = ref('')
+
+const openTeachingMaterial = (record: any) => {
+  if (record.payType == 0) return
+  window.open(record.teachingMaterial.fileUrl)
+}
+
+const changeChapter = (index: number, id: string) => {
+  currentMediaList.value = state.value.chapterList[index].itemList
+  chapterIdRef.value = id
+}
+
+const getDuration = (count: any) => {
+  const m = Math.floor(Number(count).toFixed(0) / 60)
+  const s = Number(count).toFixed(0) % 60
+  return (m > 10 ? m : '0' + m) + ':' + (s > 10 ? s : '0' + s)
+}
+
+// 0  视频  2 图文 1 音频
+const mediaType = ref(0)
+
+const playCourse = (record) => {
+  if (record.payType === 0) return
+  if (mediaType.value === 0) {
+    currentVideo.value = record.video.videoUrl
+  } else if (mediaType.value === 2) {
+    router.push({
+      path: '/media',
+      query: { id: record.id }
+    })
+  }
+}
+
+const changeTabs = (id: number) => {
+  curTabRef.value = id
+}
+
+// 获取课程
+const _getAICourse = async () => {
+  const { data } = await getAICourse({ skuId: skuId as string, hasWork: '' })
+  state.value = data
+  mediaType.value = data.mediaType
+  currentMediaList.value = data.chapterList[0].itemList
+  chapterIdRef.value = data.chapterList[0].id
+}
+
+onMounted(() => {
+  _getAICourse()
+  registerWxopenButton(getParentWXSignature)
+})
+
+</script>
+
+<style lang="scss" scoped >
+.course-detail {
+  width: 100vw;
+  min-height: 100vh;
+  background-color: #F6F6F6;
+}
+.course {
+  .cover {
+    width: 375px;
+    height: 231px;
+    background-color: deepskyblue;
+    position: relative;
+    z-index: 1;
+
+    img {
+      width: 100%;
+      height: 100%;
+      display: block;
+      object-fit: cover;
+      position: absolute;
+      top: 0;
+      left: 0;
+      z-index: 2;
+    }
+  }
+  .desc {
+    width: 375px;
+    height: 185px;
+    background: #FFFFFF;
+    box-shadow: 0px 6px 11px 4px rgba(231,237,241,0.6);
+    border-radius: 22px 22px 0px 0px;
+    margin-top: -22px;
+    padding: 16px;
+    box-sizing: border-box;
+    position: relative;
+    z-index: 2;
+    .price {
+      display: flex;
+      align-items: center;
+      .current-price {
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 600;
+        font-size: 26px;
+        color: #FF1F1F;
+        line-height: 37px;
+        text-align: left;
+        font-style: normal;
+        margin-right: 12px;
+      }
+      .discount-price {
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 400;
+        font-size: 12px;
+        color: #999999;
+        line-height: 17px;
+        text-align: left;
+        font-style: normal;
+        text-decoration-line: line-through;
+      }
+    }
+    .title {
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 600;
+      font-size: 18px;
+      color: #333333;
+      line-height: 25px;
+      text-align: left;
+      font-style: normal;
+      margin-top: 6px;
+    }
+    .subtitle {
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 400;
+      font-size: 13px;
+      color: #797979;
+      line-height: 20px;
+      text-align: justify;
+      font-style: normal;
+      margin-top: 5px;
+    }
+    .sub-desc {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-top: 16px;
+      .tag {
+        display: flex;
+        .tag-item {
+          width: 60px;
+          height: 23px;
+          background: #FFF2E8;
+          margin-right: 14px;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 400;
+          font-size: 11px;
+          color: #FF7422;
+          font-style: normal;
+        }
+      }
+      .buy {
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 400;
+        font-size: 12px;
+        color: #999999;
+        line-height: 23px;
+        text-align: left;
+        font-style: normal;
+        display: flex;
+        align-items: center;
+        img {
+          width: 11px;
+          height: 11px;
+          margin-right: 4px;
+        }
+      }
+    }
+  }
+}
+
+.meun-section {
+  margin-top: 20px;
+  background-color: #F6F6F6;
+
+    .tabs {
+      width: 100vw;
+      height: 58px;
+      display: flex;
+      align-items: center;
+      justify-content: space-around;
+      background-color: #fff;
+      position: sticky;
+      top: 210px;
+      z-index: 4;
+      .tabs-item {
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 500;
+        font-size: 16px;
+        color: #999999;
+        line-height: 22px;
+        text-align: left;
+        font-style: normal;
+      }
+      .tabs-item-active {
+        font-weight: 600;
+        font-size: 17px;
+        color: #333333;
+        line-height: 24px;
+      }
+      .line {
+        width: 30px;
+        height: 6px;
+        background-color: #0B57C7;
+        border-radius: 10px;
+        position: absolute;
+        top: 44px;
+        left: 80px;
+      }
+    }
+    .course-desc {
+      width: 100vw;
+      height: 42vh;
+      padding: 16px;
+      box-sizing: border-box;
+      font-weight: 600;
+      font-size: 16px;
+      color: #636161;
+      line-height: 18px;
+    }
+    .course-meun {
+      width: 100vw;
+      padding: 16px;
+      padding-left: 26px;
+      box-sizing: border-box;
+      padding-bottom: 100px;
+      .course-meun-tabs {
+        margin-bottom: 20px;
+        width: calc(100vw - 32px);
+        overflow: hidden;
+        overflow-x: scroll;
+        display: flex;
+        align-items: center;
+        .course-meun-tabs-item {
+          background: #F6F6F6;
+          border-radius: 18px;
+          padding: 8px 20px;
+          box-sizing: border-box;
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 500;
+          font-size: 15px;
+          color: #9B9B9B;
+          line-height: 21px;
+          height: 36px;
+          margin-right: 20px;
+          background-color: #fff;
+        }
+        .course-meun-tabs-item-active {
+          border: 1px solid #0B57C7;
+          color: #0B57C7
+        }
+      }
+      .course-meun-item {
+        display: flex;
+        align-items: center;
+        margin-bottom: 20px;
+        .cover {
+          width: 107px;
+          height: 60px;
+          margin-right: 14px;
+          position: relative;
+          .overlay {
+            width: 107px;
+            height: 60px;
+            background-color: rgba( 0, 0, 0, 0.6);
+            position: absolute;
+            top: 0;
+            left: 0;
+            z-index: 3;
+            display: flex;
+            justify-content: center;
+            align-items: start;
+            border-radius: 20px;
+            .lock {
+              width: 17px;
+              height: 16px;
+              display: block;
+              position: absolute;
+              top: 50%;
+              left: 50%;
+              transform: translate(-50%, -50%);
+            }
+          }
+          img {
+            width: 107px;
+            height: 60px;
+            border-radius: 20px;
+            display: block;
+            object-fit: cover;
+            position: absolute;
+            top: 0;
+            left: 0;
+            z-index: 2;
+          }
+        }
+        .course-meun-item-intro {
+          .title-container {
+            display: flex;
+            align-items: center;
+            width: 220px;
+            .title {
+              max-width: 180px;
+              font-family: PingFangSC, PingFang SC;
+              font-weight: 500;
+              font-size: 15px;
+              color: #333333;
+              line-height: 21px;
+              text-align: left;
+              font-style: normal;
+              white-space: nowrap;
+              overflow: hidden;
+              text-overflow: ellipsis;
+              margin-right: 6px;
+            }
+            .try-see {
+              width: 39px;
+              height: 18px;
+              background: linear-gradient( 279deg, #FF9055 0%, #FFB856 100%);
+              border-radius: 9px;
+              display: flex;
+              justify-content: center;
+              align-items: center;
+              font-size: 12px;
+              line-height: 18px;
+            }
+          }
+
+          .intro {
+            display: flex;
+            font-family: PingFangSC, PingFang SC;
+            font-weight: 400;
+            font-size: 12px;
+            color: #BEBEBE;
+            line-height: 17px;
+            text-align: left;
+            font-style: normal;
+            margin-top: 10px;
+            .intro-item {
+              margin-right: 16px;
+              display: flex;
+              align-items: center;
+              img {
+                width: 13px;
+                height: 13px;
+                display: block;
+                margin-right: 2px;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  video {
+      width: 100%;
+      height: 210px;
+      display: block;
+      object-fit: cover;
+      position: fixed;
+      top: 0;
+      left: 0;
+      z-index: 1;
+    }
+
+.btn {
+  width: 375px;
+  height: 87px;
+  background: #FFFFFF;
+  box-shadow: 0px -4px 34px 0px rgba(0,0,0,0.06);
+  position: fixed;
+  bottom: -2px;
+  left: 0%;
+  z-index: 100;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .open-app-btn {
+    width: 343px;
+    height: 46px;
+    background: linear-gradient( 306deg, #FF9A59 0%, #FF4747 100%);
+    border-radius: 23px;
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 500;
+    font-size: 18px;
+    color: #FFFFFF;
+    line-height: 25px;
+    text-align: left;
+    font-style: normal;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+}
+
+</style>

+ 6 - 0
src/pages/DownloadAppParent/App.vue

@@ -0,0 +1,6 @@
+<script setup lang="ts">
+</script>
+
+<template>
+  <router-view/>
+</template>

BIN
src/pages/DownloadAppParent/assets/guidance.png


BIN
src/pages/DownloadAppParent/assets/logo.png


+ 1 - 0
src/pages/DownloadAppParent/assets/redirect.html

@@ -0,0 +1 @@
+No Content: https://itunes.apple.com/cn/app/id741292507

+ 14 - 0
src/pages/DownloadAppParent/main.ts

@@ -0,0 +1,14 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+import 'lib-flexible'
+import 'normalize.css'
+import * as Pinia from 'pinia'
+// import VConsole from 'vconsole'
+import '@/utils/vant'
+
+// const vconsole = new VConsole()
+
+// import store from './store'
+
+createApp(App).use(router).use(Pinia.createPinia()).mount('#DownloadAppParent')

+ 17 - 0
src/pages/DownloadAppParent/public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title>逻辑狗</title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="DownloadAppParent"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 16 - 0
src/pages/DownloadAppParent/router/index.ts

@@ -0,0 +1,16 @@
+import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
+
+const routes: Array<RouteRecordRaw> = [
+  {
+    path: '/',
+    name: 'page',
+    component: () => import('../views/index.vue')
+  }
+]
+
+const router = createRouter({
+  history: createWebHashHistory(),
+  routes
+})
+
+export default router

+ 115 - 0
src/pages/DownloadAppParent/views/index.vue

@@ -0,0 +1,115 @@
+<template>
+  <div class="download-app" >
+    <div class="app" >
+      <img class="logo" :src="require('@/pages/DownloadAppParent/assets/logo.png')" alt="">
+      <div class="logo-desc" >
+        逻辑狗·与千万逻辑狗宝贝一起成长
+      </div>
+      <div class="download-btn" @click="downloadApp" >
+        立即下载逻辑狗·家园共育
+      </div>
+    </div>
+
+    <div class="guidance-overlay" v-if="isInWeChat" >
+      <img class="guidance" :src="require('@/pages/DownloadApp/assets/guidance.png')" alt="">
+      <div class="desc" >
+        请使用其他浏览器打开
+      </div>
+    </div>
+
+  </div>
+
+</template>
+
+<script setup lang="ts">
+import { onMounted } from 'vue'
+
+const userAgent = navigator.userAgent
+
+const isAndroid = /Android/.test(userAgent)
+
+const isIOS = /(iPhone|iPad|iPod)/.test(userAgent)
+
+// 判断是否在微信中
+var isInWeChat = /MicroMessenger/.test(userAgent)
+
+onMounted(() => {
+  console.log('isIOS:', isIOS)
+  console.log('isAndroid:', isAndroid)
+  console.log('userAgent:', userAgent)
+  downloadApp()
+})
+
+const downloadApp = () => {
+  if (isIOS) {
+    window.location.href = 'https://apps.apple.com/cn/app/%E9%80%BB%E8%BE%91%E7%8B%97-%E5%AE%B6%E5%9B%AD%E5%85%B1%E8%82%B2/id1495775053'
+  } else {
+    window.location.href = 'market://details?id=com.zaojiao.app.parent'
+  }
+}
+</script>
+
+<style>
+.download-app {
+  width: 100vw;
+  height: 100vh;
+}
+
+.app {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  display: flex;
+  flex-direction: column;
+  flex-wrap: wrap;
+  align-items: center;
+  width: 100vw;
+}
+
+.logo {
+  width: 86px;
+  height: 86px;
+  border-radius: 10px;
+  z-index: 1;
+  margin: 0 auto;
+}
+
+.logo-desc {
+  margin-top: 20px;
+  font-size: 16px;
+}
+
+.download-btn {
+  border: 1px solid #2f9f3e;
+  padding: 10px 30px;
+  margin-top: 20px;
+  border-radius: 20px;
+  color: #2f9f3e;
+  letter-spacing: 2px;
+}
+
+.guidance-overlay {
+  width: 100vw;
+  height: 100vh;
+  background-color: rgba(0, 0, 0, 0.7);
+  position: fixed;
+  z-index: 2;
+}
+
+.guidance {
+  width: 135px;
+  position: fixed;
+  top: 20px;
+  right: 20px;
+}
+
+.desc {
+  font-size: 20px;
+  color: #fff;
+  position: fixed;
+  top: 170px;
+  right: 20px;
+}
+
+</style>

+ 14 - 14
src/pages/LearnPlan/main.ts

@@ -1,14 +1,14 @@
-import { createApp } from 'vue'
-import App from './App.vue'
-import router from './router'
-import 'lib-flexible'
-import 'normalize.css'
-import * as Pinia from 'pinia'
-// import VConsole from 'vconsole'
-import '@/utils/vant'
-
-// import store from './store'
-
-// new VConsole()
-
-createApp(App).use(router).use(Pinia.createPinia()).mount('#LearnPlan')
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+import 'lib-flexible'
+import 'normalize.css'
+import * as Pinia from 'pinia'
+// import VConsole from 'vconsole'
+import '@/utils/vant'
+
+// import store from './store'
+
+// new VConsole()
+
+createApp(App).use(router).use(Pinia.createPinia()).mount('#LearnPlan')

+ 111 - 0
src/pages/Pay/App.vue

@@ -0,0 +1,111 @@
+
+<template>
+  <div></div>
+</template>
+
+<script setup lang="ts">
+import wx from 'weixin-js-sdk'
+import { showToast, showLoadingToast, closeToast } from 'vant'
+import { onMounted } from 'vue'
+
+function getUrlParameter (paramName: string) {
+  const url = window.location.href
+  // 提取 URL 中 hash 之后的部分
+  const hashIndex = url.indexOf('#')
+  const queryString = url.slice(hashIndex + 1)
+
+  // 匹配参数名及其值的正则表达式
+  const pattern = new RegExp('[?&]' + paramName + '=([^&]+)', 'i')
+  const match = queryString.match(pattern)
+
+  // 如果找到匹配的结果,则返回参数值,否则返回 null
+  return match ? decodeURIComponent(match[1]) : null
+}
+
+// q 是支付所需要的的参数
+const q = JSON.parse(decodeURIComponent(getUrlParameter('q') as string))
+const redirect = getUrlParameter('redirect')
+
+console.log(q, redirect)
+
+const wxPay = (record: any) => {
+  function onBridgeReady (record: any) {
+    console.log(window.WeixinJSBridge)
+    console.log('调用微信支付WeixinJSBridge:', JSON.stringify(record))
+    return new Promise((resolve, reject) => {
+      // eslint-disable-next-line no-undef
+      console.log('WeixinJSBridge:', window.WeixinJSBridge)
+      // eslint-disable-next-line no-undef
+      window.WeixinJSBridge.invoke(
+        'getBrandWCPayRequest',
+        {
+          appId: record.appId, // 公众号名称,由商户传入
+          timeStamp: record.timeStamp, // 时间戳
+          nonceStr: record.nonceStr, // 随机串
+          package: record.package, // 预支付id
+          signType: record.signType, // 微信签名方式
+          paySign: record.paySign // 微信签名
+        },
+        (res) => {
+          console.log('支付结果:', res.err_msg)
+          if (res.err_msg === 'get_brand_wcpay_request:ok') {
+          // 使用以上方式判断前端返回,微信团队郑重提示:
+          // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
+            console.log('支付成功')
+            setTimeout(() => {
+              if (redirect) window.location.href = redirect
+              else window.history.back()
+            }, 100)
+            showToast('支付成功')
+            resolve(true)
+          } else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
+            console.log('支付取消')
+            setTimeout(() => {
+              window.history.back()
+            }, 100)
+            showToast('支付取消')
+            resolve(false)
+          } else if (res.err_msg === 'get_brand_wcpay_request:fail') {
+            console.log('支付失败')
+            showToast('支付失败')
+            setTimeout(() => {
+              window.history.back()
+            }, 100)
+            resolve(false)
+          } else {
+            resolve(false)
+          }
+        }
+      )
+    })
+  }
+
+  if (typeof window.WeixinJSBridge === 'undefined') {
+    // 微信浏览器内置对象。参考微信官方文档
+    console.log('WeixinJSBridge 不存在')
+    const _document: any = document
+    if (_document.addEventListener) {
+      _document.addEventListener('WeixinJSBridgeReady', onBridgeReady(record), false)
+    } else if (_document.attachEvent) {
+      _document.attachEvent('WeixinJSBridgeReady', onBridgeReady(record))
+      _document.attachEvent('onWeixinJSBridgeReady', onBridgeReady(record))
+    }
+  } else {
+    onBridgeReady(record)
+  }
+}
+
+onMounted(() => {
+  showLoadingToast({
+    duration: 0,
+    forbidClick: true,
+    message: '调取微信支付中....'
+  })
+
+  setTimeout(() => {
+    wxPay(q)
+    closeToast()
+  }, 1000)
+})
+
+</script>

+ 13 - 0
src/pages/Pay/main.ts

@@ -0,0 +1,13 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import 'lib-flexible'
+import 'normalize.css'
+import * as Pinia from 'pinia'
+import VConsole from 'vconsole'
+import '@/utils/vant'
+
+// const vconsole = new VConsole()
+
+// import store from './store'
+
+createApp(App).mount('#pay')

+ 17 - 0
src/pages/Pay/public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title>学习计划</title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="pay"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 102 - 102
upload.py

@@ -1,102 +1,102 @@
-import paramiko
-import os
-import sys
-import time
-import zipfile
-
-hostname=""
-username=""
-password=""
-port=222
-
-if sys.argv[3] == 'pro':
- hostname="000.luojigou.vip"
- username="admin"
- password='FUpnUQ8aLpngnEW'
-else:
- hostname="local.luojigou.vip"
- username="root" 
- password='RDefC4Rh&I0VN1j1'
- port=22
-
-
-############################## 
-############################## 
-############################## 
-
-transport = paramiko.Transport((hostname, port))
-
-transport.connect(username=username, password=password)
-
-############################## 
-############################## 
-############################## 
-
-sftp = paramiko.SFTPClient.from_transport(transport)
-
-# transport.close(),
-############################## 
-############################## 
-############################## 
-
-# 创建SSH对象
-ssh = paramiko.SSHClient()
-
-# 允许连接不在know_hosts文件中的主机
-ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-# 连接服务器
-ssh.connect(hostname=hostname, port=port, username=username, password=password,allow_agent=False,look_for_keys=False)
-
-############################## 
-##############################
-############################## 
-
-local_path = os.getcwd() + "\dist.zip"
-
-target_file_name = sys.argv[2]
-
-remote_path = sys.argv[1]
-
-remote_file_name = remote_path + target_file_name
-
-print("本地文件地址: " + local_path )
-print("远程目录地址: " + remote_file_name)
-
-srmdir_all_folder = os.getcwd() + '/dist'  # 文件夹路径
-
-zip_file_path = srmdir_all_folder + ".zip"  # 压缩文件路径
-
-print("打包中.....🍗")
-def make_zip(source_dir, output_filename):
-    zipf = zipfile.ZipFile(output_filename, 'w')
-    pre_len = len(os.path.dirname(source_dir))
-    for parent, _, filenames in os.walk(source_dir):
-        for filename in filenames:
-            pathfile = os.path.join(parent, filename)
-            arcname = pathfile[pre_len:].strip(os.path.sep)     #相对路径
-            zipf.write(pathfile,  arcname.replace('/dist', ''), zipfile.ZIP_DEFLATED)
-    zipf.close()
-
-make_zip(srmdir_all_folder, zip_file_path)
-
-time.sleep(1)
-print("打包完成.....😎")
-
-print("上传中.....💪")
-sftp.put(local_path,  remote_file_name + "/dist.zip")
-
-time.sleep(1)
-
-cmd1 = "unzip -o -d " + remote_file_name + " " + remote_file_name + "/dist.zip"
-
-stdin, stdout, stderr= ssh.exec_command(cmd1)
-
-result = stdout.read()
-
-print("上传成功🎉🎉🎉🎉")
-
-transport.close()
-
-ssh.close()
-
-
+import paramiko
+import os
+import sys
+import time
+import zipfile
+
+hostname=""
+username=""
+password=""
+port=222
+
+if sys.argv[3] == 'pro':
+ hostname="000.luojigou.vip"
+ username="admin"
+ password='FUpnUQ8aLpngnEW'
+else:
+ hostname="local.luojigou.vip"
+ username="root" 
+ password='RDefC4Rh&I0VN1j1'
+ port=22
+
+
+############################## 
+############################## 
+############################## 
+
+transport = paramiko.Transport((hostname, port))
+
+transport.connect(username=username, password=password)
+
+############################## 
+############################## 
+############################## 
+
+sftp = paramiko.SFTPClient.from_transport(transport)
+
+# transport.close(),
+############################## 
+############################## 
+############################## 
+
+# 创建SSH对象
+ssh = paramiko.SSHClient()
+
+# 允许连接不在know_hosts文件中的主机
+ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+# 连接服务器
+ssh.connect(hostname=hostname, port=port, username=username, password=password,allow_agent=False,look_for_keys=False)
+
+############################## 
+##############################
+############################## 
+
+local_path = os.getcwd() + "\dist.zip"
+
+target_file_name = sys.argv[2]
+
+remote_path = sys.argv[1]
+
+remote_file_name = remote_path + target_file_name
+
+print("本地文件地址: " + local_path )
+print("远程目录地址: " + remote_file_name)
+
+srmdir_all_folder = os.getcwd() + '/dist'  # 文件夹路径
+
+zip_file_path = srmdir_all_folder + ".zip"  # 压缩文件路径
+
+print("打包中.....🍗")
+def make_zip(source_dir, output_filename):
+    zipf = zipfile.ZipFile(output_filename, 'w')
+    pre_len = len(os.path.dirname(source_dir))
+    for parent, _, filenames in os.walk(source_dir):
+        for filename in filenames:
+            pathfile = os.path.join(parent, filename)
+            arcname = pathfile[pre_len:].strip(os.path.sep)     #相对路径
+            zipf.write(pathfile,  arcname.replace('/dist', ''), zipfile.ZIP_DEFLATED)
+    zipf.close()
+
+make_zip(srmdir_all_folder, zip_file_path)
+
+time.sleep(1)
+print("打包完成.....😎")
+
+print("上传中.....💪")
+sftp.put(local_path,  remote_file_name + "/dist.zip")
+
+time.sleep(1)
+
+cmd1 = "unzip -o -d " + remote_file_name + " " + remote_file_name + "/dist.zip"
+
+stdin, stdout, stderr= ssh.exec_command(cmd1)
+
+result = stdout.read()
+
+print("上传成功🎉🎉🎉🎉")
+
+transport.close()
+
+ssh.close()
+
+

+ 92 - 82
vue.config.js

@@ -1,82 +1,92 @@
-const { resolve } = require('path')
-const { VantResolver } = require('unplugin-vue-components/resolvers')
-const ComponentsPlugin = require('unplugin-vue-components/webpack')
-
-module.exports = {
-  publicPath: '/app_web', // 打包后资源访问路径
-  lintOnSave: false, // eslint是否在保存的时候检查
-  pages: {
-    index: {
-      entry: 'src/main.ts', // page 的入口
-      template: 'public/index.html', // 模板来源
-      filename: 'index.html' //  在 dist/index.html 的输出
-    },
-    demo: {
-      entry: 'src/pages/demo/main.ts',
-      template: 'src/pages/demo/public/index.html',
-      filename: 'demo.html'
-    },
-    LearnPlan: {
-      entry: 'src/pages/LearnPlan/main.ts',
-      template: 'src/pages/LearnPlan/public/index.html',
-      filename: 'learn-plan.html'
-    },
-    SectionAudition: {
-      entry: 'src/pages/SectionAudition/main.ts',
-      template: 'src/pages/SectionAudition/public/index.html',
-      filename: 'section-audition.html'
-    },
-    DownloadApp: {
-      entry: 'src/pages/DownloadApp/main.ts',
-      template: 'src/pages/DownloadApp/public/index.html',
-      filename: 'download-app.html'
-    },
-    Course: {
-      entry: 'src/pages/Course/main.ts',
-      template: 'src/pages/Course/public/index.html',
-      filename: 'course.html'
-    },
-    LP: {
-      entry: 'src/pages/LearnPlanActive/main.ts',
-      template: 'src/pages/LearnPlanActive/public/index.html',
-      filename: 'lp.html'
-    }
-  },
-  chainWebpack: config => {
-    config.resolve.alias
-      .set('@', resolve('src'))
-      .set('@hook', resolve('src/hook'))
-      .set('@demo', resolve('src/pages/demo/src'))
-      .set('@LP', resolve('src/pages/LearnPlan'))
-  },
-  configureWebpack: {
-    plugins: [
-      ComponentsPlugin({
-        resolvers: [VantResolver()]
-      })
-    ]
-  },
-  devServer: {
-    proxy: {
-      '/api/': {
-        target: 'http://local.luojigou.vip:8888/',
-        ws: false,
-        secure: false,
-        changeOrigin: true,
-        pathRewrite: {
-          '^/api/': ''
-        }
-      },
-      '/zd-api/': {
-        // target: 'https://open.test.luojigou.vip/', // 开发环境
-        target: 'https://open.api.luojigou.vip/', // 生产环境
-        ws: false,
-        secure: false,
-        changeOrigin: true,
-        pathRewrite: {
-          '^/zd-api/': ''
-        }
-      }
-    }
-  }
-}
+const { resolve } = require('path')
+const { VantResolver } = require('unplugin-vue-components/resolvers')
+const ComponentsPlugin = require('unplugin-vue-components/webpack')
+
+module.exports = {
+  publicPath: '/app_web', // 打包后资源访问路径
+  lintOnSave: false, // eslint是否在保存的时候检查
+  pages: {
+    index: {
+      entry: 'src/main.ts', // page 的入口
+      template: 'public/index.html', // 模板来源
+      filename: 'index.html' //  在 dist/index.html 的输出
+    },
+    demo: {
+      entry: 'src/pages/demo/main.ts',
+      template: 'src/pages/demo/public/index.html',
+      filename: 'demo.html'
+    },
+    LearnPlan: {
+      entry: 'src/pages/LearnPlan/main.ts',
+      template: 'src/pages/LearnPlan/public/index.html',
+      filename: 'learn-plan.html'
+    },
+    SectionAudition: {
+      entry: 'src/pages/SectionAudition/main.ts',
+      template: 'src/pages/SectionAudition/public/index.html',
+      filename: 'section-audition.html'
+    },
+    DownloadApp: {
+      entry: 'src/pages/DownloadApp/main.ts',
+      template: 'src/pages/DownloadApp/public/index.html',
+      filename: 'download-app.html'
+    },
+    DownloadAppParent: {
+      entry: 'src/pages/DownloadAppParent/main.ts',
+      template: 'src/pages/DownloadAppParent/public/index.html',
+      filename: 'download-app-parent.html'
+    },
+    Course: {
+      entry: 'src/pages/Course/main.ts',
+      template: 'src/pages/Course/public/index.html',
+      filename: 'course.html'
+    },
+    LP: {
+      entry: 'src/pages/LearnPlanActive/main.ts',
+      template: 'src/pages/LearnPlanActive/public/index.html',
+      filename: 'lp.html'
+    },
+    pay: {
+      entry: 'src/pages/Pay/main.ts',
+      template: 'src/pages/Pay/public/index.html',
+      filename: 'pay.html'
+    }
+  },
+  chainWebpack: config => {
+    config.resolve.alias
+      .set('@', resolve('src'))
+      .set('@hook', resolve('src/hook'))
+      .set('@demo', resolve('src/pages/demo/src'))
+      .set('@LP', resolve('src/pages/LearnPlan'))
+  },
+  configureWebpack: {
+    plugins: [
+      ComponentsPlugin({
+        resolvers: [VantResolver()]
+      })
+    ]
+  },
+  devServer: {
+    proxy: {
+      '/api/': {
+        target: 'http://local.luojigou.vip:8888/',
+        ws: false,
+        secure: false,
+        changeOrigin: true,
+        pathRewrite: {
+          '^/api/': ''
+        }
+      },
+      '/zd-api/': {
+        // target: 'https://open.test.luojigou.vip/', // 开发环境
+        target: 'https://open.api.luojigou.vip/', // 生产环境
+        ws: false,
+        secure: false,
+        changeOrigin: true,
+        pathRewrite: {
+          '^/zd-api/': ''
+        }
+      }
+    }
+  }
+}