shmily1213 преди 17 часа
родител
ревизия
2c2656a8e2

+ 25 - 0
src/common/routes.ts

@@ -88,6 +88,31 @@ export const routes = {
    * 隐私政策
    */
   pagePrivacyPolicy: '/pagesSystem/pages/privacy-policy/privacy-policy',
+  /**
+   * 我的收藏
+   */
+  pageCollect: '/pagesOther/pages/collect/collect',
+  /**
+   * 课程学习
+   */
+  pageCourseStudy: '/pagesOther/pages/video-center/index/index',
+  /**
+   * 组卷作业
+   */
+  pageHomework: '/pagesStudy/pages/homework/homework',
+  /**
+   * 错题本
+   */
+  pageWrongBook: '/pagesOther/pages/topic-center/wrong-book/wrong-book',
+  /**
+   * 学习记录
+   */
+  pageStudyHistory: '/pagesStudy/pages/study-history/study-history',
+  /**
+   * 会员卡校验
+   */
+  pageCardVerify: '/pagesSystem/pages/card-verify/card-verify',
+
 } as const;
 
 export type Routes = keyof typeof routes;

+ 7 - 1
src/components/ie-dropdown/ie-dropdown-item.vue

@@ -53,6 +53,8 @@ const instance = getCurrentInstance();
 const props = defineProps<{
   config: Dropdown.DropdownItem;
   index: number;
+  // 是否使用绝对定位
+  absolute?: boolean;
 }>();
 const dropdown = inject(DROPDOWN_SYMBOL);
 const triggerSelector = `#dropdown-trigger-${props.config.prop}`;
@@ -109,7 +111,11 @@ const open = async () => {
   checkboxValue.value = dropdown?.form.value[props.config.prop] || [];
   isOpen.value = true;
   const triggerRect = await getRect(triggerSelector);
-  top.value = triggerRect.top + triggerRect.height;
+  if (props.absolute) {
+    top.value = triggerRect.height;
+  } else {
+    top.value = triggerRect.top + triggerRect.height;
+  }
   setTimeout(() => {
     nextTick(() => {
       show.value = true;

+ 3 - 1
src/components/ie-dropdown/ie-dropdown.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="flex items-center gap-20 px-20 h-[44px] border-0 border-b border-solid border-border-light">
     <view v-for="(item, index) in configs" :key="item.prop" class="flex-1 min-w-1 h-full">
-      <ie-dropdown-item :config="item" :index="index" />
+      <ie-dropdown-item :config="item" :index="index" :absolute="absolute" />
     </view>
   </view>
 </template>
@@ -16,6 +16,8 @@ const emit = defineEmits<{
 const modelValue = defineModel<Record<string, any>>();
 const props = defineProps<{
   configs: Dropdown.DropdownItem[];
+  // 是否使用绝对定位
+  absolute?: boolean;
 }>();
 const dropdown = useDropdown(props.configs);
 

+ 18 - 6
src/components/ie-tabs-swiper/ie-tabs-swiper.vue

@@ -5,7 +5,15 @@
         :key-name="keyName"></uv-tabs>
     </view>
     <ie-auto-resizer>
-      <slot></slot>
+      <swiper class="swiper h-full" :current="modelValue" @change="handleChangeSwiper">
+        <swiper-item v-for="(item, index) in list" :key="index" class="h-full">
+          <view class="h-full" v-if="Math.abs(index - modelValue) <= cacheCount">
+            <scroll-view class=" h-full" scroll-y>
+              <slot :name="item.slot"></slot>
+            </scroll-view>
+          </view>
+        </swiper-item>
+      </swiper>
     </ie-auto-resizer>
   </view>
 </template>
@@ -20,17 +28,21 @@ defineOptions({
 });
 type Props = {
   list: SwiperTabItem[];
-  scrollable: boolean;
-  keyName: string;
-  bgColor: string;
-  border: boolean;
+  scrollable?: boolean;
+  keyName?: string;
+  bgColor?: string;
+  border?: boolean;
+  cacheCount?: number;
+  height?: string;
 }
 const props = withDefaults(defineProps<Props>(), {
   list: () => [],
   modelValue: 0,
   keyName: 'name',
   bgColor: '#FFFFFF',
-  border: true
+  border: true,
+  cacheCount: 2,
+  height: '100%'
 });
 const modelValue = defineModel<number>('modelValue', {
   type: Number,

+ 6 - 0
src/pages.json

@@ -140,6 +140,12 @@
           "style": {
             "navigationBarTitleText": ""
           }
+        },
+        {
+          "path": "pages/collect/collect",
+          "style": {
+            "navigationBarTitleText": ""
+          }
         }
       ]
     },

+ 5 - 19
src/pagesMain/pages/me/components/me-menu.vue

@@ -50,8 +50,8 @@
 <script lang="ts" setup>
 import { useTransferPage } from '@/hooks/useTransferPage';
 import { useUserStore } from '@/store/userStore';
-import {routes} from "@/common/routes";
-const { transferTo } = useTransferPage();
+
+const { transferTo, routes } = useTransferPage();
 const userStore = useUserStore();
 
 const contactPhone = computed(() => userStore.orgInfo.contactPhone);
@@ -71,7 +71,7 @@ const menus = [
   {
     name: '我的收藏',
     icon: '/static/personal/my_collected.png',
-    pagePath: '/pagesOther/pages/personal-center/my-concerned/my-concerned',
+    pagePath: routes.pageCollect,
   },
   {
     name: '我的志愿表',
@@ -81,8 +81,7 @@ const menus = [
   {
     name: '绑定会员卡',
     icon: '/static/personal/bind_card.png',
-    // pagePath: '/pagesOther/pages/personal-center/bind-card/bind-card',
-    pagePath: '/pagesSystem/pages/card-verify/card-verify',
+    pagePath: routes.pageCardVerify,
   }
 ];
 const cellStyle = {
@@ -123,20 +122,7 @@ const handleLogout = async () => {
   }
 }
 const handlePhone = async () => {
-  if (!contactPhone.value) {
-    uni.$ie.showToast('暂无客服电话');
-    return;
-  } else {
-    uni.showActionSheet({
-      title: '客服电话',
-      itemList: [`拨打电话:${contactPhone.value}`],
-      success: (res) => {
-        uni.makePhoneCall({
-          phoneNumber: contactPhone.value
-        });
-      }
-    });
-  }
+  userStore.callContactPhone();
 }
 </script>
 <style lang="scss" scoped></style>

+ 2 - 2
src/pagesOther/pages/career/detail/components/related-jobs.vue

@@ -1,5 +1,5 @@
 <template>
-  <scroll-view class=" h-full overflow-auto" scroll-y>
+  <view>
     <view class="py-20">
       <uv-tabs :list="list" :current="current" :itemStyle="itemStyle" :customStyle="customStyle" lineColor="transparent"
         @change="handleChange">
@@ -60,7 +60,7 @@
       <view class="text-24 text-fore-light">{{ detail?.vocationalSource }}</view>
     </view>
     <ie-safe-area-bottom bg-color="#FFFFFF" />
-  </scroll-view>
+  </view>
 </template>
 <script lang="ts" setup>
 import SalaryChart from './salary-chart.vue';

+ 6 - 8
src/pagesOther/pages/career/detail/detail.vue

@@ -3,14 +3,12 @@
     <ie-navbar :title="pageTitle" />
     <ie-auto-resizer>
       <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
-        <swiper class="swiper h-full" :current="current" @change="handleChangeSwiper">
-          <swiper-item v-for="(item, index) in tabs" :key="index" class="h-full">
-            <view class="h-full" v-if="Math.abs(index - current) <= 2">
-              <career-overview v-if="item.slot === 'career-overview' && code" :code="code" @change-job="handleChangeJob" />
-              <related-jobs v-if="item.slot === 'related-jobs' && code" :code="code" :name="jobName" />
-            </view>
-          </swiper-item>
-        </swiper>
+        <template #career-overview>
+          <career-overview v-if="code" :code="code" @change-job="handleChangeJob" />
+        </template>
+        <template #related-jobs>
+          <related-jobs v-if="code" :code="code" :name="jobName" />
+        </template>
       </ie-tabs-swiper>
     </ie-auto-resizer>
   </ie-page>

+ 33 - 0
src/pagesOther/pages/collect/collect.vue

@@ -0,0 +1,33 @@
+<template>
+  <ie-page :fix-height="true" :safe-area-inset-bottom="false">
+    <ie-navbar title="我的收藏" />
+    <ie-auto-resizer>
+      <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
+        <template #university>
+          123
+        </template>
+        <template #major>
+          234
+        </template>
+      </ie-tabs-swiper>
+    </ie-auto-resizer>
+  </ie-page>
+</template>
+
+<script lang="ts" setup>
+import type { SwiperTabItem } from '@/types';
+
+const current = ref(0);
+const tabs = ref<SwiperTabItem[]>([
+  {
+    name: '关注的院校',
+    slot: 'university'
+  },
+  {
+    name: '关注的专业',
+    slot: 'major'
+  }
+]);
+</script>
+
+<style lang="scss"></style>

+ 6 - 8
src/pagesOther/pages/major/detail/detail.vue

@@ -3,14 +3,12 @@
     <ie-navbar title="专业详情" />
     <ie-auto-resizer>
       <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
-        <swiper class="swiper h-full" :current="current" @change="handleChangeSwiper">
-          <swiper-item v-for="(item, index) in tabs" :key="index" class="h-full">
-            <view class="h-full" v-if="Math.abs(index - current) <= 2">
-              <major-overview v-if="item.slot === 'major-overview' && overviewData" :data="overviewData" />
-              <related-university v-if="item.slot === 'open-college' && overviewData" :data="overviewData" />
-            </view>
-          </swiper-item>
-        </swiper>
+        <template #major-overview>
+          <major-overview v-if="overviewData" :data="overviewData" />
+        </template>
+        <template #open-college>
+          <related-university v-if="overviewData" :data="overviewData" />
+        </template>
       </ie-tabs-swiper>
     </ie-auto-resizer>
   </ie-page>

+ 14 - 9
src/pagesOther/pages/news/index/index.vue

@@ -3,13 +3,18 @@
     <ie-navbar title="资讯" />
     <ie-auto-resizer>
       <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="true">
-        <swiper class="swiper h-full" :current="current" @change="handleChangeSwiper">
-          <swiper-item v-for="(item, index) in tabs" :key="index" class="h-full">
-            <view class="h-full" v-if="Math.abs(index - current) <= 2">
-              <news-paging-list :params="item.params" />
-            </view>
-          </swiper-item>
-        </swiper>
+        <!-- #ifdef WEB -->
+        <template v-for="item in tabs" #[item.slot]>
+          <news-paging-list :params="item.params" />
+        </template>
+        <!-- #endif -->
+        <!-- #ifdef MP-WEIXIN -->
+        <block v-for="item in tabs">
+          <template #[item.slot]>
+            <news-paging-list :params="item.params" />
+          </template>
+        </block>
+        <!-- #endif -->
       </ie-tabs-swiper>
     </ie-auto-resizer>
   </ie-page>
@@ -33,13 +38,13 @@ const handleChangeSwiper = (e: any) => {
 }
 const loadData = () => {
   getNewsTypes().then(res => {
-    const list = res.rows.map(item => ({ name: item.label, value: item.value, slot: item.label, params: {type: item.value} }));
+    const list = res.rows.map(item => ({ name: item.label, value: item.value, slot: item.label, params: { type: item.value } }));
     tabs.value = [
       {
         name: '热门资讯',
         value: 'hot',
         slot: 'hot',
-        params: {tag: 'hot'}
+        params: { tag: 'hot' }
       },
       ...list
     ]

+ 75 - 66
src/pagesOther/pages/university/detail/detail.vue

@@ -1,49 +1,58 @@
 <template>
-    <ie-page>
-        <ie-navbar :title="prevData.name" transparent bg-color="#FFFFFF" title-color="black" keep-title-color/>
-        <ie-image :src="baseInfo.bannerUrl||baseInfo.logo" custom-class="w-full h-360"/>
-        <view class="-mt-60 z-1 rounded-t-3xl p-30 bg-white">
-            <college-info :info="baseInfo" :loading="loading"/>
-        </view>
-        <uv-gap height="10" bg-color="#F6F8FA"/>
-        <uv-sticky :offset-top="appStore.isH5?0:baseStickyTop">
-            <view :style="{height: tabHeight + 'px'}">
-                <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
-                    <swiper class="swiper h-full" :current="current" @change="handleChangeSwiper">
-                        <swiper-item v-for="(item, index) in tabs" :key="index" class="h-full">
-                            <scroll-view scroll-y :style="{height: (tabHeight-44) + 'px'}">
-                                <college-profile v-if="item.slot==='profile'&&item.visited" :loading="loading"/>
-                                <college-brochure v-if="item.slot==='brochure'&&item.visited"/>
-                                <college-exam v-if="item.slot==='exam'&&item.visited"/>
-                            </scroll-view>
-                            <plan-enroll-list v-if="item.slot==='plan'&&item.visited" mode="plan" :list="planList"/>
-                            <plan-enroll-list v-if="item.slot==='enroll'&&item.visited" mode="enroll" :list="enrollList"/>
-                        </swiper-item>
-                    </swiper>
-                </ie-tabs-swiper>
-            </view>
-        </uv-sticky>
-    </ie-page>
+  <ie-page>
+    <ie-navbar :title="prevData.name" transparent bg-color="#FFFFFF" title-color="black" keep-title-color />
+    <ie-image :src="baseInfo.bannerUrl || baseInfo.logo" custom-class="w-full h-360" />
+    <view class="-mt-60 z-1 rounded-t-3xl p-30 bg-white">
+      <college-info :info="baseInfo" :loading="loading" />
+    </view>
+    <uv-gap height="10" bg-color="#F6F8FA" />
+    <uv-sticky :offset-top="appStore.isH5 ? 0 : baseStickyTop">
+      <view :style="{ height: tabHeight + 'px' }">
+        <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
+          <!-- #ifdef WEB -->
+          <template v-for="item in tabs" #[item.slot]>
+            <college-profile v-if="item.slot === 'profile' && item.visited" :loading="loading" />
+            <college-brochure v-if="item.slot === 'brochure' && item.visited" />
+            <college-plan v-if="item.slot === 'plan' && item.visited" />
+            <college-enroll v-if="item.slot === 'enroll' && item.visited" />
+            <college-exam v-if="item.slot === 'exam' && item.visited" />
+          </template>
+          <!-- #endif -->
+          <!-- #ifdef MP-WEIXIN -->
+          <block v-for="item in tabs">
+            <template #[item.slot]>
+              <college-profile v-if="item.slot === 'profile' && item.visited" :loading="loading" />
+              <college-brochure v-if="item.slot === 'brochure' && item.visited" />
+              <college-plan v-if="item.slot === 'plan' && item.visited" />
+              <college-enroll v-if="item.slot === 'enroll' && item.visited" />
+              <college-exam v-if="item.slot === 'exam' && item.visited" />
+            </template>
+          </block>
+          <!-- #endif -->
+        </ie-tabs-swiper>
+      </view>
+    </uv-sticky>
+  </ie-page>
 </template>
 <script lang="ts" setup>
 
-import {useTransferPage} from "@/hooks/useTransferPage";
-import {UniversityDetail, University} from "@/types/university";
-import {MajorItem} from "@/types/major";
-import {universityDetail} from "@/api/modules/university";
-import {getMajorTree} from "@/api/modules/major";
+import { useTransferPage } from "@/hooks/useTransferPage";
+import { UniversityDetail, University } from "@/types/university";
+import { MajorItem } from "@/types/major";
+import { universityDetail } from "@/api/modules/university";
+import { getMajorTree } from "@/api/modules/major";
 import CollegeInfo from "@/pagesOther/pages/university/detail/components/college-info.vue";
-import {SwiperTabItem} from "@/types";
-import {useNavbar} from "@/hooks/useNavbar";
-import {useAppStore} from "@/store/appStore";
-import {MAJOR_TREE, UNIVERSITY_DETAIL} from "@/types/injectionSymbols";
+import { SwiperTabItem } from "@/types";
+import { useNavbar } from "@/hooks/useNavbar";
+import { useAppStore } from "@/store/appStore";
+import { MAJOR_TREE, UNIVERSITY_DETAIL } from "@/types/injectionSymbols";
 import CollegeProfile from "@/pagesOther/pages/university/detail/components/college-profile.vue";
 import CollegeBrochure from "@/pagesOther/pages/university/detail/components/college-brochure.vue";
 import CollegeExam from "@/pagesOther/pages/university/detail/components/college-exam.vue";
 import PlanEnrollList from "@/pagesOther/pages/university/detail/components/plan-enroll-list.vue";
 
-const {prevData} = useTransferPage()
-const {baseStickyTop} = useNavbar()
+const { prevData } = useTransferPage()
+const { baseStickyTop } = useNavbar()
 const detail = ref<UniversityDetail>({} as UniversityDetail)
 const baseInfo = computed<University>(() => detail.value.baseInfo || {} as University)
 const planList = computed(() => detail.value.planHistories || [])
@@ -55,47 +64,47 @@ const appStore = useAppStore()
 const current = ref(0)
 const tabHeight = computed(() => appStore.sysInfo.screenHeight - baseStickyTop.value)
 const tabs = ref<SwiperTabItem[]>([{
-    name: '概况',
-    slot: 'profile',
-    visited: true
+  name: '概况',
+  slot: 'profile',
+  visited: true
 }, {
-    name: '简章',
-    slot: 'brochure',
-    visited: false
+  name: '简章',
+  slot: 'brochure',
+  visited: false
 }, {
-    name: '计划',
-    slot: 'plan',
-    visited: false
+  name: '计划',
+  slot: 'plan',
+  visited: false
 }, {
-    name: '录取',
-    slot: 'enroll',
-    visited: false
+  name: '录取',
+  slot: 'enroll',
+  visited: false
 }, {
-    name: '考试大纲',
-    slot: 'exam',
-    visited: false
+  name: '考试大纲',
+  slot: 'exam',
+  visited: false
 }])
 
 const handleChangeSwiper = function (e: any) {
-    current.value = e.detail.current
-    tabs.value[current.value].visited = true
+  current.value = e.detail.current
+  tabs.value[current.value].visited = true
 }
 
 provide(UNIVERSITY_DETAIL, detail)
 provide(MAJOR_TREE, majorTree)
 onMounted(() => {
-    uni.$ie.showLoading()
-    loading.value = true
-    universityDetail({code: prevData.value.code})
-        .then(res => {
-            detail.value = res.data
-            return getMajorTree({})
-        })
-        .then(res => majorTree.value = res.data)
-        .finally(() => {
-            uni.$ie.hideLoading()
-            loading.value = false
-        })
+  uni.$ie.showLoading()
+  loading.value = true
+  universityDetail({ code: prevData.value.code })
+    .then(res => {
+      detail.value = res.data
+      return getMajorTree({})
+    })
+    .then(res => majorTree.value = res.data)
+    .finally(() => {
+      uni.$ie.hideLoading()
+      loading.value = false
+    })
 })
 // 必须手动触发才能保证 navbar.transparent 正常工作
 onPageScroll(() => {
@@ -104,6 +113,6 @@ onPageScroll(() => {
 
 <style lang="scss" scoped>
 ::v-deep .uv-tabs__wrapper__nav__item__text {
-    white-space: nowrap;
+  white-space: nowrap;
 }
 </style>

+ 2 - 1
src/pagesOther/pages/university/index/components/college-list.vue

@@ -3,7 +3,7 @@
     <z-paging ref="paging" v-model="list" @query="handleQuery">
       <template #top>
         <slot name="top" />
-        <college-conditions-picker v-if="filterOptions" :options="filterOptions" @change="handleSearch" />
+        <college-conditions-picker v-if="filterOptions" :options="filterOptions" :absolute="absolute" @change="handleSearch" />
         <ie-search v-model="queryParams.name" placeholder="输入院校名称" @search="handleSearch" @clear="handleSearch" />
       </template>
       <view class="p-20 flex flex-col gap-20">
@@ -25,6 +25,7 @@ import { routes } from "@/common/routes";
 const props = withDefaults(defineProps<{
   customItemClick?: boolean;
   extraFilter?: Record<string, any>;
+  absolute?: boolean;
 }>(), {
   customItemClick: false,
   extraFilter: () => ({})

+ 2 - 1
src/pagesOther/pages/university/index/components/plus/college-conditions-picker.vue

@@ -1,6 +1,6 @@
 <template>
   <view>
-    <ie-dropdown :configs="configs" v-model="form" @change="handleChange" />
+    <ie-dropdown :configs="configs" v-model="form" :absolute="absolute" @change="handleChange" />
   </view>
 </template>
 
@@ -12,6 +12,7 @@ import type { UniversityQueryDto, UniversityFilter } from "@/types/university";
 
 const props = defineProps<{
   options: UniversityFilter;
+  absolute?: boolean;
 }>()
 const filter = inject(UNIVERSITY_FILTER) || ref({} as UniversityQueryDto)
 

+ 19 - 19
src/pagesOther/pages/university/index/index.vue

@@ -1,34 +1,34 @@
 <template>
-    <ie-page fix-height bg-color="#F6F8FA" :safe-area-inset-bottom="false">
-        <ie-navbar title="院校库"/>
-        <ie-auto-resizer>
-            <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
-                <swiper class="swiper h-full" :current="current" @change="handleChangeSwiper">
-                    <swiper-item v-for="(item, index) in tabs" :key="index" class="h-full">
-                        <college-list v-if="item.slot==='list'"/>
-                        <college-rank v-if="item.slot==='rank'"/>
-                    </swiper-item>
-                </swiper>
-            </ie-tabs-swiper>
-        </ie-auto-resizer>
-    </ie-page>
+  <ie-page fix-height bg-color="#F6F8FA" :safe-area-inset-bottom="false">
+    <ie-navbar title="院校库" />
+    <ie-auto-resizer>
+      <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
+        <template #list>
+          <college-list :absolute="true" />
+        </template>
+        <template #rank>
+          <college-rank />
+        </template>
+      </ie-tabs-swiper>
+    </ie-auto-resizer>
+  </ie-page>
 </template>
 <script lang="ts" setup>
-import {SwiperTabItem} from "@/types";
+import { SwiperTabItem } from "@/types";
 import CollegeList from "@/pagesOther/pages/university/index/components/college-list.vue";
 import CollegeRank from "@/pagesOther/pages/university/index/components/college-rank.vue";
 
 const current = ref(0);
 const tabs = ref<SwiperTabItem[]>([{
-    name: '院校库',
-    slot: 'list'
+  name: '院校库',
+  slot: 'list'
 }, {
-    name: '院校排名',
-    slot: 'rank'
+  name: '院校排名',
+  slot: 'rank'
 }]);
 
 const handleChangeSwiper = function (e: any) {
-    current.value = e.detail.current;
+  current.value = e.detail.current;
 }
 </script>
 <style lang="scss" scoped></style>

+ 8 - 8
src/pagesStudy/pages/index/compoentns/index-menu.vue

@@ -11,7 +11,8 @@
 <script lang="ts" setup>
 import { useUserStore } from '@/store/userStore';
 import { useTransferPage } from '@/hooks/useTransferPage';
-const { transferTo } = useTransferPage();
+
+const { transferTo, routes } = useTransferPage();
 const userStore = useUserStore();
 type MenuItem = {
   label: string;
@@ -22,38 +23,37 @@ const menus = computed(() => [
   {
     label: '课程学习',
     icon: '/menu/menu-course.png',
-    pageUrl: '/pagesOther/pages/video-center/index/index',
+    pageUrl: routes.pageCourseStudy,
     visible: true
   },
   {
     label: '组卷作业',
     icon: '/menu/menu-exam.png',
-    pageUrl: '/pagesStudy/pages/homework/homework',
+    pageUrl: routes.pageHomework,
     visible: userStore.isStudent
   },
   {
     label: '收藏夹',
     icon: '/menu/menu-favorite.png',
-    // pageUrl: '/pagesOther/pages/personal-center/my-concerned/my-concerned'
-    pageUrl: '/pagesOther/pages/topic-center/topic-collection/topic-collection',
+    pageUrl: routes.pageCollect,
     visible: true
   },
   {
     label: '错题本',
     icon: '/menu/menu-mistake.png',
-    pageUrl: '/pagesOther/pages/topic-center/wrong-book/wrong-book',
+    pageUrl: routes.pageWrongBook,
     visible: true
   },
   {
     label: '学习记录',
     icon: '/menu/menu-record.png',
-    pageUrl: '/pagesStudy/pages/study-history/study-history',
+    pageUrl: routes.pageStudyHistory,
     visible: true
   }
 ])
 const navigateTo = (menu: MenuItem) => {
   if (menu.label === '错题本') {
-    transferTo('/pagesOther/pages/topic-center/wrong-book/wrong-book', {
+    transferTo(routes.pageWrongBook, {
       data: {}
     });
   } else {

+ 3 - 1
src/pagesSystem/pages/setting/setting.vue

@@ -82,7 +82,9 @@ const settings = computed(() => [
     title: '客服电话',
     icon: 'server-man',
     value: contactPhone.value,
-    handler: () => { }
+    handler: () => {
+      userStore.callContactPhone();
+    }
   }
 ]);
 </script>

BIN
src/static/personal/icon-protocol.png


+ 19 - 0
src/store/userStore.ts

@@ -280,6 +280,25 @@ export const useUserStore = defineStore('ie-user', {
       }).finally(() => {
         uni.$ie.hideLoading();
       });
+    },
+    /**
+     * 拨打客服电话
+     * @returns 
+     */
+    callContactPhone() {
+      if (!this.orgInfo.contactPhone) {
+        uni.$ie.showToast('暂无客服电话');
+        return;
+      }
+      uni.showActionSheet({
+        title: '客服电话',
+        itemList: [`拨打电话:${this.orgInfo.contactPhone}`],
+        success: (res) => {
+          uni.makePhoneCall({
+            phoneNumber: this.orgInfo.contactPhone
+          });
+        }
+      });
     }
   },
   persist: {