Преглед изворни кода

📦 对接挖掘页和优化

快乐的梦鱼 пре 1 месец
родитељ
комит
f70e3e947b

+ 2 - 0
src/api/inhert/VillageApi.ts

@@ -10,6 +10,7 @@ export class VillageListItem extends DataModel<VillageListItem> {
     this.setNameMapperCase('Camel', 'Snake');
     this.setNameMapperCase('Camel', 'Snake');
     this._convertTable = {
     this._convertTable = {
       id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
       id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
+      collectFlag: { clientSide: 'boolean' },
     }
     }
     this._nameMapperServer = {
     this._nameMapperServer = {
       name: 'villageName',
       name: 'villageName',
@@ -43,6 +44,7 @@ export class VillageListItem extends DataModel<VillageListItem> {
   district = '' as string|null;
   district = '' as string|null;
   township = '' as string|null;
   township = '' as string|null;
   address = '';
   address = '';
+  collectFlag = false;
   villageVolunteerId = null as number|null;
   villageVolunteerId = null as number|null;
   villageId !:number;
   villageId !:number;
   claimReason = '';
   claimReason = '';

+ 6 - 0
src/api/light/FollowVillageApi.ts

@@ -59,6 +59,12 @@ export class FollowVillageApi extends AppServerRequestModule<DataModel> {
     return res.requireData();
     return res.requireData();
   }
   }
 
 
+  async getClaimedVallageList(volunteerId?: string) {
+    const res = await this.get('/village/village/getVillageList', '获取已认领村落', {
+      village_volunteer_id: volunteerId,
+    });
+    return transformArrayDataModel<VillageListItem>(VillageListItem, transformSomeToArray(res.data), `村落`, true);
+  }
   async getFollowVillageList(options?: {
   async getFollowVillageList(options?: {
     page?: number;
     page?: number;
     pageSize?: number;
     pageSize?: number;

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

@@ -38,6 +38,10 @@ export class VillageListItem extends DataModel<VillageListItem> {
         this.image = this.images[0]
         this.image = this.images[0]
       }
       }
       this.thumbnail = this.image;
       this.thumbnail = this.image;
+      if (!this.name && this.villageName)
+        this.name = this.villageName as string;
+      if (this.villageId)
+        this.id = this.villageId;
     }
     }
 
 
   }
   }

+ 31 - 26
src/common/components/CommonDialog.vue

@@ -5,36 +5,41 @@
     closeable
     closeable
     closeIcon=""
     closeIcon=""
     backgroundColor="transparent"
     backgroundColor="transparent"
-    contentScrollMaxHeight="80vh"
+    contentScroll
+    contentScrollMaxHeight="90vh"
+    :contentPadding="0"
+    width="auto"
     @update:show="emit('update:show', $event)"
     @update:show="emit('update:show', $event)"
   >
   >
-    <BackgroundBox 
-      backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxDialog.png"
-      :backgroundCutBorder="48"
-      :backgroundCutBorderSize="48"
-      :padding="24"
-      direction="column"
-      gap="gap.md"
-    >
-      <template v-if="props.title">
+    <template #content>
+      <BackgroundBox 
+        backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxDialog.png"
+        :backgroundCutBorder="48"
+        :backgroundCutBorderSize="48"
+        :padding="24"
+        direction="column"
+        gap="gap.md"
+      >
+        <template v-if="props.title">
+          <Height :size="24" />
+          <slot name="titlePre"></slot>
+          <FlexCol center gap="gap.lg">
+            <slot name="titleHeader"></slot>
+            <H3 fontConfig="primaryTitle">{{ props.title }}</H3>
+            <CommonDivider v-if="props.showDivider" />
+          </FlexCol>
+        </template>
+        <slot></slot>
         <Height :size="24" />
         <Height :size="24" />
-        <slot name="titlePre"></slot>
-        <FlexCol center gap="gap.lg">
-          <slot name="titleHeader"></slot>
-          <H3 fontConfig="primaryTitle">{{ props.title }}</H3>
-          <CommonDivider v-if="props.showDivider" />
-        </FlexCol>
-      </template>
-      <slot></slot>
+      </BackgroundBox>
       <Height :size="24" />
       <Height :size="24" />
-    </BackgroundBox>
-    <Height :size="24" />
-    <ImageButton v-if="props.showCloseButton"
-      src="https://xy.wenlvti.net/app_static/images/ButtonClose.png"
-      :width="80"
-      :height="80"
-      @click="emit('update:show', false)"
-    />
+      <ImageButton v-if="props.showCloseButton"
+        src="https://xy.wenlvti.net/app_static/images/ButtonClose.png"
+        :width="80"
+        :height="80"
+        @click="emit('update:show', false)"
+      />
+    </template>
   </Dialog>
   </Dialog>
 </template>
 </template>
 
 

+ 5 - 1
src/common/components/RequireLogin.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
   <slot v-if="isLogged" />
   <slot v-if="isLogged" />
-  <BoxMid v-else center :height="300" :gap="30">
+  <BoxMid v-else-if="showLoginView" center :height="300" :gap="30">
     <FlexCol center :gap="20">
     <FlexCol center :gap="20">
       <Icon name="smile-filling" :size="80" />
       <Icon name="smile-filling" :size="80" />
       <Text :text="unLoginMessage" textAlign="center" fontConfig="contentSpeicalText" />
       <Text :text="unLoginMessage" textAlign="center" fontConfig="contentSpeicalText" />
@@ -31,6 +31,10 @@ defineProps({
     type: String,
     type: String,
     default: '登录后享受更多权益'
     default: '登录后享受更多权益'
   },
   },
+  showLoginView : {
+    type: Boolean,
+    default: true
+  }
 })
 })
 
 
 watch(isLogged, (newVal) => {
 watch(isLogged, (newVal) => {

+ 19 - 12
src/common/composeabe/UserTools.ts

@@ -1,11 +1,13 @@
 import VillageApi, { VolunteerInfo } from "@/api/inhert/VillageApi";
 import VillageApi, { VolunteerInfo } from "@/api/inhert/VillageApi";
 import { useSimpleDataLoader } from "@/components/composeabe/loader/SimpleDataLoader";
 import { useSimpleDataLoader } from "@/components/composeabe/loader/SimpleDataLoader";
 import { useAuthStore } from "@/store/auth";
 import { useAuthStore } from "@/store/auth";
+import { useVillageStore } from "@/store/village";
 import { ref } from "vue";
 import { ref } from "vue";
 
 
 export function useUserTools() {
 export function useUserTools() {
 
 
   const authStore = useAuthStore();
   const authStore = useAuthStore();
+  const villageStore = useVillageStore();
   const volunteerInfo = ref<VolunteerInfo | null>(null);
   const volunteerInfo = ref<VolunteerInfo | null>(null);
 
 
   async function getIsVolunteer() {
   async function getIsVolunteer() {
@@ -20,25 +22,30 @@ export function useUserTools() {
       return false;
       return false;
     }
     }
   }
   }
-  
-  const joinedVillagesLoader = useSimpleDataLoader(async () => {
+  async function getIsJoinedVillage(villageId: number) {
+    if (!authStore.isLogged) {
+      return false;
+    }
+    if (villageStore.myJoinedVillages.length === 0) {
+      await villageStore.loadMyJoinedVillages();
+    }
     try {
     try {
-      return await VillageApi.getClaimedVallageList();
+      const isJoined = villageStore.myJoinedVillages.some(p => p.villageId === villageId) ?? false;
+      return isJoined;
     } catch (error) {
     } catch (error) {
-      return [];
+      return false;
     }
     }
-  });
-
-  async function getIsJoinedVillage(villageId: number) {
+  }
+  async function getCanCollect(villageId: number) {
     if (!authStore.isLogged) {
     if (!authStore.isLogged) {
       return false;
       return false;
     }
     }
-    if (!joinedVillagesLoader.isLoaded.value) {
-      await joinedVillagesLoader.load();
+    if (villageStore.myJoinedVillages.length === 0) {
+      await villageStore.loadMyJoinedVillages();
     }
     }
     try {
     try {
-      const isJoined = joinedVillagesLoader.content.value?.some(p => p.villageId === villageId) ?? false;
-      return isJoined;
+      const village = villageStore.myJoinedVillages.find(p => p.villageId === villageId);
+      return Boolean(village !== undefined && village.collectFlag);
     } catch (error) {
     } catch (error) {
       return false;
       return false;
     }
     }
@@ -47,7 +54,7 @@ export function useUserTools() {
   return {
   return {
     getIsVolunteer,
     getIsVolunteer,
     getIsJoinedVillage,
     getIsJoinedVillage,
-    joinedVillagesLoader,
+    getCanCollect,
     volunteerInfo,
     volunteerInfo,
   };
   };
 }
 }

+ 0 - 19
src/common/data/CollectableModulesNameMapping.ts

@@ -1,19 +0,0 @@
-export const CollectableModulesNameMapping : Record<string, string> = {
-  'overview': '村落概况',
-  'distribution': '建筑分布',
-  'building': '传统建筑',
-  'folk_culture': '民俗文化',
-  'food_product': '美食物产',
-  'route': '旅游路线',
-  'travel_guide': '旅游导览',
-  'element': '环境要素',
-  'environment': '环境格局',
-  'relic': '文物古迹',
-  'cultural': '历史文化',
-  'figure': '历史人物',
-  'ich': '非遗',
-  'story': '掌故轶事',
-  'spots': '风景名胜',
-  'speaker': '口述者',
-  'collect': '随手记',
-}

+ 2 - 0
src/components/dialog/Dialog.vue

@@ -8,6 +8,8 @@
     <DialogInner 
     <DialogInner 
       ref="dialogInner"
       ref="dialogInner"
       v-bind="props"
       v-bind="props"
+      :contentScroll="props.contentScroll"
+      :contentScrollMaxHeight="props.contentScrollMaxHeight"
       :onConfirm="$props.onConfirm"
       :onConfirm="$props.onConfirm"
       :onCancel="$props.onCancel"
       :onCancel="$props.onCancel"
       :confirmCountDownTime="props.confirmCountDown"
       :confirmCountDownTime="props.confirmCountDown"

+ 4 - 1
src/components/dialog/DialogInner.vue

@@ -1,6 +1,9 @@
 <template>
 <template>
   <!--TODO: 在uniapp插槽问题修复后,此处可修改为插槽默认值-->
   <!--TODO: 在uniapp插槽问题修复后,此处可修改为插槽默认值-->
-  <FlexCol :innerStyle="{ ...themeStyles.dialog.value, width: themeContext.resolveThemeSize(width) }">
+  <FlexCol :innerStyle="{ 
+    ...themeStyles.dialog.value, 
+    width: themeContext.resolveThemeSize(width) 
+  }">
     <slot v-if="topSlots?.default" />
     <slot v-if="topSlots?.default" />
     <FlexCol v-else :padding="contentPadding" align="center">
     <FlexCol v-else :padding="contentPadding" align="center">
       <!-- 图标 -->
       <!-- 图标 -->

+ 3 - 3
src/pages/dig/forms/data/history.ts

@@ -27,7 +27,7 @@ export const villageInfoStoryFormItems: SingleForm = [CommonInfoModel, (r) => ({
 export const villageInfoFigureFormItems: SingleForm = [CommonInfoModel, (r) => ({
 export const villageInfoFigureFormItems: SingleForm = [CommonInfoModel, (r) => ({
   formItems: [
   formItems: [
     {
     {
-      label: '历史人物名称',
+      label: '人物名称',
       name: 'name',
       name: 'name',
       type: 'text',
       type: 'text',
       defaultValue: '',
       defaultValue: '',
@@ -40,8 +40,8 @@ export const villageInfoFigureFormItems: SingleForm = [CommonInfoModel, (r) => (
       }]
       }]
     },
     },
     ...villageCommonContent(r, {
     ...villageCommonContent(r, {
-      title: '历史人物',
+      title: '人物',
       showTitle: false,
       showTitle: false,
     }).formItems
     }).formItems
   ]
   ]
-}), { title: '历史人物', typeName: '', }]
+}), { title: '人物', typeName: '', }]

+ 6 - 7
src/pages/dig/forms/list-ordinary.vue

@@ -33,7 +33,7 @@
           />
           />
         </FlexRow>
         </FlexRow>
         <NotVolTip 
         <NotVolTip 
-          v-if="!isJoined" 
+          v-if="!canCollect" 
           @goJoin="goJoin"
           @goJoin="goJoin"
         /> 
         /> 
         <Height :height="5" />
         <Height :height="5" />
@@ -111,15 +111,14 @@ import VillageApi, { type VillageCatalogListItem } from '@/api/inhert/VillageApi
 import Icon from '@/components/basic/Icon.vue';
 import Icon from '@/components/basic/Icon.vue';
 import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
 import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
 import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
-import BackgroundImageButton from '@/components/basic/BackgroundImageButton.vue';
 import Width from '@/components/layout/space/Width.vue';
 import Width from '@/components/layout/space/Width.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
 import NotVolTip from '@/pages/home/components/NotVolTip.vue';
 import NotVolTip from '@/pages/home/components/NotVolTip.vue';
 
 
 const subTitle = ref('');
 const subTitle = ref('');
 const searchText = ref('');
 const searchText = ref('');
-const { getIsVolunteer, getIsJoinedVillage, volunteerInfo } = useUserTools();
-const isJoined = ref(false);
+const { getIsVolunteer, getCanCollect, volunteerInfo } = useUserTools();
+const canCollect = ref(false);
 const authStore = useAuthStore();
 const authStore = useAuthStore();
 const error = ref('');
 const error = ref('');
 
 
@@ -191,7 +190,7 @@ const listLoader = useSimplePageListLoader<{
 }, false);
 }, false);
 
 
 function newData() {
 function newData() {
-  if (!isJoined.value) {
+  if (!canCollect.value) {
     confirm({ 
     confirm({ 
       title: '提示', 
       title: '提示', 
       content: "您还不是当前村社的志愿者,请先加入志愿者队伍", 
       content: "您还不是当前村社的志愿者,请先加入志愿者队伍", 
@@ -220,7 +219,7 @@ function goDetail(item: { id: number, villageVolunteerId: number }) {
   let canEdit = false;
   let canEdit = false;
 
 
   if (!authStore.isAdmin 
   if (!authStore.isAdmin 
-    && (!isJoined.value || item.villageVolunteerId !== volunteerInfo.value?.id)
+    && (!canCollect.value || item.villageVolunteerId !== volunteerInfo.value?.id)
   ) {
   ) {
     //非当前村社志愿者或者不是自己提交的文章,只能查看详情
     //非当前村社志愿者或者不是自己提交的文章,只能查看详情
     //村社概览表单特殊处理
     //村社概览表单特殊处理
@@ -360,7 +359,7 @@ const { querys } = useLoadQuerys({
 }, async (querys) => {
 }, async (querys) => {
   //普通用户进入预览模式
   //普通用户进入预览模式
   await getIsVolunteer();
   await getIsVolunteer();
-  isJoined.value = await getIsJoinedVillage(querys.villageId);
+  canCollect.value = await getCanCollect(querys.villageId);
 
 
   function pushCatalogWithCurrentCatalog(catalog: VillageCatalogListItem) {
   function pushCatalogWithCurrentCatalog(catalog: VillageCatalogListItem) {
     if (catalog.collectModuleId === querys.collectModuleId) {
     if (catalog.collectModuleId === querys.collectModuleId) {

+ 1 - 1
src/pages/dig/forms/submits.vue

@@ -31,7 +31,7 @@
     <Height :height="20" />
     <Height :height="20" />
     <SimplePageListLoader :loader="listLoader" :noEmpty="true">
     <SimplePageListLoader :loader="listLoader" :noEmpty="true">
       <template #empty>
       <template #empty>
-        <Empty image="search" description="这里还没提交过投稿,快来去写吧!">
+        <Empty image="search" description="这里还没提交过投稿,欢迎成为志愿者投稿!">
         </Empty>
         </Empty>
       </template>
       </template>
       <FlexCol :gap="20">
       <FlexCol :gap="20">

+ 48 - 14
src/pages/home/components/VillageMyFollow.vue

@@ -1,21 +1,30 @@
 <template>
 <template>
   <FlexCol padding="space.md">
   <FlexCol padding="space.md">
-    <HomeTitle title="我关注" />
+    <HomeTitle title="我关注/加入的村社" />
     <RequireLogin unLoginMessage="登录后查看我的关注村社" @loginSuccess="villageStore.loadMyFollowVillages()">
     <RequireLogin unLoginMessage="登录后查看我的关注村社" @loginSuccess="villageStore.loadMyFollowVillages()">
       <FlexCol gap="gap.md">
       <FlexCol gap="gap.md">
-        <ImageBlock3
-          v-for="(item, i) in villageStore.myFollowVillages"
+        <Empty v-if="villageList.length === 0" description="还没有关注村社哦" />
+        <FlexRow 
+          v-for="(item, i) in villageList"
           :key="i"
           :key="i"
-          backgroundColor="transparent"
-          :src="item.image"
-          defaultImage="https://xy.wenlvti.net/app_static/images/village/PlaceholderVillage.jpg"
-          :title="item.name"
-          :desc="item.address"
-          :imageRadius="15"
-          :imageWidth="200"
-          :imageHeight="140"
-          @click="emit('goDetails', item as VillageListItem)"
-        />
+          justify="space-between" align="center" gap="gap.md"
+        >
+          <ImageBlock3
+            backgroundColor="transparent"
+            :src="item.image"
+            defaultImage="https://xy.wenlvti.net/app_static/images/village/PlaceholderVillage.jpg"
+            :title="item.name"
+            :desc="item.address"
+            :imageRadius="15"
+            :imageWidth="200"
+            :imageHeight="140"
+            @click="emit('goDetails', item as VillageListItem)"
+          />
+          <FlexRow justify="flex-end" align="center" gap="gap.md" width="200rpx">
+            <Tag v-if="item.isFollow" text="已关注" size="small" />
+            <Tag v-if="item.isJoined" text="已加入" size="small" type="primary" />
+          </FlexRow>
+        </FlexRow>
       </FlexCol>
       </FlexCol>
     </RequireLogin>
     </RequireLogin>
   </FlexCol>
   </FlexCol>
@@ -28,9 +37,34 @@ import ImageBlock3 from '@/components/display/block/ImageBlock3.vue';
 import RequireLogin from '@/common/components/RequireLogin.vue';
 import RequireLogin from '@/common/components/RequireLogin.vue';
 import type { VillageListItem } from '@/api/light/LightVillageApi';
 import type { VillageListItem } from '@/api/light/LightVillageApi';
 import { useVillageStore } from '@/store/village';
 import { useVillageStore } from '@/store/village';
+import Empty from '@/components/feedback/Empty.vue';
+import { computed } from 'vue';
+import Tag from '@/components/display/Tag.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
   (e: 'goDetails', item: VillageListItem): void;
   (e: 'goDetails', item: VillageListItem): void;
 }>();
 }>();
 const villageStore = useVillageStore();
 const villageStore = useVillageStore();
-</script>
+
+const villageList = computed(() => {
+  const followMap = new Map<number, typeof villageStore.myFollowVillages[0]>();
+  
+  villageStore.myFollowVillages.forEach(item => {
+    followMap.set(item.id, { ...item, isFollow: true, isJoined: false });
+  });
+  
+  villageStore.myJoinedVillages.forEach(item => {
+    const existing = followMap.get(item.id);
+    if (existing) {
+      existing.isJoined = true;
+    } else {
+      followMap.set(item.id, { ...item, isFollow: false, isJoined: true });
+    }
+  });
+  
+  return Array.from(followMap.values());
+});
+
+
+</script>

+ 139 - 105
src/pages/home/dig.vue

@@ -1,113 +1,117 @@
 <template>
 <template>
-  <FlexCol>
-    <FlexCol :padding="30">
-      <HomeLargeTitle title="挖掘" />
-      <ImageSwiper
-        :images="appConfiguration?.banners.dig"
-        width="100%"
-        :height="400"
-        radius="radius.md"
-        :innerStyle="{
-          border: '1px solid #fff',
-          overflow: 'hidden',
+  <FlexCol padding="padding.md">
+    <HomeLargeTitle title="挖掘" />
+    <ImageSwiper
+      :images="appConfiguration?.banners.dig"
+      width="100%"
+      :height="400"
+      radius="radius.md"
+      :innerStyle="{
+        border: '1px solid #fff',
+        overflow: 'hidden',
+      }"
+    />
+    <HomeTitle title="我的村社" />
+    <RequireLogin unLoginMessage="欢迎您成为志愿者!在这之前您需要登录或者注册完善基础信息后才能投稿和查看我认领的村社哦">
+      <FlexCol 
+        v-if="notVolunteerError"
+        gap="gap.lg" 
+        padding="padding.md"
+        center
+      >
+        <Image src="https://xy.wenlvti.net/app_static/images/home/BadgeNew.png" :width="320" mode="widthFix" />
+        <CommonDivider />
+        <Text 
+          textAlign="center"
+          text="认领属于你的村庄,参与建设家乡 或者先随便看看,了解更多乡村故事" 
+          fontConfig="contentSpeicalText" 
+        />
+        <FlexRow justify="space-around" gap="gap.md">
+          <FrameButton primary text="去认领村庄" @click="navTo('/pages/home/light/submit-map', {
+            city: currentCity,
+          })" width="220rpx" />
+        </FlexRow>
+      </FlexCol>
+      <SimplePageContentLoader
+        v-else
+        :loader="villageListLoader"
+        :showEmpty="villageListLoader.content.value?.length == 0"
+        :emptyView="{
+          text: '您点亮的村社正在审核中,审核通过后您可以查看和管理',
+          button: false,
         }"
         }"
-      />
-      <HomeTitle title="我的村社" />
-      <RequireLogin unLoginMessage="欢迎您成为志愿者!在这之前您需要登录或者注册完善基础信息后才能投稿和查看我认领的村社哦">
-        <FlexCol 
-          v-if="notVolunteerError"
-          gap="gap.lg" 
-          padding="padding.md"
-          center
-        >
-          <Image src="https://xy.wenlvti.net/app_static/images/home/BadgeNew.png" :width="320" mode="widthFix" />
-          <CommonDivider />
-          <Text 
-            textAlign="center"
-            text="认领属于你的村庄,参与建设家乡 或者先随便看看,了解更多乡村故事" 
-            fontConfig="contentSpeicalText" 
-          />
-          <FlexRow justify="space-around" gap="gap.md">
-            <FrameButton primary text="去认领村庄" @click="navTo('/pages/home/light/submit-map', {
-              city: currentCity,
-            })" width="220rpx" />
+      >
+        <FlexCol :gap="10">
+          <FlexRow 
+            v-for="item in villageListLoader.content.value"
+            :key="item.id"
+            radius="radius.md"
+            :padding="20"
+            align="center"
+            justify="space-between"
+            :innerStyle="{
+              border: '1px solid #fff',
+            }"
+          >
+            <FlexRow align="center" :gap="20">
+              <Image 
+                mode="aspectFill"
+                :src="item.image" 
+                round
+                :width="80"
+                :height="80"
+              />
+              <H3>{{ item.villageName }}</H3>
+            </FlexRow>
+            <ButtonGroup direction="row" align="center" :gap="0">
+              <BubbleBox :items="[
+                {
+                  icon: 'edit-filling',
+                  text: '管理',
+                  onClick: () => goManagePage(item),
+                },
+                {
+                  icon: 'edit-filling',
+                  text: '采编',
+                  onClick: () => goSubmitDigPage(item),
+                },
+              ]">
+                <Button v-if="authStore.isAdmin" icon="edit-filling" size="small">采编/管理</Button>
+              </BubbleBox>
+              <Button v-if="!authStore.isAdmin" icon="edit-filling" size="small" @click="goSubmitDigPage(item)">采编</Button>
+              <Button type="primary" size="small" icon="edit-filling" @click="goMyDigPage(item)">我的投稿</Button>            
+            </ButtonGroup>
           </FlexRow>
           </FlexRow>
         </FlexCol>
         </FlexCol>
-        <SimplePageContentLoader
-          v-else
-          :loader="villageListLoader"
-          :showEmpty="villageListLoader.content.value?.length == 0"
-          :emptyView="{
-            text: '您点亮的村社正在审核中,审核通过后您可以查看和管理',
-            button: false,
-          }"
-        >
-          <FlexCol :gap="10">
-            <FlexRow 
-              v-for="item in villageListLoader.content.value"
-              :key="item.id"
-              radius="radius.md"
-              :padding="20"
-              align="center"
-              justify="space-between"
-              :innerStyle="{
-                border: '1px solid #fff',
-              }"
-            >
-              <FlexRow align="center" :gap="20">
-                <Image 
-                  mode="aspectFill"
-                  :src="item.image" 
-                  round
-                  :width="80"
-                  :height="80"
-                />
-                <H3>{{ item.villageName }}</H3>
-              </FlexRow>
-              <ButtonGroup direction="row" align="center" :gap="0">
-                <BubbleBox :items="[
-                  {
-                    icon: 'edit-filling',
-                    text: '管理',
-                    onClick: () => goManagePage(item),
-                  },
-                  {
-                    icon: 'edit-filling',
-                    text: '采编',
-                    onClick: () => goSubmitDigPage(item),
-                  },
-                ]">
-                  <Button v-if="authStore.isAdmin" icon="edit-filling" size="small">采编/管理</Button>
-                </BubbleBox>
-                <Button v-if="!authStore.isAdmin" icon="edit-filling" size="small" @click="goSubmitDigPage(item)">采编</Button>
-                <Button type="primary" size="small" icon="edit-filling" @click="goMyDigPage(item)">我的投稿</Button>            
-              </ButtonGroup>
-            </FlexRow>
-          </FlexCol>
-        </SimplePageContentLoader>
-      </RequireLogin>
+      </SimplePageContentLoader>
+    </RequireLogin>
 
 
-      <Height :height="20" />
-      <HomeTitle v-if="authStore.isLogged" title="我的贡献" />
-      <BoxMid 
-        v-if="authStore.isLogged" 
-        :padding="[40,20]"
-        direction="row"
-      >
-        <FlexCol :flex="1" :gap="10" center>
-          <Text fontConfig="lightGoldTitle">{{ volunteerInfoLoader.content.value?.points || 0 }}</Text>
-          <Touchable direction="row" align="center" :gap="10" @click="navTo('/pages/dig/about/point')">
-            <Text>文化积分</Text>
-            <Icon icon="help-filling" color="primary" :size="40" />
-          </Touchable>
-        </FlexCol>
-        <FlexCol :flex="1" :gap="10" center>
-          <Text fontConfig="lightGoldTitle">Lv.{{ volunteerInfoLoader.content.value?.level || 1 }}</Text>
-          <Text>等级</Text>
-        </FlexCol>
-      </BoxMid>
-    </FlexCol>
+    <Height :height="20" />
+    <HomeTitle v-if="authStore.isLogged" title="我的贡献" />
+    <BoxMid 
+      v-if="authStore.isLogged" 
+      :padding="[40,20]"
+      direction="row"
+    >
+      <FlexCol :flex="1" :gap="10" center>
+        <Text fontConfig="lightGoldTitle">{{ volunteerInfoLoader.content.value?.points || 0 }}</Text>
+        <Touchable direction="row" align="center" :gap="10" @click="navTo('/pages/dig/about/point')">
+          <Text>文化积分</Text>
+          <Icon icon="help-filling" color="primary" :size="40" />
+        </Touchable>
+      </FlexCol>
+      <FlexCol :flex="1" :gap="10" center>
+        <Text fontConfig="lightGoldTitle">Lv.{{ volunteerInfoLoader.content.value?.level || 1 }}</Text>
+        <Text>等级</Text>
+      </FlexCol>
+    </BoxMid>
+    <Height :height="300" />
   </FlexCol>
   </FlexCol>
+  <ClamVolunteerDialog 
+    ref="clamVolunteerDialog"
+    :villageId="clamVolunteerVillageId"
+    @finish="clamFinish"
+  />
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
@@ -118,6 +122,7 @@ import { useCollectStore } from '@/store/collect';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
 import { useStorageVar } from '@/components/composeabe/StorageVar';
 import { useStorageVar } from '@/components/composeabe/StorageVar';
 import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
 import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
+import { confirm } from '@/components/dialog/CommonRoot';
 import VillageApi, { VillageListItem } from '@/api/inhert/VillageApi';
 import VillageApi, { VillageListItem } from '@/api/inhert/VillageApi';
 import RequireLogin from '@/common/components/RequireLogin.vue';
 import RequireLogin from '@/common/components/RequireLogin.vue';
 import SimplePageContentLoader from '@/components/loader/SimplePageContentLoader.vue';
 import SimplePageContentLoader from '@/components/loader/SimplePageContentLoader.vue';
@@ -137,9 +142,9 @@ import FrameButton from '@/common/components/FrameButton.vue';
 import CommonDivider from '@/common/components/CommonDivider.vue';
 import CommonDivider from '@/common/components/CommonDivider.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import Icon from '@/components/basic/Icon.vue';
 import Icon from '@/components/basic/Icon.vue';
-import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import ImageSwiper from '@/common/components/parts/ImageSwiper.vue';
 import ImageSwiper from '@/common/components/parts/ImageSwiper.vue';
 import BoxMid from '@/common/components/box/BoxMid.vue';
 import BoxMid from '@/common/components/box/BoxMid.vue';
+import ClamVolunteerDialog from './village/dialogs/ClamVolunteerDialog.vue';
 
 
 const authStore = useAuthStore();
 const authStore = useAuthStore();
 const collectStore = useCollectStore();
 const collectStore = useCollectStore();
@@ -172,7 +177,36 @@ watch(() => authStore.isLogged, (newVal) => {
   }
   }
 })
 })
 
 
+const clamVolunteerDialog = ref<InstanceType<typeof ClamVolunteerDialog>>();
+const clamVolunteerVillageId = ref<number>(0);
+
+function checkIsVolunteer(item: VillageListItem) {
+  if (!item.collectFlag) {
+    confirm({
+      title: '提示',
+      content: '您还不是本村志愿者,申请成为志愿者后即可开始采编挖掘',
+      confirmText: '去申请',
+      cancelText: '取消',
+    }).then((res) => {
+      if (res) {
+        clamVolunteerVillageId.value = item.villageId;
+        clamVolunteerDialog.value?.show();
+      }
+    })
+    return false;
+  }
+  return true;
+}
+
+function clamFinish() {
+  volunteerInfoLoader.reload();
+  rankListLoader.reload();
+}
+
 function goSubmitDigPage(item: VillageListItem) {
 function goSubmitDigPage(item: VillageListItem) {
+  if (!checkIsVolunteer(item))
+    return;
+  
   navTo('./dig/details', { 
   navTo('./dig/details', { 
     name: item.villageName,
     name: item.villageName,
     villageId: item.villageId,
     villageId: item.villageId,

+ 2 - 0
src/pages/home/index.vue

@@ -391,6 +391,8 @@ async function loadInfo() {
 
 
   //加载我的关注村庄
   //加载我的关注村庄
   await villageStore.loadMyFollowVillages();
   await villageStore.loadMyFollowVillages();
+  await villageStore.loadMyJoinedVillages();
+
   if (villageStore.myFollowVillages.length > 0) {
   if (villageStore.myFollowVillages.length > 0) {
     const currentVillage = villageStore.loadCurrentVillage();
     const currentVillage = villageStore.loadCurrentVillage();
     if (currentVillage) {
     if (currentVillage) {

+ 16 - 3
src/pages/home/light/form/claim.ts

@@ -1,5 +1,4 @@
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
-import type { CheckBoxListProps } from '@/components/dynamic/wrappers/CheckBoxList.vue';
 import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
 import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
 import type { FieldProps } from '@/components/form/Field.vue';
 import type { FieldProps } from '@/components/form/Field.vue';
 import type { FormProps } from '@/components/form/Form.vue';
 import type { FormProps } from '@/components/form/Form.vue';
@@ -50,7 +49,7 @@ export function getClaimVillageForm(options: {
             defaultValue: 'villager',
             defaultValue: 'villager',
             additionalProps: {
             additionalProps: {
               options: [
               options: [
-                { text: '村民', value: 'villager' },
+                //{ text: '村民', value: 'villager' },
                 { text: '志愿者', value: 'volunteer' },
                 { text: '志愿者', value: 'volunteer' },
                 { text: '管理人员', value: 'staff' },
                 { text: '管理人员', value: 'staff' },
               ],
               ],
@@ -78,6 +77,20 @@ export function getClaimVillageForm(options: {
             rules: [{ required: true, message: '请输入联系方式' }],
             rules: [{ required: true, message: '请输入联系方式' }],
           },
           },
           {
           {
+            label: '居民身份',
+            name: 'residentStatus',
+            type: 'radio-value',
+            defaultValue: 3,
+            additionalProps: {
+              options: [
+                { text: '在村劳作', value: 1 },
+                { text: '社区居民', value: 2 },
+                { text: '在外游子', value: 3 },
+                { text: '退休人员', value: 4 },
+              ],
+            } as RadioValueProps,
+          },
+          {
             label: '居住地址',
             label: '居住地址',
             name: 'address',
             name: 'address',
             type: 'text',
             type: 'text',
@@ -110,7 +123,7 @@ export function getClaimVillageForm(options: {
             name: 'claimReason',
             name: 'claimReason',
             type: 'textarea',
             type: 'textarea',
             additionalProps: {
             additionalProps: {
-              placeholder: '请说明认领该村社的原因',
+              placeholder: '请说明认领该村社的原因,可加快审核速度',
               showWordLimit: true,
               showWordLimit: true,
               maxLength: 200,
               maxLength: 200,
             } as FieldProps,
             } as FieldProps,

+ 0 - 6
src/pages/home/light/submit.vue

@@ -89,7 +89,6 @@
 import { onMounted, ref } from 'vue';
 import { onMounted, ref } from 'vue';
 import { useAppInit } from '@/common/composeabe/AppInit';
 import { useAppInit } from '@/common/composeabe/AppInit';
 import { useAuthStore } from '@/store/auth';
 import { useAuthStore } from '@/store/auth';
-import { useUserTools } from '@/common/composeabe/UserTools';
 import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
 import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
 import { UserApi } from '@/api/auth/UserApi';
 import { UserApi } from '@/api/auth/UserApi';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
@@ -99,18 +98,14 @@ import { back } from '@/components/utils/PageAction';
 import { closeToast, toast } from '@/components/dialog/CommonRoot';
 import { closeToast, toast } from '@/components/dialog/CommonRoot';
 import { showError } from '@/common/composeabe/ErrorDisplay';
 import { showError } from '@/common/composeabe/ErrorDisplay';
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
-import Button from '@/components/basic/Button.vue';
 import Result from '@/components/feedback/Result.vue';
 import Result from '@/components/feedback/Result.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import Height from '@/components/layout/space/Height.vue';
 import Height from '@/components/layout/space/Height.vue';
 import Icon from '@/components/basic/Icon.vue';
 import Icon from '@/components/basic/Icon.vue';
 import Text from '@/components/basic/Text.vue';
 import Text from '@/components/basic/Text.vue';
-import CommonRoot from '@/components/dialog/CommonRoot.vue';
 import DynamicForm from '@/components/dynamic/DynamicForm.vue';
 import DynamicForm from '@/components/dynamic/DynamicForm.vue';
-import Alert from '@/components/feedback/Alert.vue';
 import VillageApi, { VillageClaimInfo, VolunteerInfo } from '@/api/inhert/VillageApi';
 import VillageApi, { VillageClaimInfo, VolunteerInfo } from '@/api/inhert/VillageApi';
 import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
 import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
-import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
 import ProvideVar from '@/components/theme/ProvideVar.vue';
 import ProvideVar from '@/components/theme/ProvideVar.vue';
 import BoxMid from '@/common/components/box/BoxMid.vue';
 import BoxMid from '@/common/components/box/BoxMid.vue';
@@ -121,7 +116,6 @@ import BoxMid from '@/common/components/box/BoxMid.vue';
 
 
 const authStore = useAuthStore();
 const authStore = useAuthStore();
 const { init } = useAppInit();
 const { init } = useAppInit();
-const { getIsVolunteer } = useUserTools();
 
 
 const { querys } = useLoadQuerys({ 
 const { querys } = useLoadQuerys({ 
   villageId: 0,  
   villageId: 0,  

+ 114 - 0
src/pages/home/village/dialogs/ClamVolunteerDialog.vue

@@ -0,0 +1,114 @@
+<template>
+  <CommonDialog v-model:show="show" title="成为志愿者" :showDivider="false" :showCloseButton="false">
+    <FlexCol gap="gap.lg" padding="padding.md" width="600rpx">
+      <template v-if="step === 'form'">
+        <Text textAlign="center" text="请完善身份信息,解锁更多村社专属功能" fontConfig="contentSpeicalText" />
+        <Height :height="10" />
+        <ProvideVar :vars="{
+          FieldBackgroundColor: 'transparent',
+        }">
+          <BoxMid>
+            <DynamicForm
+              ref="addFormRef"
+              :model="addFormModel"
+              :options="addFormDefine"
+            />
+          </BoxMid>
+        </ProvideVar>
+        <Height :height="20" />
+        <FlexRow justify="space-around" gap="gap.md">
+          <FrameButton text="返回" @click="show = false" width="220rpx" />
+          <FrameButton primary text="提交" @click="addSubmit" :loading="addFormLoading" width="220rpx" />
+        </FlexRow>
+      </template>
+      <template v-else-if="step === 'finished'">
+        <Result
+          status="success"
+          title="提交成功"
+          description="等待系统审核,您可稍后再回来,您可以先逛逛社区看看其他村社吧"
+        />
+        <FlexRow justify="space-around" gap="gap.md">
+          <FrameButton primary text="完成" @click="show = false; emit('finish')" width="220rpx" />
+        </FlexRow>
+      </template>
+    </FlexCol>
+  </CommonDialog>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue';
+import { toast } from '@/components/dialog/CommonRoot';
+import { showError } from '@/common/composeabe/ErrorDisplay';
+import { useVillageStore } from '@/store/village';
+import VillageApi, { VillageClaimInfo } from '@/api/inhert/VillageApi';
+import CommonDialog from '@/common/components/CommonDialog.vue';
+import FrameButton from '@/common/components/FrameButton.vue';
+import Text from '@/components/basic/Text.vue';
+import DynamicForm from '@/components/dynamic/DynamicForm.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import Height from '@/components/layout/space/Height.vue';
+import Result from '@/components/feedback/Result.vue';
+import ProvideVar from '@/components/theme/ProvideVar.vue';
+import BoxMid from '@/common/components/box/BoxMid.vue';
+import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
+import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
+import type { FieldProps } from '@/components/form/Field.vue';
+import type { RuleItem } from 'async-validator';
+import { getClaimVillageForm } from '../../light/form/claim';
+
+const show = ref(false);
+const props = defineProps<{
+  villageId: number;
+}>();
+const emit = defineEmits(['finish']);
+
+const villageStore = useVillageStore();
+const step = ref('form');
+
+const addFormLoading = ref(false);
+const addFormRef = ref<IDynamicFormRef>();
+const addFormModel = ref<VillageClaimInfo>(new VillageClaimInfo());
+const addFormDefine = ref<IDynamicFormOptions>();
+
+async function addSubmit() {
+  if (!addFormRef.value || !addFormModel.value)
+    return;
+  try {
+    await addFormRef.value.validate();
+  } catch (e) {
+    toast({ content: '有必填项未填写,请检查' });
+    return;
+  }
+
+  try {
+    addFormLoading.value = true;
+    addFormModel.value.villageId = props.villageId;
+    await VillageApi.claimVallage(addFormModel.value as VillageClaimInfo);
+    toast({ content: '提交成功' });
+    step.value = 'finished';
+    villageStore.loadMyJoinedVillages();
+
+    setTimeout(() => {
+      villageStore.reloadVillageInfo();
+    }, 500);
+  } catch (e) {
+    showError(e);
+  } finally {
+    addFormLoading.value = false;
+  }
+}
+
+defineExpose({
+  show: () => {
+    show.value = true;
+    step.value = 'form';
+    addFormModel.value = new VillageClaimInfo();
+    addFormModel.value.type = 'volunteer';
+    addFormModel.value.villageId = props.villageId;
+    addFormDefine.value = getClaimVillageForm({
+      formRef: addFormRef,
+    });
+  },
+});
+</script>

+ 9 - 3
src/pages/home/village/dialogs/JoinDialog.vue

@@ -46,7 +46,7 @@
         <Result
         <Result
           status="success"
           status="success"
           title="提交成功"
           title="提交成功"
-          description="等待管理员审核,通过后即可为村社做贡献,您可以先逛逛学习吧"
+          description="等待系统审核,您可稍后再回来,您可以先逛逛社区看看其他村社吧"
         />
         />
         <FlexRow justify="space-around" gap="gap.md">
         <FlexRow justify="space-around" gap="gap.md">
           <FrameButton primary text="完成" @click="show = false" width="220rpx" />
           <FrameButton primary text="完成" @click="show = false" width="220rpx" />
@@ -60,6 +60,7 @@
 import { ref } from 'vue';
 import { ref } from 'vue';
 import { toast } from '@/components/dialog/CommonRoot';
 import { toast } from '@/components/dialog/CommonRoot';
 import { showError } from '@/common/composeabe/ErrorDisplay';
 import { showError } from '@/common/composeabe/ErrorDisplay';
+import { useVillageStore } from '@/store/village';
 import VillageApi, { VillageClaimInfo } from '@/api/inhert/VillageApi';
 import VillageApi, { VillageClaimInfo } from '@/api/inhert/VillageApi';
 import CommonDialog from '@/common/components/CommonDialog.vue';
 import CommonDialog from '@/common/components/CommonDialog.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
@@ -69,7 +70,6 @@ import DynamicForm from '@/components/dynamic/DynamicForm.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
 import Height from '@/components/layout/space/Height.vue';
 import Height from '@/components/layout/space/Height.vue';
-import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
 import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
@@ -84,6 +84,7 @@ const props = defineProps<{
 }>();
 }>();
 const emit = defineEmits(['apply']);
 const emit = defineEmits(['apply']);
 
 
+const villageStore = useVillageStore();
 const step = ref('chooseIdentity');
 const step = ref('chooseIdentity');
 
 
 const identityChoices = ref([
 const identityChoices = ref([
@@ -203,7 +204,12 @@ async function addSubmit() {
     addFormModel.value.villageId = props.villageId;
     addFormModel.value.villageId = props.villageId;
     await VillageApi.claimVallage(addFormModel.value as VillageClaimInfo);
     await VillageApi.claimVallage(addFormModel.value as VillageClaimInfo);
     toast({ content: '提交成功' });
     toast({ content: '提交成功' });
-    show.value = false;
+    step.value = 'finished';
+    villageStore.loadMyJoinedVillages();
+
+    setTimeout(() => {
+      villageStore.reloadVillageInfo();
+    }, 500);
   } catch (e) {
   } catch (e) {
     showError(e);
     showError(e);
   } finally {
   } finally {

+ 4 - 4
src/pages/home/village/goods/index.vue

@@ -63,8 +63,8 @@ const { querys } = useLoadQuerys({
   villageId: 0,
   villageId: 0,
 });
 });
 
 
-const { getIsVolunteer, getIsJoinedVillage, volunteerInfo } = useUserTools();
-const isJoined = ref(false);
+const { getIsVolunteer, getCanCollect, volunteerInfo } = useUserTools();
+const canCollect = ref(false);
 const CollectModuleId = 24; // 乡源好物模块id
 const CollectModuleId = 24; // 乡源好物模块id
 
 
 const goodsLoader = useSimplePageListLoader(20, async (page, pageSize, params) => {
 const goodsLoader = useSimplePageListLoader(20, async (page, pageSize, params) => {
@@ -88,7 +88,7 @@ const handleGoodDetail = (good: { id: number }) => {
   });
   });
 };
 };
 const handlePublish = () => {
 const handlePublish = () => {
-  if (!isJoined.value) {
+  if (!canCollect.value) {
     confirm({ 
     confirm({ 
       title: '提示', 
       title: '提示', 
       content: "您还不是当前村社的志愿者,请先加入志愿者队伍才能采编信息哦", 
       content: "您还不是当前村社的志愿者,请先加入志愿者队伍才能采编信息哦", 
@@ -111,7 +111,7 @@ const handlePublish = () => {
 
 
 onMounted(async () => {
 onMounted(async () => {
   await getIsVolunteer();
   await getIsVolunteer();
-  isJoined.value = await getIsJoinedVillage(querys.value.villageId);
+  canCollect.value = await getCanCollect(querys.value.villageId);
   await goodsLoader.load();
   await goodsLoader.load();
 });
 });
 
 

+ 15 - 6
src/pages/home/village/index.vue

@@ -28,7 +28,7 @@
         <Height :height="20" />
         <Height :height="20" />
         <FlexRow gap="gap.lg">
         <FlexRow gap="gap.lg">
           <FrameButton :text="isFollowed ? '已关注' : '先关注村庄'" @click="isFollowed ? onUnFollow() : onFollow()" />
           <FrameButton :text="isFollowed ? '已关注' : '先关注村庄'" @click="isFollowed ? onUnFollow() : onFollow()" />
-          <FrameButton text="去申请点亮" @click="handleGoApply()" primary />
+          <FrameButton text="去申请点亮" @click="handleLight" primary />
         </FlexRow>
         </FlexRow>
       </FlexCol>
       </FlexCol>
       <template v-else>
       <template v-else>
@@ -41,7 +41,11 @@
             </template>
             </template>
           </HomeLargeTitle>
           </HomeLargeTitle>
         </FlexRow>
         </FlexRow>
-        <Card v-if="tab === 'card'" @goTree="tab = 'tree'" />
+        <Card 
+          v-if="tab === 'card'" 
+          @goTree="tab = 'tree'" 
+          @goJoin="joinDialog?.show()"
+        />
         <Tree v-if="tab === 'tree'" />
         <Tree v-if="tab === 'tree'" />
       </template>
       </template>
       <Height :height="150" />
       <Height :height="150" />
@@ -60,6 +64,11 @@
     >
     >
       <VillageMyFollow @goDetails="onSelectVillage" />
       <VillageMyFollow @goDetails="onSelectVillage" />
     </Popup>
     </Popup>
+    <JoinDialog
+      ref="joinDialog" 
+      v-if="villageStore.currentVillage"
+      :villageId="villageStore.currentVillage.id" 
+    />
 
 
   </CommonRoot>
   </CommonRoot>
 </template>
 </template>
@@ -88,12 +97,14 @@ import Around from './recommed/around.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import { isDevEnv } from '@/common/config/AppCofig';
 import { isDevEnv } from '@/common/config/AppCofig';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
+import JoinDialog from './dialogs/JoinDialog.vue';
 
 
 const topTab = ref<'village' | 'around'>('village');
 const topTab = ref<'village' | 'around'>('village');
 const tab = ref('card');
 const tab = ref('card');
 const villageStore = useVillageStore();
 const villageStore = useVillageStore();
 const showMyFollowPopup = ref(false);
 const showMyFollowPopup = ref(false);
 const { isFollowed, onFollow, onUnFollow } = useFollow();
 const { isFollowed, onFollow, onUnFollow } = useFollow();
+const joinDialog = ref<InstanceType<typeof JoinDialog>>();
 
 
 const props = withDefaults(defineProps<{
 const props = withDefaults(defineProps<{
   showSwitch?: boolean;
   showSwitch?: boolean;
@@ -105,11 +116,9 @@ const isLight = computed(() => {
   return villageStore.currentVillage?.isLight ?? false;
   return villageStore.currentVillage?.isLight ?? false;
 });
 });
 
 
-function handleGoApply() {
+function handleLight() {
   navTo('/pages/home/light/submit', {
   navTo('/pages/home/light/submit', {
-    villageId: villageStore.currentVillage?.id ?? undefined,
-    unit: (villageStore.currentVillage?.city as string) + (villageStore.currentVillage?.district as string) + (villageStore.currentVillage?.township as string),
-    regionId: villageStore.currentVillage?.region ?? undefined,
+    villageId: villageStore.currentVillage?.id || 0,
   });
   });
 }
 }
 
 

+ 2 - 13
src/pages/home/village/introd/card.vue

@@ -225,12 +225,6 @@
     :topic="recommendTagName" 
     :topic="recommendTagName" 
     @publishsuccess="onPublishSuccess"
     @publishsuccess="onPublishSuccess"
   />
   />
-
-  <JoinDialog
-    ref="joinDialog" 
-    v-if="villageStore.currentVillage"
-    :villageId="villageStore.currentVillage.id" 
-  />
   <UpgradeDialog 
   <UpgradeDialog 
     ref="applyGoodsDialog" 
     ref="applyGoodsDialog" 
     v-if="villageStore.currentVillage"
     v-if="villageStore.currentVillage"
@@ -247,13 +241,11 @@ import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLo
 import { useVillageStore } from '@/store/village';
 import { useVillageStore } from '@/store/village';
 import { useRequireLogin } from '@/common/composeabe/RequireLogin';
 import { useRequireLogin } from '@/common/composeabe/RequireLogin';
 import { useFollow } from '../composeabe/Follow';
 import { useFollow } from '../composeabe/Follow';
-import { confirm, toast } from '@/components/utils/DialogAction';
 import { ArrayUtils } from '@imengyu/imengyu-utils';
 import { ArrayUtils } from '@imengyu/imengyu-utils';
 import { navTo } from '@/components/utils/PageAction';
 import { navTo } from '@/components/utils/PageAction';
 import HomeTitle from '@/common/components/parts/HomeTitle.vue';
 import HomeTitle from '@/common/components/parts/HomeTitle.vue';
 import Button from '@/components/basic/Button.vue';
 import Button from '@/components/basic/Button.vue';
 import Icon from '@/components/basic/Icon.vue';
 import Icon from '@/components/basic/Icon.vue';
-import Image from '@/components/basic/Image.vue';
 import Text from '@/components/basic/Text.vue';
 import Text from '@/components/basic/Text.vue';
 import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
@@ -263,12 +255,10 @@ import VillageMiniMap from '../../components/VillageMiniMap.vue';
 import Divider from '@/components/display/Divider.vue';
 import Divider from '@/components/display/Divider.vue';
 import RoundTags from '@/common/components/parts/RoundTags.vue';
 import RoundTags from '@/common/components/parts/RoundTags.vue';
 import VillageUserRankList from '../../components/VillageUserRankList.vue';
 import VillageUserRankList from '../../components/VillageUserRankList.vue';
-import BackgroundImageButton from '@/components/basic/BackgroundImageButton.vue';
 import ProvideVar from '@/components/theme/ProvideVar.vue';
 import ProvideVar from '@/components/theme/ProvideVar.vue';
 import Grid from '@/components/layout/grid/Grid.vue';
 import Grid from '@/components/layout/grid/Grid.vue';
 import GridItem from '@/components/layout/grid/GridItem.vue';
 import GridItem from '@/components/layout/grid/GridItem.vue';
 import LightVillageApi from '@/api/light/LightVillageApi';
 import LightVillageApi from '@/api/light/LightVillageApi';
-import Construction from '@/common/components/Construction.vue';
 import OfficialAccountPublishWrap from '@/common/components/OfficialAccountPublishWrap.vue';
 import OfficialAccountPublishWrap from '@/common/components/OfficialAccountPublishWrap.vue';
 import UpgradeDialog from '../dialogs/UpgradeDialog.vue';
 import UpgradeDialog from '../dialogs/UpgradeDialog.vue';
 import JoinDialog from '../dialogs/JoinDialog.vue';
 import JoinDialog from '../dialogs/JoinDialog.vue';
@@ -307,10 +297,9 @@ const villageInfoLoader = useSimpleDataLoader(async () => {
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
   (e: 'goTree'): void;
   (e: 'goTree'): void;
+  (e: 'goJoin'): void;
 }>();
 }>();
 
 
-const joinDialog = ref();
-
 const rankActiveTag = ref('乡源果');
 const rankActiveTag = ref('乡源果');
 const listActiveTag = ref('广场');
 const listActiveTag = ref('广场');
 
 
@@ -348,7 +337,7 @@ const recommendTagName = computed(() => {
 function handleGoJoin() {
 function handleGoJoin() {
   if (isJoined.value)
   if (isJoined.value)
     return;
     return;
-  joinDialog.value.show();
+  emit('goJoin');
 }
 }
 function handleGoNew() {
 function handleGoNew() {
   navTo('/pages/article/common/list', {
   navTo('/pages/article/common/list', {

+ 1 - 13
src/pages/index.vue

@@ -90,18 +90,6 @@ async function loadShareVillageInfo(id?: number) {
   }
   }
   tabIndex.value = 1;
   tabIndex.value = 1;
 }
 }
-async function reloadVillageInfo() {
-  try {
-    if (!villageStore.currentVillage)
-      return;
-    const res = await LightVillageApi.getVillageDetails(villageStore.currentVillage.id as number);
-    villageStore.setCurrentVillage(res);
-  } catch (error) {
-    console.error(error);
-    return;
-  }
-  tabIndex.value = 1;
-}
 function getShareVillageInfo() {
 function getShareVillageInfo() {
   if (villageStore.currentVillage) {
   if (villageStore.currentVillage) {
     //分享村社信息
     //分享村社信息
@@ -124,7 +112,7 @@ async function paySuccessAndRefresh() {
     });
     });
 
 
     tabIndex.value = 0;
     tabIndex.value = 0;
-    await reloadVillageInfo();
+    await villageStore.reloadVillageInfo();
     await waitTimeOut(100);
     await waitTimeOut(100);
     tabIndex.value = 1;
     tabIndex.value = 1;
   } catch (error) {
   } catch (error) {

+ 15 - 2
src/store/village.ts

@@ -24,6 +24,17 @@ export const useVillageStore = defineStore('village', () => {
   function loadCurrentVillage() {
   function loadCurrentVillage() {
     return uni.getStorageSync('currentVillage') as number|unknown;
     return uni.getStorageSync('currentVillage') as number|unknown;
   }
   }
+  async function reloadVillageInfo() {
+    try {
+      if (!currentVillage.value)
+        return;
+      const res = await LightVillageApi.getVillageDetails(currentVillage.value.id as number);
+      setCurrentVillage(res);
+    } catch (error) {
+      console.error(error);
+      return;
+    }
+  }
   function setCurrentLonlat(lonlat: { longitude: number, latitude: number }) {
   function setCurrentLonlat(lonlat: { longitude: number, latitude: number }) {
     currentLonlat.value = lonlat;
     currentLonlat.value = lonlat;
   }
   }
@@ -34,7 +45,8 @@ export const useVillageStore = defineStore('village', () => {
     const villages = await FollowVillageApi.getFollowVillageList();
     const villages = await FollowVillageApi.getFollowVillageList();
     myFollowVillages.value = villages.list;
     myFollowVillages.value = villages.list;
   }
   }
-  function setMyJoinedVillages(villages: VillageListItem[]) {
+  async function loadMyJoinedVillages() {
+    const villages = await FollowVillageApi.getClaimedVallageList();
     myJoinedVillages.value = villages;
     myJoinedVillages.value = villages;
   }
   }
   function setShareFromVillageUserId(userId: number) {
   function setShareFromVillageUserId(userId: number) {
@@ -49,11 +61,12 @@ export const useVillageStore = defineStore('village', () => {
     myJoinedVillages,
     myJoinedVillages,
     shareFromVillageUserId,
     shareFromVillageUserId,
     loadCurrentVillage,
     loadCurrentVillage,
+    reloadVillageInfo,
     setCurrentVillage,
     setCurrentVillage,
     setCurrentLonlat,
     setCurrentLonlat,
     setCurrentRegion,
     setCurrentRegion,
     loadMyFollowVillages,
     loadMyFollowVillages,
-    setMyJoinedVillages,
+    loadMyJoinedVillages,
     setShareFromVillageUserId,
     setShareFromVillageUserId,
   }
   }
 })
 })