Forráskód Böngészése

new volunteer - init

abpcoder 2 hete
szülő
commit
50a11ad5bf

+ 3 - 1
package.json

@@ -8,7 +8,8 @@
     "dev:mp": "uni -p mp-dev",
     "build": "uni build -p",
     "build:h5": "uni build pro-h5",
-    "build:mp": "uni build pro-mp"
+    "build:mp": "uni build pro-mp",
+    "wx:dev": "npm run server mp-dev"
   },
   "uni-app": {
     "scripts": {
@@ -75,6 +76,7 @@
     "@dcloudio/uni-cli-shared": "3.0.0-4080720251210001",
     "@dcloudio/uni-stacktracey": "3.0.0-4080720251210001",
     "@dcloudio/vite-plugin-uni": "3.0.0-4080720251210001",
+    "@types/lodash": "^4.17.21",
     "@types/node": "^24.1.0",
     "@uni-helper/vite-plugin-uni-tailwind": "^0.15.2",
     "@vue/runtime-core": "^3.4.21",

+ 16 - 0
src/components/ie-gap/ie-gap.vue

@@ -0,0 +1,16 @@
+<template>
+    <view class="w-full bg-[#F6F8FA]" :class="['h-'+height]"/>
+</template>
+
+<script setup lang="ts">
+defineProps({
+    height: {
+        type: [String, Number],
+        default: 16
+    }
+})
+</script>
+
+<style scoped>
+
+</style>

+ 38 - 0
src/pagesMain/pages/volunteer/components/volunteer-banner-item.vue

@@ -0,0 +1,38 @@
+<template>
+    <view class="relative" @click="$emit('click')">
+        <view class="absolute z-1 top-24 left-28">
+            <view class="text-fore-title text-lg font-bold">{{ title }}</view>
+            <view class="mt-6 h-42 flex justify-center items-center px-12 rounded-full text-2xs text-fore-title"
+                  :style="{backgroundColor: descBgColor}">
+                {{ desc }}
+            </view>
+        </view>
+        <ie-image :src="bgSrc" is-oss custom-class="w-full"/>
+    </view>
+</template>
+
+<script setup lang="ts" name="VolunteerBannerItem">
+defineProps({
+    title: {
+        type: String,
+        default: ''
+    },
+    desc: {
+        type: String,
+        default: ''
+    },
+    descBgColor: {
+        type: String,
+        default: ''
+    },
+    bgSrc: {
+        type: String,
+        default: ''
+    }
+})
+defineEmits(['click'])
+</script>
+
+<style scoped>
+
+</style>

+ 30 - 0
src/pagesMain/pages/volunteer/components/volunteer-banner.vue

@@ -0,0 +1,30 @@
+<template>
+    <view class="px-28 flex gap-18">
+        <volunteer-banner-item title="测录取概率" desc="院校录取风险评估" desc-bg-color="#A8F496"
+                               bg-src="/volunteer/index/banner_rate.png" class="flex-1" @click="goRateCalc"/>
+        <view class="flex-1 flex flex-col justify-between">
+            <volunteer-banner-item title="测技能分" desc="精准定位" desc-bg-color="#F8ECA6"
+                                   bg-src="/volunteer/index/banner_skill.png" @click="goSkillCalc"/>
+            <volunteer-banner-item title="志愿表" desc="我的报考意向" desc-bg-color="#DDD6FF"
+                                   bg-src="/volunteer/index/banner_list.png" @click="goVoluntaryList"/>
+        </view>
+    </view>
+</template>
+
+<script setup lang="ts" name="VolunteerBanner">
+import VolunteerBannerItem from "@/pagesMain/pages/volunteer/components/volunteer-banner-item.vue";
+
+const goRateCalc = function () {
+
+}
+const goSkillCalc = function () {
+
+}
+const goVoluntaryList = function () {
+
+}
+</script>
+
+<style scoped>
+
+</style>

+ 18 - 0
src/pagesMain/pages/volunteer/components/volunteer-menu-item.vue

@@ -0,0 +1,18 @@
+<template>
+    <view class="w-92 flex flex-col items-center gap-8" @click="$emit('click')">
+        <ie-image is-oss :src="icon" custom-class="w-full"/>
+        <text class="keep-all whitespace-nowrap text-xs text-fore-title">{{ title }}</text>
+    </view>
+</template>
+
+<script setup lang="ts" name="VolunteerMenuItem">
+defineProps({
+    title: String,
+    icon: String
+})
+defineEmits(['click'])
+</script>
+
+<style scoped>
+
+</style>

+ 40 - 0
src/pagesMain/pages/volunteer/components/volunteer-menu.vue

@@ -0,0 +1,40 @@
+<template>
+    <view class="pt-20 pb-30 px-50 flex justify-between items-center">
+        <volunteer-menu-item v-for="m in menus" :key="m.title" :title="m.title" :icon="m.icon" @click="goPage(m)" />
+    </view>
+</template>
+
+<script setup lang="ts" name="VolunteerMenu">
+import VolunteerMenuItem from "@/pagesMain/pages/volunteer/components/volunteer-menu-item.vue";
+
+type Menu = {
+    title: string
+    icon: string
+    pagePath: string
+}
+const menus: Menu[] = [{
+    title: '找院校',
+    icon: '/volunteer/index/menu_college.png',
+    pagePath: ''
+}, {
+    title: '查专业',
+    icon: '/volunteer/index/menu_major.png',
+    pagePath: ''
+}, {
+    title: '看职业',
+    icon: '/volunteer/index/menu_vocation.png',
+    pagePath: ''
+}, {
+    title: '志愿分析',
+    icon: '/volunteer/index/menu_analysis.png',
+    pagePath: ''
+}]
+
+const goPage = function (menu: Menu) {
+
+}
+</script>
+
+<style scoped>
+
+</style>

+ 37 - 79
src/pagesMain/pages/volunteer/volunteer.vue

@@ -1,88 +1,46 @@
 <template>
-  <ie-page>
-    <ie-image :is-oss="true" src="/volunteer/page-bg.png" custom-class="w-full h-auto absolute top-0 left-0 -z-1" />
-    <ie-image :is-oss="true" src="/volunteer/title-right.png"
-      :custom-class="`w-400 h-auto absolute right-0 ${appStore.isH5 ? 'top-100' : 'top-170'}`" />
-    <view :class="`ml-30 ${appStore.isH5 ? 'pt-200' : 'pt-270'}`">
-      <ie-image :is-oss="true" src="/volunteer/title.png" custom-class="w-fit h-140 bg-back" mode="heightFix" />
-    </view>
-    <view class="relative">
-      <ie-image :is-oss="true" src="/volunteer/volunteer-bg.png" custom-class="w-full h-220" mode="scaleToFill" />
-      <view class="text-28 text-white absolute top-40 left-60">我的信息</view>
-      <view
-        class="px-46 h-1/2 absolute left-0 right-0 top-1/2 -translate-y-1/2 flex items-center justify-between box-border pt-50 text-24 text-primary">
-        <text>姓名:{{ userStore.nickName }}</text>
-        <text>省份:{{ userStore.getLocation || '--' }}</text>
-        <view class="flex items-center">
-          <text>类别:</text>
-          <ie-dict :dict-name="EnumDictName.EXAM_TYPE" :dict-value="userStore.getExamType || '--'" />
-        </view>
-      </view>
-    </view>
-    <view class="mx-26">
-      <view class="mb-20 shadow-card px-30 py-20 bg-white rounded-8 flex items-center justify-between gap-x-30"
-        v-for="item in menu" :key="item.title" @click="handleClick(item)">
-        <ie-image :is-oss="true" :src="item.icon" custom-class="w-96 h-96 rounded-full" mode="aspectFill" />
-        <view class="flex-1">
-          <view class="text-28 text-fore-title">{{ item.title }}</view>
-          <view class="mt-8 text-22 text-fore-light">{{ item.desc }}</view>
-        </view>
-        <uv-icon name="arrow-right" size="16" color="#B2B2B2" />
-      </view>
-    </view>
-    <template #tabbar>
-      <ie-tabbar :active="1" />
-    </template>
-  </ie-page>
+    <ie-page bg-color="white">
+        <ie-navbar bg-color="#FFFFFF" transparent custom-back :click-hover="false">
+            <template #headerLeft>
+                <view class="flex items-center gap-7 text-fore-subtitle text-sm font-medium">
+                    <ie-image is-oss src="/volunteer/index/navbar_title.png" custom-class="w-146"/>
+                    <text>·</text>
+                    <text>{{ examTypeName }}</text>
+                </view>
+            </template>
+            <template #headerRight>
+                <view class="flex items-center gap-5 text-fore-subtitle text-base font-medium">
+                    <ie-image is-oss src="/volunteer/index/navbar_location.png" custom-class="w-24"/>
+                    <text>{{ userStore.getLocation }}</text>
+                </view>
+            </template>
+        </ie-navbar>
+        <volunteer-banner :style="{marginTop: (baseStickyTop + 10) + 'px'}"/>
+        <volunteer-menu/>
+        <ie-gap/>
+        <template #tabbar>
+            <ie-tabbar :active="1"/>
+        </template>
+    </ie-page>
 </template>
 
 <script lang="ts" setup>
-import { useUserStore } from '@/store/userStore';
-import { useAppStore } from '@/store/appStore';
-import { useTransferPage } from '@/hooks/useTransferPage';
-import { EnumDictName } from '@/common/enum';
+import {useUserStore} from '@/store/userStore';
+import {useTransferPage} from '@/hooks/useTransferPage';
+import {EnumDictName} from '@/common/enum';
+import {useDictStore} from "@/store/dictStore";
+import {useNavbar} from "@/hooks/useNavbar";
+import VolunteerBanner from "@/pagesMain/pages/volunteer/components/volunteer-banner.vue";
+import VolunteerMenu from "@/pagesMain/pages/volunteer/components/volunteer-menu.vue";
 
-const { transferTo } = useTransferPage();
+const {transferTo} = useTransferPage();
 const userStore = useUserStore();
-const appStore = useAppStore();
-type MenuItem = {
-  title: string;
-  desc: string;
-  icon: string;
-  pagePath: string;
-};
-const menu: MenuItem[] = [
-  {
-    title: '院校录取概率测试',
-    desc: '输入院校专业,精准测算录取结果',
-    icon: '/volunteer/single.png',
-    pagePath: '/pagesOther/pages/ie/entry-single/entry-single'
-  },
-  // {
-  //   title: '模拟志愿分析',
-  //   desc: '精准分析你的志愿表',
-  //   icon: '/volunteer/analysis.png',
-  //   pagePath: '/pagesOther/pages/ie/entry-analysis/entry-analysis'
-  // },
-  // {
-  //   title: 'AI志愿',
-  //   desc: '精准推荐合理志愿,生成志愿表',
-  //   icon: '/volunteer/ai.png',
-  //   pagePath: '/pagesOther/pages/ie/entry-ai/entry-ai'
-  // },
-  {
-    title: '测职业技能分',
-    desc: '结合院校录取规则,快速测算',
-    icon: '/volunteer/calculate.png',
-    pagePath: '/pagesOther/pages/ie/entry-calculate/entry-calculate'
-  }
-];
-const handleClick = async (item: MenuItem) => {
-  const isLogin = await userStore.checkLogin();
-  if (isLogin) {
-    transferTo(item.pagePath);
-  }
-}
+const dictStore = useDictStore()
+const {baseStickyTop} = useNavbar();
+
+const examTypeName = computed(() => {
+    return dictStore.getDictLabel(EnumDictName.EXAM_TYPE, userStore.getExamType)
+})
 </script>
 
 <style lang="scss" scoped></style>

+ 6 - 15
src/store/dictStore.ts

@@ -1,6 +1,7 @@
 import { defineStore } from 'pinia';
 import { getDictData } from '@/api/modules/system';
 import { DictItem, DictStoreState } from '@/types';
+import _ from 'lodash';
 
 export const useDictStore = defineStore('ie-dict', {
   state: (): DictStoreState => {
@@ -13,26 +14,16 @@ export const useDictStore = defineStore('ie-dict', {
   },
   actions: {
     async loadDicts(dictNames: string[]) {
-      if (!dictNames.length) {
-        return Promise.resolve(true);
-      }
+      if (!dictNames.length) return
       // 已有的字段不需要重新加载
-      const newDictNames = dictNames.filter(dictName => {
-        if (!this.dicts[dictName]) {
-          this.dicts[dictName] = [];
-          return false;
-        }
-        return true;
-      });
-      if (!newDictNames.length) {
-        return Promise.resolve(true);
-      }
+      const newDictNames = _.difference(dictNames, _.keys(this.dicts))
+      if (!newDictNames.length) return
+      // 并发时可能会重复请求,但多请求比不请求好
       const name = newDictNames.join(',');
       const { data } = await getDictData(name);
       for (const dictName in data) {
-        this.dicts[dictName].push(...data[dictName]);
+        this.dicts[dictName] = data[dictName];
       }
-      return await Promise.resolve(true);
     },
     async loadDict(dictName: string) {
       if (this.dicts[dictName]) {