Explorar el Código

📦 排名页面对接

快乐的梦鱼 hace 2 semanas
padre
commit
52e7690ea0

+ 1 - 0
src/api/light/LightVillageApi.ts

@@ -84,6 +84,7 @@ export class LightVillageApi extends AppServerRequestModule<DataModel> {
       mobile: string;
       points: number;
       level: number;
+      type: string;
       type_text?: string;
       sex_text?: string;
       status_text?: string;

+ 0 - 1
src/components/display/Badge.vue

@@ -248,7 +248,6 @@ const showBadge = computed(() =>
   justify-content: center;
   align-items: center;
   text-align: center;
-  align-self: flex-start;
   overflow: hidden;
   flex-shrink: 0;
 }

+ 0 - 1
src/components/display/Tag.vue

@@ -281,7 +281,6 @@ const style = computed(() => {
   flex-basis: auto;
   min-width: 20rpx;
   width: auto;
-  align-self: flex-start;
 }
 
 </style>

+ 14 - 0
src/pages.json

@@ -60,6 +60,20 @@
       }
     },
     {
+      "path": "pages/home/village/rank/volunteer",
+      "style": {
+        "navigationBarTitleText": "志愿者排名",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/home/village/rank/village",
+      "style": {
+        "navigationBarTitleText": "村落排名",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
       "path": "pages/dig/details",
       "style": {
         "navigationBarTitleText": "村社文化资源挖掘平台-详情",

+ 4 - 4
src/pages/home/components/VillageMyFollow.vue

@@ -2,8 +2,8 @@
   <FlexCol padding="space.md">
     <HomeTitle title="我的关注" />
     <RequireLogin unLoginMessage="登录后查看我的关注村社" @loginSuccess="myFollowLoader.reload()">
-      <FlexCol>
-        <SimplePageListLoader :loader="myFollowLoader">
+      <SimplePageListLoader :loader="myFollowLoader">
+        <FlexCol gap="gap.md">
           <ImageBlock3
             v-for="(item, i) in myFollowLoader.list.value"
             :key="i"
@@ -16,8 +16,8 @@
             :imageHeight="140"
             @click="emit('goDetails', item)"
           />
-        </SimplePageListLoader>
-      </FlexCol>
+        </FlexCol>
+      </SimplePageListLoader>
     </RequireLogin>
   </FlexCol>
 </template>

+ 20 - 12
src/pages/home/index.vue

@@ -95,10 +95,14 @@
       </Button>
     </FlexRow>
 
-    <HomeTitle title="乡村排名" showMore />
+    <HomeTitle title="乡村排名" showMore @moreClicked="navTo('/pages/home/village/rank/village', {
+      regionId: currentRegion ?? undefined,
+    })" />
     <VillageRankList :list="villageRankListLoader.content.value ?? []" />
 
-    <HomeTitle title="志愿者排名" showMore :lightCount="3" />
+    <HomeTitle title="志愿者排名" showMore :lightCount="3" @moreClicked="navTo('/pages/home/village/rank/volunteer', {
+      regionId: currentRegion ?? undefined,
+    })" />
     <VillageUserRankList :list="villageUserRankListLoader.content.value ?? []" />
 
     <HomeTitle title="精选记忆" showMore />
@@ -150,6 +154,10 @@ import { useTheme } from '@/components/theme/ThemeDefine';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
 import { useStorageVar } from '@/components/composeabe/StorageVar';
 import { useVillageStore } from '@/store/village';
+import { useGetCurrentLocation } from './composeabe/GetCurrentLocation';
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import { ArrayUtils } from '@imengyu/imengyu-utils';
+import { toast } from '@/components/utils/DialogAction';
 import { navTo } from '@/components/utils/PageAction';
 import Image from '@/components/basic/Image.vue';
 import Loadmore from '@/components/display/loading/Loadmore.vue';
@@ -161,26 +169,20 @@ import Button from '@/components/basic/Button.vue';
 import HomeTitle from '@/common/components/parts/HomeTitle.vue';
 import VillageRankList from './components/VillageRankList.vue';
 import VillageUserRankList from './components/VillageUserRankList.vue';
-import VillageInfoApi from '@/api/inhert/VillageInfoApi';
 import MasonryGrid from '@/components/layout/masonry/MasonryGrid.vue';
 import MasonryGridItem from '@/components/layout/masonry/MasonryGridItem.vue';
 import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
 import Popup from '@/components/dialog/Popup.vue';
 import CitySelect from './components/CitySelect.vue';
 import VillageMyFollow from './components/VillageMyFollow.vue';
-import type { CityItem } from '@/api/map/MapApi';
 import MapApi from '@/api/map/MapApi';
 import LightMap from './components/LightMap.vue';
 import NoticeBar from '@/components/display/NoticeBar.vue';
 import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
-import type { VillageListItem } from '@/api/inhert/VillageApi';
 import FollowVillageApi from '@/api/light/FollowVillageApi';
-import { useGetCurrentLocation } from './composeabe/GetCurrentLocation';
-import { toast } from '@/components/utils/DialogAction';
 import LightVillageApi from '@/api/light/LightVillageApi';
-import CommonContent from '@/api/CommonContent';
-import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
-import { ArrayUtils } from '@imengyu/imengyu-utils';
+import type { CityItem } from '@/api/map/MapApi';
+import type { VillageListItem } from '@/api/inhert/VillageApi';
 
 const emit = defineEmits(['goVillage']);
 
@@ -293,7 +295,13 @@ onMounted(async () => {
   }
   const res = await FollowVillageApi.getFollowVillageList({ page: 1, pageSize: 200 });
   villageStore.setMyFollowVillages(res.list);
-  if (res.list.length > 0)
-    villageStore.setCurrentVillage(res.list[0]);
+  if (res.list.length > 0) {
+    const currentVillage = villageStore.loadCurrentVillage();
+    if (currentVillage) {
+      villageStore.setCurrentVillage(res.list.find(p => p.id === currentVillage) as VillageListItem);
+    } else {
+      villageStore.setCurrentVillage(res.list[0]);
+    }
+  }
 });
 </script>

+ 1 - 1
src/pages/home/village/index.vue

@@ -14,7 +14,7 @@
       <HomeLargeTitle title="村社名片" :active="tab === 'card'" @click="tab = 'card'" />
       <HomeLargeTitle title="乡源树" :active="tab === 'tree'" @click="tab = 'tree'">
         <template #icon>
-          <Image src="https://xy.wenlvti.net/app_static/images/village/IconLargeTree.png" :width="45" :height="46" mode="heightFix" />
+          <Image src="https://xy.wenlvti.net/app_static/images/village/TreeIconAmin.gif" :width="45" :height="46" mode="heightFix" />
         </template>
       </HomeLargeTitle>
     </FlexRow>

+ 34 - 3
src/pages/home/village/introd/card.vue

@@ -35,6 +35,7 @@
           :width="200"
           :height="140"
           mode="aspectFill"
+          defaultImage=""
           touchable
         >
           <template #empty>
@@ -126,9 +127,11 @@
     </BackgroundBox>
 
     <!-- 排行榜 -->
-    <HomeTitle title="排行榜" />
+    <HomeTitle title="排行榜" showMore @moreClicked="navTo('/pages/home/village/rank/volunteer', {
+      villageId: villageStore.currentVillage?.id ?? undefined,
+    })" />
     <RoundTags v-model:active="rankActiveTag" :tags="['乡源果', '志愿者', '乡源光']" />
-    <VillageUserRankList />
+    <VillageUserRankList :list="villageUserRankListLoader.content.value ?? []" />
 
     <!-- 魅力乡源 -->
     <HomeTitle title="魅力乡源" showMore>
@@ -229,6 +232,9 @@ import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem
 import { useVillageStore } from '@/store/village';
 import FollowVillageApi from '@/api/light/FollowVillageApi';
 import { confirm, toast } from '@/components/utils/DialogAction';
+import LightVillageApi from '@/api/light/LightVillageApi';
+import { ArrayUtils } from '@imengyu/imengyu-utils';
+import { navTo } from '@/components/utils/PageAction';
 
 const villageStore = useVillageStore();
 const villageInfoLoader = useSimpleDataLoader(async () => {
@@ -252,12 +258,37 @@ const villageInfoLoader = useSimpleDataLoader(async () => {
 watch(() => villageStore.currentVillage, () => {
   villageInfoLoader.reload();
   recommendLoader.reload();
-
+  villageUserRankListLoader.reload();
 });
 
 const rankActiveTag = ref('乡源果');
 const listActiveTag = ref('广场');
 
+const villageUserRankListLoader = useSimpleDataLoader(async () => {
+  const res = (await LightVillageApi.getVolunteerRankList({ 
+    num: 3,
+    village_id: villageStore.currentVillage?.id ?? undefined,
+  }))
+    .map((item, i) => ({
+      id: item.id,
+      image: item.image ?? '',
+      title: item.name,
+      rank: i + 1,
+      score: item.points,
+    }));
+  if (res.length >= 3) {
+    //移动第一名到中间
+    const first = res[0];
+    ArrayUtils.removeAt(res, 0);
+    ArrayUtils.insert(res, 1, first);
+  }
+  return res
+});
+
+watch(rankActiveTag, () => {
+  villageUserRankListLoader.reload();
+});
+
 const isFollowed = computed(() => {
   return villageStore.myFollowVillages.some(p => p.id === villageStore.currentVillage?.id);
 });

+ 81 - 0
src/pages/home/village/rank/village.vue

@@ -0,0 +1,81 @@
+<template>
+  <FlexCol gap="gap.lg" padding="space.md">
+    <BackgroundBox
+      v-for="(item, index) in villageRankListLoader.content.value"
+      :key="item.id"
+      backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxLong.png"
+      :backgroundCutBorder="[10,10,10,10]"
+      :backgroundCutBorderSize="[10,10,10,10]"
+      :padding="[25,25]"
+      direction="row"
+      justify="space-between"
+      align="center"
+      gap="gap.md"
+    >
+      <FlexRow align="center" gap="gap.lg">
+        <BackgroundBox
+          backgroundImage="https://xy.wenlvti.net/app_static/images/village/ImageBlessingCount.png"
+          width="60rpx"
+          height="60rpx"
+          center
+        >
+          <Text :text="index + 1" fontConfig="h4" color="white" />
+        </BackgroundBox>
+        <Image 
+          :src="item.image" 
+          width="170rpx"
+          height="120rpx"
+          mode="aspectFill"
+          radius="radius.md"
+        />
+        <Text :text="item.title" fontConfig="contentText" />
+      </FlexRow>
+      <FlexRow center gap="gap.md">
+        <BackgroundBox
+          backgroundImage="https://xy.wenlvti.net/app_static/images/village/TagNormal.png"
+          :backgroundCutBorder="[10,10,10,10]"
+          :backgroundCutBorderSize="[10,10,10,10]"
+          :padding="[15,10]"
+          center
+          direction="row"
+          gap="gap.md"
+          width="100"
+        >
+          <Image src="https://xy.wenlvti.net/app_static/images/village/IconLight.png" width="30rpx" height="30rpx" mode="aspectFill" />
+          <Text :text="item.points" fontConfig="contentText" />
+        </BackgroundBox>
+      </FlexRow>
+    </BackgroundBox>
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
+import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import LightVillageApi from '@/api/light/LightVillageApi';
+import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
+import Text from '@/components/basic/Text.vue';
+import Image from '@/components/basic/Image.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+
+const { querys } = useLoadQuerys({
+  regionId: 0,
+}, () => {
+  villageRankListLoader.reload();
+});
+
+const villageRankListLoader = useSimpleDataLoader(async () => {
+  const res = await LightVillageApi.getVillageRankList({ 
+    region_id: querys.value.regionId || undefined, 
+    num: 30
+  });
+  return res.map((item, i) => ({
+    image: item.image ?? '',
+    title: item.name,
+    rank: i + 1,
+    id: item.id,
+    points: item.points,
+  }));
+});
+</script>

+ 105 - 0
src/pages/home/village/rank/volunteer.vue

@@ -0,0 +1,105 @@
+<template>
+  <FlexCol gap="gap.lg" padding="space.md">
+    <VillageUserRankList :list="villageUserRankListFirst3" />
+    <BackgroundBox
+      v-for="(item, index) in villageUserRankListAfter3"
+      :key="item.id"
+      backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxLong.png"
+      :backgroundCutBorder="[10,10,10,10]"
+      :backgroundCutBorderSize="[10,10,10,10]"
+      :padding="[25,25]"
+      direction="row"
+      justify="space-between"
+      align="center"
+      gap="gap.md"
+    >
+      <FlexRow align="center" gap="gap.lg">
+        <BackgroundBox
+          backgroundImage="https://xy.wenlvti.net/app_static/images/village/ImageBlessingCount.png"
+          width="100rpx"
+          height="70rpx"
+          center
+        >
+          <Text :text="index + 4" fontConfig="h3" color="white" />
+        </BackgroundBox>
+        <Avatar 
+          :url="item.image" 
+          :size="70" 
+          mode="aspectFill" 
+          radius="radius.md" 
+        />
+        <Text :text="item.title" fontConfig="contentText" />
+      </FlexRow>
+      <FlexRow center gap="gap.md">
+        <Tag v-if="item.isAdmin" text="管理员" size="small" />
+        <BackgroundBox
+          backgroundImage="https://xy.wenlvti.net/app_static/images/village/TagNormal.png"
+          :backgroundCutBorder="[10,10,10,10]"
+          :backgroundCutBorderSize="[10,10,10,10]"
+          :padding="[15,10]"
+          center
+          direction="row"
+          gap="gap.md"
+          width="100"
+        >
+          <Image src="https://xy.wenlvti.net/app_static/images/village/IconFruit.png" width="30rpx" height="30rpx" mode="aspectFill" />
+          <Text :text="item.score" fontConfig="contentText" />
+        </BackgroundBox>
+      </FlexRow>
+    </BackgroundBox>
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
+import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
+import { ArrayUtils } from '@imengyu/imengyu-utils';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import VillageUserRankList from '../../components/VillageUserRankList.vue';
+import LightVillageApi from '@/api/light/LightVillageApi';
+import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
+import { computed } from 'vue';
+import Text from '@/components/basic/Text.vue';
+import Avatar from '@/components/display/Avatar.vue';
+import Tag from '@/components/display/Tag.vue';
+import Image from '@/components/basic/Image.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+
+const { querys } = useLoadQuerys({
+  regionId: 0,
+  villageId: 0,
+}, () => {
+  villageUserRankListLoader.reload();
+});
+
+const villageUserRankListLoader = useSimpleDataLoader(async () => {
+  const res = (await LightVillageApi.getVolunteerRankList({ 
+    region_id: querys.value.regionId || undefined, 
+    village_id: querys.value.villageId || undefined,
+    num: 30,
+  }))
+    .map((item, i) => ({
+      id: item.id,
+      image: item.image ?? '',
+      title: item.name,
+      rank: i + 1,
+      score: item.points,
+      isAdmin: item.type === 'admin',
+    }));
+
+  if (res.length >= 3) {
+    //移动第一名到中间
+    const first = res[0];
+    ArrayUtils.removeAt(res, 0);
+    ArrayUtils.insert(res, 1, first);
+  }
+  return res
+});
+const villageUserRankListFirst3 = computed(() => {
+  return villageUserRankListLoader.content.value?.slice(0, 3) ?? [];
+});
+const villageUserRankListAfter3 = computed(() => {
+  return villageUserRankListLoader.content.value?.slice(3) ?? [];
+});
+
+</script>

+ 5 - 1
src/store/village.ts

@@ -15,7 +15,10 @@ export const useVillageStore = defineStore('village', () => {
 
   function setCurrentVillage(village: VillageListItem) {
     currentVillage.value = village;
-    console.log('setCurrentVillage', village);
+    uni.setStorageSync('currentVillage', village.id);
+  }
+  function loadCurrentVillage() {
+    return uni.getStorageSync('currentVillage') as number|unknown;
   }
   function setCurrentLonlat(lonlat: { longitude: number, latitude: number }) {
     currentLonlat.value = lonlat;
@@ -36,6 +39,7 @@ export const useVillageStore = defineStore('village', () => {
     currentRegion,
     myFollowVillages,
     myJoinedVillages,
+    loadCurrentVillage,
     setCurrentVillage,
     setCurrentLonlat,
     setCurrentRegion,