Bladeren bron

feat: 调整个人信息页面

IlhamTahir 1 jaar geleden
bovenliggende
commit
6074180a1a

+ 3 - 0
pages.config.ts

@@ -48,6 +48,9 @@ export default defineUniPages({
     {
       path: 'pages/setting/index',
       type: 'page',
+      style: {
+        navigationBarTitleText: '设置',
+      },
     },
     {
       path: 'pages/start-filing/index',

+ 6 - 0
src/api/user.ts

@@ -0,0 +1,6 @@
+import type { User } from '@/model/user'
+import httpClient from '@/api/httpClient'
+
+export function getCurrentUser() {
+  return httpClient.get<User>('/users/current')
+}

+ 15 - 1
src/main.ts

@@ -1,14 +1,28 @@
 import { createPinia } from 'pinia'
+import { createPersistedState } from 'pinia-plugin-persistedstate'
 import { createSSRApp } from 'vue'
 import App from './App.vue'
 import './styles/tailwind.css'
 
 export function createApp() {
-  const pinia = createPinia()
   const app = createSSRApp(App)
+  const pinia = createPinia()
+  pinia.use(customStorage())
   app.use(pinia)
   return {
     app,
     pinia,
   }
 }
+function customStorage() {
+  return createPersistedState({
+    storage: {
+      getItem(key) {
+        return uni.getStorageSync(key)
+      },
+      setItem(key, value) {
+        uni.setStorageSync(key, value)
+      },
+    },
+  })
+}

+ 2 - 2
src/model/pet-manual.ts

@@ -1,5 +1,5 @@
 import type { Paging } from '@/model/base'
-import type { Pet } from '@/model/pet'
+import type { CreatePetRequest } from '@/model/pet'
 
 export interface CreateCarousalsRequest {
   imageUrl: string
@@ -36,7 +36,7 @@ export interface Recommends {
 }
 export interface PetCard {
   image?: string
-  key?: keyof Pet
+  key?: keyof CreatePetRequest
   value?: any
   name: string
 }

+ 15 - 1
src/model/pet.ts

@@ -1,4 +1,4 @@
-import type { TraceableModel } from '@/model/base'
+import type { BaseModel, TraceableModel } from '@/model/base'
 
 export interface Pet extends TraceableModel {
   birthday: string
@@ -47,3 +47,17 @@ export enum Gender {
   FEMALE,
   UNKNOWN,
 }
+
+export enum FeedingGoal {
+  GAIN = 'gain',
+  LOSE = 'lose',
+  MAINTAIN = 'maintain',
+}
+
+export interface FeedingPlan extends BaseModel {
+  feedingGoal: FeedingGoal
+  targetWeight: number
+}
+
+export interface CreateFeedingPlanRequest extends Omit<FeedingPlan, keyof BaseModel> {
+}

+ 5 - 0
src/model/user.ts

@@ -4,6 +4,11 @@ export interface User extends TraceableModel {
   username: string
   locked: boolean
   enabled: boolean
+  age: number
+  avatar: null | string
+  address: null | string
+  occupation: null | string
+  trueName: null | string
 }
 
 export interface UserSearchFilter extends BaseFilterRequest {

+ 3 - 1
src/pages.json

@@ -45,7 +45,9 @@
     {
       "path": "pages/setting/index",
       "type": "page",
-      "style": {}
+      "style": {
+        "navigationBarTitleText": "设置"
+      }
     },
     {
       "path": "pages/start-filing/index",

+ 17 - 33
src/pages/feed-calculator/components/FeedQuestionnaire.vue

@@ -4,7 +4,6 @@ import FeedForm from '@/pages/feed-calculator/components/FeedForm.vue'
 import FeedSlogan from '@/pages/feed-calculator/components/FeedSlogan.vue'
 import ProgressBar from '@/pages/feed-calculator/components/ProgressBar.vue'
 import avator from '@/static/image/pet-parameters/avatar.png'
-import right from '@/static/image/pet-parameters/right.png'
 
 const props = defineProps<{
   list: FeedFormQuestions[]
@@ -51,19 +50,21 @@ function handlePrevious() {
     emits('back')
   }
 }
-function handleAnswer(answer: PetCard) {
-  console.log(answer.name, '答案')
 
+const feedingPlanStore = useFeedingPlanStore()
+
+function handleAnswer(answer: PetCard) {
+  if (answer.key) {
+    feedingPlanStore.setPetValue(answer.key, answer.value)
+  }
   if (step.value === 2 || step.value === 7) {
     emits('step', step.value)
   }
   if (step.value === props.list.length - 1) {
-    console.log(123)
     isUserPage.value = true
   }
   if (step.value < props.list.length - 1 + addPage.value) {
     step.value += 1
-    console.log(step.value, 'step')
   }
 }
 </script>
@@ -78,41 +79,24 @@ function handleAnswer(answer: PetCard) {
         <image :src="avator" class="w-[64px] h-[64px] rounded-full" />
         <view class="mt-[5px] ">
           <text class="font-bold text-[16px] ">
-            {{ props.userList.username }}
+            {{ feedingPlanStore.pet.name }}
           </text>
           <view class="mt-[8px] flex gap-2">
-            <view v-for="(item, index) in props.userList.type" :key="index" class="text-[12px] text-[#999] bg-[#F3F3F3] rounded-[3px] py-[2px] px-[8px]">
-              {{ item }}
+            <view v-for="item in feedingPlanStore.petTags" :key="item.key" class="text-[12px] text-[#999] bg-[#F3F3F3] rounded-[3px] py-[2px] px-[8px]">
+              {{ item.value }}
             </view>
           </view>
         </view>
       </view>
     </view>
-    <view class="w-[calc(100% - 32px)] mx-[16px] h-[56px] bg-[white] rounded-t-3 mt-4 flex items-center card_border_bottom p-4 justify-between">
-      <view class="whitespace-nowrap">
-        喂养目标
-      </view>
-
-      <view class="flex justify-center items-center">
-        <picker :value="aimIndex" :range="aimList" @change="handleAimChange($event, 'aim')">
-          <view class="uni-input">
-            {{ aimList[aimIndex] }}
-          </view>
-        </picker>
-        <image :src="right" class="w-[24px] h-[24px]" />
-      </view>
-    </view>
-    <view class="w-[calc(100% - 32px)] mx-[16px] h-[56px] bg-[white] rounded-b-3 flex items-center p-4 justify-between">
-      <view>目标体重</view>
-      <view class="flex justify-center items-center">
-        <picker :value="weightIndex" :range="weightList" @change="handleAimChange($event, 'weight')">
-          <view class="uni-input">
-            {{ weightList[weightIndex] }}
-          </view>
-        </picker>
-        <image :src="right" class="w-[24px] h-[24px]" />
-      </view>
-    </view>
+    <CellGroup>
+      <Cell title="喂养目标" border>
+        <PickerItem v-model="feedingPlanStore.feedingPlan.feedingGoal" :options="feedingPlanStore.feedingGoalOptions" />
+      </Cell>
+      <Cell title="目标体重">
+        <PopupInput v-model="feedingPlanStore.feedingPlan.targetWeight" placeholder="请输入目标体重" />
+      </Cell>
+    </CellGroup>
     <view class="flex items-center justify-center">
       <button class="w-[176px] h-[47px] flex items-center justify-center bg-[#4545E5] border-none text-[white] rounded-3xl mt-[210px]">
         下一步

+ 34 - 18
src/pages/me/index.vue

@@ -4,10 +4,9 @@ import avatar from '@/static/image/me/avatar.png'
 import consult from '@/static/image/me/consult.png'
 import coupon from '@/static/image/me/coupon.png'
 import memberShop from '@/static/image/me/memberShop.png'
-import ToolApi from '@/utils'
 
-const safeHeight = ToolApi.getSafeHeight()
-const titleName = ref<string>('我的')
+const appStore = useAppStore()
+
 const userInfo = ref<UserInfo>({
   age: 0,
   avatar,
@@ -36,10 +35,24 @@ const userModules = ref<UserModule>({
     path: '',
   },
 })
+
+onShow(appStore.fetchCurrentUser)
+
+function goToSetting() {
+  uni.navigateTo({
+    url: '/pages/setting/index',
+  })
+}
+
+function goUserInfo() {
+  uni.navigateTo({
+    url: '/pages/userInfo/index',
+  })
+}
 </script>
 
 <template>
-  <view class="w-full bg-[#F5F6F7]" :style="`height:calc(100vh - ${safeHeight}px)`">
+  <view class="w-full bg-[#F5F6F7] h-screen">
     <view class="me-container p-4 w-full">
       <view class="me-card bg-[#FFFFFF] h-[229px] flex flex-col justify-center items-center w-full rounded-xl">
         <view class="me-card-info flex flex-1 w-full border-b-1 border-[#E7E7E7] p-4 justify-between items-center">
@@ -48,16 +61,21 @@ const userModules = ref<UserModule>({
               <image :src="userInfo.avatar" alt="avatar" class="w-[64px] h-[64px] rounded-full" />
             </view>
             <view class="me-card-info-login-person flex flex-col justify-between h-[54px]">
-              <text class="text-[16px] font-bold ">
-                {{ userInfo.nickName }}
+              <text class="text-[16px] font-bold line-clamp-1">
+                <template v-if="appStore.user">
+                  {{ appStore.user.username }}
+                </template>
+                <span v-else @click="() => appStore.login()">
+                  请登录
+                </span>
               </text>
               <view class="h-[fit-content] text-[#999999] ">
-                <uni-tag :text="`${userInfo.isLogin ? (`${userInfo.age}岁`) : '年龄'}`" class="mr-2" />
-                <uni-tag :text="userInfo.memberType" />
+                <uni-tag :text="`${appStore.age ? (`${appStore.age}岁`) : '年龄'}`" class="mr-2" />
+                <uni-tag :text="appStore.memberType" />
               </view>
             </view>
           </view>
-          <view class="me-card-info-edit w-[20px] h-[20px]">
+          <view class="me-card-info-edit w-[20px] h-[20px] shrink-0" @tap="goUserInfo">
             <image src="@/static/image/me/edit.png" alt="edit" class="w-full h-full" />
           </view>
         </view>
@@ -66,7 +84,7 @@ const userModules = ref<UserModule>({
             v-for="item in userModules" :key="item.id"
             class="flex justify-between items-center flex-col me-card-item-module"
           >
-            <image :src="item.imgUrl" :alt="item.name" class="w-[48px] h-[48px]" />
+            <image :src="item.imgUrl" :alt="item.name" class="w-[48px] h-[48px] shrink-0" />
             <text class="text-[12px] text-[#000000]">
               {{ item.name }}
             </text>
@@ -74,14 +92,12 @@ const userModules = ref<UserModule>({
         </view>
       </view>
     </view>
-    <uni-card spacing="0" padding="0" :border="false">
-      <view class="uni-body">
-        <uni-list :border="false">
-          <uni-list-item title="关于我们" show-arrow class="border-b-1 border-[#E7E7E7]" />
-          <uni-list-item title="设置" show-arrow />
-        </uni-list>
-      </view>
-    </uni-card>
+    <view class="px-4">
+      <CellGroup>
+        <Cell title="关于我们" border />
+        <Cell title="设置" @tap="goToSetting" />
+      </CellGroup>
+    </view>
   </view>
 </template>
 

+ 13 - 17
src/pages/setting/index.vue

@@ -1,25 +1,21 @@
 <script setup lang="ts">
-import ToolFun from '@/utils'
 
-const titleName = ref<string>('设置')
-const safeHeight = ToolFun.getSafeHeight()
 </script>
 
 <template>
-  <TitleBar :title-name="titleName" />
-  <view class="flex flex-col bg-[#F5F6F7] overflow-y-auto" :style="`height:calc(100vh - ${safeHeight}px)`">
-    <uni-card>
-      <uni-list class="text-[16px] font-normal" :border="false">
-        <uni-list-item title="通用设置" />
-        <uni-list-item title="通知设置" />
-      </uni-list>
-    </uni-card>
-    <uni-card>
-      <uni-list class="mt-6 text-[16px] font-normal" :border="false">
-        <uni-list-item title="账号安全" />
-        <uni-list-item title="隐私" />
-      </uni-list>
-    </uni-card>
+  <view class="flex flex-col bg-[#F5F6F7] overflow-y-auto h-screen gap-4 pt-4">
+    <view class="px-4">
+      <CellGroup>
+        <Cell title="通用设置" border />
+        <Cell title="通知设置" />
+      </CellGroup>
+    </view>
+    <view class="px-4">
+      <CellGroup>
+        <Cell title="账号安全" border />
+        <Cell title="隐私" />
+      </CellGroup>
+    </view>
   </view>
 </template>
 

+ 2 - 22
src/pages/userInfo/index.vue

@@ -2,15 +2,10 @@
 import avatar from '@/static/image/user-info/avatar.png'
 import component from '@/static/image/user-info/Component.png'
 import union from '@/static/image/user-info/union.png'
-import ToolFun from '@/utils'
-
-const titleName = ref<string>('个人信息')
-const safeHeight = ToolFun.getSafeHeight()
 </script>
 
 <template>
-  <TitleBar :title-name="titleName" />
-  <view class="flex flex-col bg-[#F5F6F7] overflow-y-auto" :style="`height:calc(100vh - ${safeHeight}px)`">
+  <view class="flex flex-col bg-[#F5F6F7] overflow-y-auto h-screen">
     <view class="flex justify-center items-center  p-[61px] w-full pb-[30px] ">
       <view class="relative h-[80px] w-[80px]">
         <image
@@ -49,20 +44,5 @@ const safeHeight = ToolFun.getSafeHeight()
 </template>
 
 <style  lang="scss" scoped>
-        :deep .uni-list-item{
-        height: 56px !important;
-      }
-      :deep .uni-list-item__content-title {
-        color: var(--text-icon-font-gy-190, rgba(0, 0, 0, 0.90)) !important;
-      font-size: 16px !important;
-      font-family: "PingFang SC" !important;
-      font-style: normal !important;
-      font-weight: 400 !important;
-     }
-     :deep .uni-list-item__extra-text{
-      color: var(--text-icon-font-gy-190, rgba(0, 0, 0, 0.90)) !important;
-      font-size: 16px !important;
-      font-style: normal !important;
-      font-weight: 400 !important;
-     }
+
 </style>

+ 23 - 1
src/stores/app.ts

@@ -1,4 +1,6 @@
+import type { User } from '@/model/user'
 import { createToken } from '@/api/token'
+import { getCurrentUser } from '@/api/user'
 import { defineStore } from 'pinia'
 import { computed, ref } from 'vue'
 
@@ -6,7 +8,10 @@ export const useAppStore = defineStore(
   'app',
   () => {
     const token = ref('')
-
+    const user = ref<User | null>(null)
+    const fetchCurrentUser = async () => {
+      user.value = await getCurrentUser()
+    }
     const login = () => {
       uni.showLoading({ title: '登录中' })
       return new Promise<void>((resolve, reject) => {
@@ -15,6 +20,7 @@ export const useAppStore = defineStore(
           success: async (result) => {
             const data = await createToken(result.code)
             token.value = data.token
+            await fetchCurrentUser()
             uni.hideLoading()
             resolve()
           },
@@ -30,10 +36,26 @@ export const useAppStore = defineStore(
       return !!token.value
     })
 
+    const memberType = '会员'
+
+    const age = computed(() => {
+      if (!user.value) {
+        return 0
+      }
+      return user.value.age
+    })
+
     return {
       token,
       isLogin,
       login,
+      fetchCurrentUser,
+      user,
+      memberType,
+      age,
     }
   },
+  {
+    persist: true,
+  },
 )

+ 36 - 1
src/stores/feeding-plan.ts

@@ -1,4 +1,11 @@
-import { type CreatePetRequest, Gender, PetBodyType, PetType } from '@/model/pet'
+import {
+  type CreateFeedingPlanRequest,
+  type CreatePetRequest,
+  FeedingGoal,
+  Gender,
+  PetBodyType,
+  PetType,
+} from '@/model/pet'
 import { defineStore } from 'pinia'
 
 export const useFeedingPlanStore = defineStore('feeding-plan', () => {
@@ -26,9 +33,37 @@ export const useFeedingPlanStore = defineStore('feeding-plan', () => {
     weight: 0,
   })
 
+  const petTags = computed(() => {
+    return [
+      { key: 'age', value: `${new Date().getFullYear() - new Date(pet.value.birthday).getFullYear()}岁` },
+      { key: 'type', value: pet.value.type === PetType.CAT ? '猫猫' : '狗狗' },
+      { key: 'weight', value: `${pet.value.weight}kg` },
+    ]
+  })
+
+  const feedingPlan = ref<CreateFeedingPlanRequest>({
+    feedingGoal: FeedingGoal.LOSE,
+    targetWeight: pet.value.weight - 1,
+  })
+
+  const feedingGoalOptions = [
+    { value: FeedingGoal.GAIN, label: '增肥' },
+    { value: FeedingGoal.LOSE, label: '减重' },
+    { value: FeedingGoal.MAINTAIN, label: '保持' },
+  ]
+
+  const setPetValue = (key: keyof CreatePetRequest, value: any) => {
+    // @ts-expect-error @ts-ignore
+    pet.value[key] = (value as CreatePetRequest[keyof CreatePetRequest])
+  }
+
   return {
     pet,
     petTypeOptions,
     genderOptions,
+    setPetValue,
+    petTags,
+    feedingPlan,
+    feedingGoalOptions,
   }
 })