Pārlūkot izejas kodu

📦 对接乡源好物接口

快乐的梦鱼 1 mēnesi atpakaļ
vecāks
revīzija
830089a05a

+ 26 - 19
src/api/inhert/VillageInfoApi.ts

@@ -242,32 +242,39 @@ export class VillageInfoApi extends AppServerRequestModule<DataModel> {
       id,
     }, undefined, modelClassCreator)).data as T
   }
-  async getList<T extends DataModel = CommonInfoModel>(
-    collectModuleId: number|undefined,
-    subId: number|undefined,
-    subKey: string|undefined,
-    villageId: number|undefined,
-    villageVolunteerId: number|undefined,
+  async getList<T extends DataModel = CommonInfoModel>(data: {
+    collectModuleId?: number|undefined,
+    subId?: number|undefined,
+    subKey?: string|undefined,
+    villageId?: number|undefined,
+    villageVolunteerId?: number|undefined,
     catalogId?: number|undefined,
     page?: number,
     pageSize?: number,
     status?: number|undefined,
-    modelClassCreator: (new () => T) = CommonInfoModel as any ,
-  ) {
+    keywords?: string|undefined,
+    modelClassCreator?: (new () => T),
+  }) {
     return (this.post<{
       total: number,
       data: any[],
     }>(`/village/collect/list`, '获取信息详情', {
-      collect_module_id: collectModuleId,
-      [subKey ? subKey : 'type']: subId && subId >= 0 ? subId : undefined,
-      village_id: villageId,
-      village_volunteer_id: villageVolunteerId,
-      catalog_id: catalogId,
-      page,
-      pageSize: pageSize,
-      status,
+      collect_module_id: data.collectModuleId,
+      [data.subKey ? data.subKey : 'type']: data.subId && data.subId >= 0 ? data.subId : undefined,
+      village_id: data.villageId,
+      village_volunteer_id: data.villageVolunteerId,
+      catalog_id: data.catalogId,
+      page: data.page,
+      pageSize: data.pageSize,
+      status: data.status,
+      keywords: data.keywords,
     }))
-      .then(res => transformArrayDataModel<T>(modelClassCreator, res.data?.data ?? [], `获取分类列表`, true))
+      .then(res => {
+        return {
+          total: res.data?.total as number ?? 0,
+          list: transformArrayDataModel<T>(data.modelClassCreator ?? CommonInfoModel, res.data?.data ?? [], `获取分类列表`, true)
+        }
+      })
       .catch(e => { throw e });
   }
 
@@ -313,9 +320,9 @@ export class VillageInfoApi extends AppServerRequestModule<DataModel> {
       collect_module_id: collectModuleId,
       village_id: villageId,
       village_volunteer_id: villageVolunteerId,
-      catalog_id: catalogId,
+      catalog_id: catalogId ? catalogId : undefined,
     };
-    if (subKey)
+    if (subKey && subId && subId > 0)
       res[subKey] = subId;
     return (await this.post(`/village/collect/save`, '通用更新信息详情', res));
   }

+ 2 - 0
src/pages.json

@@ -89,6 +89,7 @@
       "path": "pages/home/village/goods/index",
       "style": {
         "navigationBarTitleText": "乡源好物",
+        "navigationStyle": "custom",
         "enablePullDownRefresh": true
       }
     },
@@ -96,6 +97,7 @@
       "path": "pages/home/village/goods/detail",
       "style": {
         "navigationBarTitleText": "乡源好物详情",
+        "navigationStyle": "custom",
         "enablePullDownRefresh": true
       }
     },

+ 5 - 4
src/pages/dig/admin/preview.vue

@@ -97,10 +97,11 @@ const imageList = computed(() => {
 });
 const overviewLoader = useSimpleDataLoader<CommonInfoModel>(async () => {
   const collectModuleId = CollectableModulesIdMap['overview'];
-  const list = await VillageInfoApi.getList(
-    collectModuleId, undefined, undefined,
-    querys.value.villageId, querys.value.villageVolunteerId
-  );
+  const list = (await VillageInfoApi.getList({
+    collectModuleId,
+    villageId: querys.value.villageId,
+    villageVolunteerId: querys.value.villageVolunteerId,
+  })).list;
 
   if (list.length > 0) {
     const info =  (await VillageInfoApi.getInfo(

+ 10 - 13
src/pages/dig/forms/data/cultural.ts

@@ -35,12 +35,11 @@ export function villageInfoFolkCultureForm(title: string) : SingleForm {
         additionalProps: {
           loadData: {
             callback: (m, r, p, i) => async () => {
-              return (await VillageInfoApi.getList(
-                CollectableModulesIdMap['ich'],
-                undefined, undefined,
-                i.formGlobalParams.villageId,
-                i.formGlobalParams.villageVolunteerId
-              )).map((p) => ({
+              return (await VillageInfoApi.getList({
+                collectModuleId: CollectableModulesIdMap['ich'],
+                villageId: i.formGlobalParams.villageId,
+                villageVolunteerId: i.formGlobalParams.villageVolunteerId
+              })).list.map((p) => ({
                 value: p.id,
                 text: p.title,
               }))
@@ -109,13 +108,11 @@ export const villageInfoCulture : GroupForm = {
             loadData: { 
               callback(_, m, p, i) { 
                 const collectStore = useCollectStore();
-                return async () => (await VillageInfoApi.getList(
-                  CollectableModulesIdMap['speaker'],
-                  undefined, undefined,
-                  i.formGlobalParams.villageId,
-                  i.formGlobalParams.villageVolunteerId
-                ))
-                .map((p) => ({
+                return async () => (await VillageInfoApi.getList({
+                  collectModuleId: CollectableModulesIdMap['speaker'],
+                  villageId: i.formGlobalParams.villageId,
+                  villageVolunteerId: i.formGlobalParams.villageVolunteerId
+                })).list.map((p) => ({
                   value: p.id,
                   text: p.name,
                 }))

+ 70 - 0
src/pages/dig/forms/data/goods.ts

@@ -0,0 +1,70 @@
+import { CommonInfoModel } from '@/api/inhert/VillageInfoApi';
+import type { FieldProps } from '@/components/form/Field.vue';
+import type { SingleForm } from '../forms';
+import { villageCommonContent } from './common';
+
+export const villageInfoGoodsFormItems: SingleForm = [
+  CommonInfoModel,
+  (r) => ({
+    formItems: [
+      {
+        label: '标题',
+        name: 'name',
+        type: 'text',
+        defaultValue: '',
+        additionalProps: {
+          placeholder: '请输入标题',
+        },
+        rules: [{
+          required: true,
+          message: '请输入标题',
+        }],
+      },
+      {
+        label: '价格',
+        name: 'price',
+        type: 'text',
+        defaultValue: '',
+        additionalProps: {
+          placeholder: '请输入价格',
+        },
+        rules: [{
+          required: true,
+          message: '请输入价格',
+        }],
+      },
+      {
+        label: '购买渠道',
+        name: 'channel',
+        type: 'text',
+        defaultValue: '',
+        additionalProps: {
+          placeholder: '请输入购买渠道',
+        },
+      },
+      {
+        label: '联系人',
+        name: 'contact',
+        type: 'text',
+        defaultValue: '',
+        additionalProps: {
+          placeholder: '请输入联系人',
+        },
+      },
+      {
+        label: '联系电话',
+        name: 'contact_number',
+        type: 'text',
+        defaultValue: '',
+        additionalProps: {
+          placeholder: '请输入联系电话',
+        },
+      },
+      ...villageCommonContent(r, {
+        title: '记录',
+        showTitle: false,
+      }).formItems,
+    ],
+  }),
+  { title: '乡源好物', typeName: '' },
+];

+ 6 - 1
src/pages/dig/forms/forms.ts

@@ -18,6 +18,7 @@ import { ichFormItems } from "./data/ich";
 import type { PickerIdFieldProps } from "@/components/dynamic/wrappers/PickerIdField";
 import { villageInfoSpotsFormItems } from "./data/spots";
 import { villageInfoGloryFormItems } from "./data/glory";
+import { villageInfoGoodsFormItems } from "./data/goods";
 
 export type SingleForm = [NewDataModel, (formRef: Ref<IDynamicFormRef>) => IDynamicFormOptions, {
   title: string,
@@ -47,6 +48,7 @@ export const CollectableModulesIdMap : Record<string, number> = {
   'ich': 10,
   'collect': 18,
   'glory': 23,
+  'goods': 24,
 };
 
 /**
@@ -136,6 +138,9 @@ const villageInfoForm : Record<number, GroupForm> = {
   23: {//乡源荣光
     [1]: villageInfoGloryFormItems,
   },
+  24: {//乡源好物
+    [1]: villageInfoGoodsFormItems,
+  },
 }
 
 export function getVillageInfoForm(collectModuleId: number, subId: number) {
@@ -211,4 +216,4 @@ export function mergeFormItems(group: GroupForm) {
   }, info ?? { title: '合并', typeName: '' }]
 
   return result;
-}
+}

+ 59 - 31
src/pages/dig/forms/list-ordinary.vue

@@ -10,10 +10,15 @@
             <SearchBar
               v-model="searchText"
               placeholder="搜一搜" 
-              :innerStyle="{ width: '200rpx' }"
+              :innerStyle="{ width: currentCatalogList.length > 0 ? '200rpx' : '400rpx' }"
               @search="search"
             />
-            <picker @change="handleCatalogChange" :value="currentCatalogIndex" :range="currentCatalogList" range-key="name">
+            <picker 
+              v-if="currentCatalogList.length > 0" 
+              @change="handleCatalogChange" 
+              :value="currentCatalogIndex" 
+              :range="currentCatalogList" range-key="name"
+            >
               <FlexRow center gap="space.md">
                 <Text :text="(currentCatalog?.title || '未选择栏目')" :lines="1" :maxWidth="180" />
                 <Icon icon="arrow-down" :size="40" />
@@ -67,10 +72,7 @@
             </BackgroundBox>
           </FlexCol>
           <template #empty>
-            <Empty image="search" description="这里还没有数据,快来编写完善吧!">
-              <Height :height="40" />
-              <Button type="primary" :text="`+ 新增${subTitle}数据`" @click="newData" />
-            </Empty>
+            <Empty image="search" description="这里还没有数据,快来编写完善吧!" />
           </template>
         </SimplePageListLoader>
       </template>
@@ -129,7 +131,6 @@ const listLoader = useSimplePageListLoader<{
   villageVolunteerId: number,
 }, {
   villageId: number,  
-  villageVolunteerId: number,
   collectModuleId: number,
   subId: number,
   subKey: string,
@@ -141,36 +142,37 @@ const listLoader = useSimplePageListLoader<{
   if (!params.villageId)
     throw new Error("params.villageId");
   let res = [] as CommonInfoModel[];
+  let total = 0;
 
   if (params.collectModuleId === CollectableModulesIdMap['overview']) {
     //村社概览特殊处理
     const info = await VillageInfoApi.getInfoByVillageId(params.villageId);
     const overviewId = info.myOverviewId || info.overviewId;
     if (overviewId) {
-      res = [
+      res = page === 1 ? [
         new CommonInfoModel().setSelfValues({
           id: info.myOverviewId || info.overviewId || 0,
           title: info.title,
           image: info.image,
-          villageVolunteerId: params.villageVolunteerId,
+          villageVolunteerId: volunteerInfo.value?.id || 0,
         }),
-      ];
+      ] : [];
+      total = 1;
     }
   } else {
-    res = await VillageInfoApi.getList(
-      params.collectModuleId,
-      params.subKey ? params.subId : undefined,
-      params.subKey,
-      params.villageId,
-      undefined,
-      currentCatalog.value?.id || 0,
+    const info = (await VillageInfoApi.getList({
+      collectModuleId: params.collectModuleId,
+      subId: params.subKey ? params.subId : undefined,
+      subKey: params.subKey,
+      villageId: params.villageId,
+      catalogId: currentCatalog.value?.id || 0,
       page,
       pageSize,
-    )
+      keywords: searchText.value,
+    }));
+    res = info.list;
+    total = info.total;
   }
-
-  if (searchText.value)
-    res = res.filter((p) => p.title.includes(searchText.value));
   const list = res.map((item) => {
     return {
       id: item.id,
@@ -184,7 +186,7 @@ const listLoader = useSimplePageListLoader<{
   })
   return {
     list: list,
-    total: list.length,
+    total: total,
   };
 }, false);
 
@@ -193,7 +195,7 @@ function newData() {
     confirm({ 
       title: '提示', 
       content: "您还不是当前村社的志愿者,请先加入志愿者队伍", 
-      confirmText: '去点亮',
+      confirmText: '去加入',
     }).then((res) => {
       if (res) {
         goJoin();
@@ -204,7 +206,7 @@ function newData() {
   navTo('common', { 
     id: -1,
     villageId: querys.value.villageId,  
-    villageVolunteerId: querys.value.villageVolunteerId,  
+    villageVolunteerId: volunteerInfo.value?.id || 0,
     catalogId: currentCatalog.value?.id || 0,
     collectModuleId: currentLoadData.value.collectModuleId,  
     subId: currentLoadData.value.subId,  
@@ -242,7 +244,7 @@ function goDetail(item: { id: number, villageVolunteerId: number }) {
     navTo('common', {
       id: item.id,
       villageId: querys.value.villageId,
-      villageVolunteerId: querys.value.villageVolunteerId,
+      villageVolunteerId: volunteerInfo.value?.id || 0,
       catalogId: currentCatalog.value?.id || 0,
       collectModuleId: currentLoadData.value.collectModuleId,
       isView: !canEdit,
@@ -322,11 +324,38 @@ function loadListCatalog(catalog: VillageCatalogListItem) {
   }
   listLoader.load(true, currentLoadData.value)
 }
+function loadListNoCatalog() {
+  try {
+    const formDefine = getVillageInfoForm(querys.value.collectModuleId, -1);
+    const goForm = [ 
+      querys.value.collectModuleId, 
+      -1, 
+      formDefine?.[2].typeName, 
+      querys.value.collectModuleId === CollectableModulesIdMap['overview'] ? 'common' : undefined,
+      querys.value.title,
+      undefined,
+    ] as TaskMenuDefGoForm;
+
+    currentLoadData.value = {
+      collectModuleId: querys.value.collectModuleId,
+      subId: goForm[1],
+      subKey: goForm[2] || 'type',
+      subTitle: goForm[4] || querys.value.title,
+      catalogId: goForm[5] || 0,
+      villageId: querys.value.villageId,
+      villageVolunteerId: volunteerInfo.value?.id || 0,
+    }
+  } catch (e) {
+    console.error(e);
+    error.value = '任务不存在';
+    return;
+  }
+  listLoader.load(true, currentLoadData.value)
+}
 
 const { querys } = useLoadQuerys({ 
   collectModuleId: 0,
   villageId: 0,  
-  villageVolunteerId: 0,
   title: '',
 }, async (querys) => {
   //普通用户进入预览模式
@@ -343,17 +372,16 @@ const { querys } = useLoadQuerys({
   }
   (await VillageApi.getCatalogList(
     querys.villageId, 
-    authStore.isAdmin ? undefined : querys.villageVolunteerId,
+    authStore.isAdmin ? undefined : volunteerInfo.value?.id || 0,
   )).forEach((catalog) => {
     pushCatalogWithCurrentCatalog(catalog);
   });
 
   if (catalogs.value.length === 0) {
-    error.value = `本村暂未开通此栏目 (${querys.collectModuleId})`;
-    return;
+    loadListNoCatalog();
+  } else {
+    loadListCatalog(catalogs.value[0] as VillageCatalogListItem);
   }
-  loadListCatalog(catalogs.value[0] as VillageCatalogListItem);
-
   currentTitle.value = querys.title || '共编村史';
 });
 

+ 10 - 12
src/pages/dig/forms/list.vue

@@ -123,19 +123,17 @@ const listLoader = useSimplePageListLoader<{
     throw new Error("params.collectModuleId");
   if (!params.villageId)
     throw new Error("params.villageId");
-  let res = await VillageInfoApi.getList(
-    params.collectModuleId,
-    params.subKey ? params.subId : undefined,
-    params.subKey,
-    params.villageId,
-    undefined,
-    querys.value.catalogId,
+  let res = (await VillageInfoApi.getList({
+    collectModuleId: params.collectModuleId,
+    subId: params.subKey ? params.subId : undefined,
+    subKey: params.subKey,
+    villageId: params.villageId,
+    catalogId: querys.value.catalogId,
     page,
     pageSize,
-  )
-  if (searchText.value)
-    res = res.filter((p) => p.title.includes(searchText.value));
-  const list = res.map((item) => {
+    keywords: searchText.value,
+  }));
+  const list = res.list.map((item) => {
     return {
       id: item.id,
       image: item.image,
@@ -148,7 +146,7 @@ const listLoader = useSimplePageListLoader<{
   })
   return {
     list: list,
-    total: list.length,
+    total: res.total,
   };
 }, false);
 

+ 8 - 13
src/pages/dig/forms/submits.vue

@@ -131,22 +131,17 @@ const villageListLoader = useSimpleDataLoader(async () => {
 }, true);
 const listLoader = useSimplePageListLoader<CommonInfoModel>(8, async (page, pageSize) => {
   await waitTimeOut(300);
-  let res = await VillageInfoApi.getList(
-    undefined,
-    undefined,
-    undefined,
-    filterVillage.value,
-    querys.value.villageVolunteerId,
-    undefined,
+  const res = await VillageInfoApi.getList({
+    villageId: filterVillage.value,
+    villageVolunteerId: querys.value.villageVolunteerId,
     page,
     pageSize,
-    filterStatus.value === -100 ? undefined : filterStatus.value,
-  )
-  if (searchText.value)
-    res = res.filter((p) => p.title.includes(searchText.value));
+    status: filterStatus.value === -100 ? undefined : filterStatus.value,
+    keywords: searchText.value,
+  })
   return {
-    list: res,
-    total: res.length,
+    list: res.list,
+    total: res.total,
   };
 });
 function goDetail(item: CommonInfoModel) {

+ 1 - 1
src/pages/home/components/NotVolTip.vue

@@ -15,7 +15,7 @@
     />
     <Text fontConfig="lightGoldTitle">您还不是当前村社的志愿者</Text>
     <Text fontConfig="contentSpeicalText">欢迎注册,加入志愿者队伍,点亮村落</Text>
-    <PrimaryButton type="primary" text="去点亮村落" @click="emit('goJoin')" />
+    <PrimaryButton type="primary" text="去加入" @click="emit('goJoin')" />
   </BoxMid>
 </template>
 

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

@@ -403,7 +403,6 @@ async function loadInfo() {
 
 watch(() => authStore.isLogged, async (newVal) => {
   if (newVal) {
-    introClamTipTimeout.reset();
     await loadInfo();
   }
 });

+ 2 - 2
src/pages/home/village/dialogs/IntroClamTip.vue

@@ -12,7 +12,7 @@
         fontConfig="contentSpeicalText" 
       />
       <FlexRow justify="space-around" gap="gap.md">
-        <FrameButton text="随便看看" @click="show = false" width="220rpx" />
+        <FrameButton text="随便看看" @click="show = false; emit('cancel')" width="220rpx" />
         <FrameButton primary text="认领村庄" @click="show = false; emit('apply')" width="220rpx" />
       </FlexRow>
     </FlexCol>
@@ -29,7 +29,7 @@ import FlexRow from '@/components/layout/FlexRow.vue';
 import { ref } from 'vue';
 
 const show = ref(false);
-const emit = defineEmits(['apply']);
+const emit = defineEmits(['apply','cancel']);
 
 defineExpose({
   show: () => {

+ 32 - 26
src/pages/home/village/goods/detail.vue

@@ -1,39 +1,50 @@
 <template>
-  <FlexCol gap="gap.md" padding="padding.md">
+  <CommonTopBanner title="乡源好物详情">
+    <FlexCol gap="gap.md" padding="padding.md">
     <SimplePageContentLoader :loader="goodLoader">
       <template v-if="goodLoader.content.value">
         <BoxMid>
-          <Image :src="goodLoader.content.value.image" :radius="20" width="100%" height="300rpx" mode="aspectFill" />
+          <ImageSwiper 
+            :images="goodLoader.content.value.images"
+            :radius="20" 
+            width="100%" 
+            height="350rpx" 
+            mode="aspectFill" 
+          />
         </BoxMid>
         <BoxMid padding="padding.lg">
           <FlexRow justify="space-between" align="center" gap="gap.md">
             <FlexCol>
-              <Text :text="goodLoader.content.value.name" fontConfig="titleText" />
+              <Text :text="goodLoader.content.value.title" fontConfig="titleText" />
               <Text :text="`出售:${goodLoader.content.value.price}元`" fontConfig="contentText" />
             </FlexCol>
             <FlexRow align="center" gap="gap.md">
               <Avatar 
-                :src="goodLoader.content.value.avatar"
+                :src="goodLoader.content.value.villageVolunteerAvatar"
                 :size="40"
               />
-              <Text :text="`发布人: ${goodLoader.content.value.userName}`" fontConfig="contentText" />
+              <Text :text="`发布人: ${goodLoader.content.value.villageVolunteerName}`" fontConfig="contentText" />
             </FlexRow>
           </FlexRow>
           <Divider />
-          <Text :text="goodLoader.content.value.description" fontConfig="contentText" />
+          <Parse :content="goodLoader.content.value.content" fontConfig="contentText" />
         </BoxMid>
         <Height :height="160" />
-        <PrimaryButton
-          text="去咨询"
-          width="500rpx"
-          @click="handleConsult"
-        />
+        <FlexRow center>
+          <PrimaryButton
+            text="去咨询"
+            width="500rpx"
+            @click="handleConsult"
+          />
+        </FlexRow>
       </template>
     </SimplePageContentLoader>
-  </FlexCol>
+    </FlexCol>
+  </CommonTopBanner>
 </template>
 
 <script setup lang="ts">
+import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
 import { toast } from '@/components/utils/DialogAction';
 import Image from '@/components/basic/Image.vue';
@@ -46,22 +57,17 @@ import Height from '@/components/layout/space/Height.vue';
 import SimplePageContentLoader from '@/components/loader/SimplePageContentLoader.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
 import BoxMid from '@/common/components/box/BoxMid.vue';
+import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
+import VillageInfoApi from '@/api/inhert/VillageInfoApi';
+import Parse from '@/components/display/parse/Parse.vue';
+import ImageSwiper from '@/common/components/parts/ImageSwiper.vue';
+
+const { querys } = useLoadQuerys({
+  id: 0,
+});
 
 const goodLoader = useSimpleDataLoader(async () => {
-  return {
-    id: 1,
-    name: '乡源好物',
-    image: 'https://xy.wenlvti.net/app_static/images/home/games/Games1.png',
-    avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games1.png',
-    userName: '张三',
-    price: 100,
-    originalPrice: 120,
-    description: '产地:个手回匠风造畜,竹音编、钉踏、产地品有桶祖指,唐祖精选了众多好物伤,同防于国美彭柯细匠桶吴订单,规格图至于俗、猛火,贪级传译答于撑精。',
-    content: '乡源好物',
-    tags: ['乡源好物'],
-    comments: ['乡源好物'],
-    likes: ['乡源好物'],
-  };
+  return await VillageInfoApi.getInfoForDiscover(querys.value.id);
 });
 
 

+ 99 - 82
src/pages/home/village/goods/index.vue

@@ -1,44 +1,51 @@
 <template>
-  <FlexCol gap="gap.md" padding="padding.md">
-    <FlexRow justify="space-between" align="center" gap="gap.sm">
-      <SearchBar v-model:value="searchValue" placeholder="搜索乡源好物" :innerStyle="{ width: '440rpx' }" />
-      <FrameButton text="开通微信小店" size="small" />
-    </FlexRow>
-    <Construction text="现在是测试数据,暂无接口" />
-    <FlexRow wrap justify="space-around" gap="gap.sm">
-      <BoxMid
-        v-for="good in goodsLoader.content.value" :key="good.id"
-        :innerStyle="{
-          width: 'calc(50% - 50rpx)',
-        }"
-      >
-        <Touchable direction="column" gap="gap.lg" @click="handleGoodDetail(good)">
-          <Image 
-            :src="good.image"
-            :radius="20"
-            width="100%"
-            height="300rpx"
-            mode="aspectFill"
-          />
-          <FlexRow align="center" gap="gap.md">
-            <Avatar 
-              :src="good.avatar"
-              :size="40"
-            />
-            <Text :text="`发布人: ${good.userName}`" fontConfig="contentText" />
-          </FlexRow>
-        </Touchable>
-      </BoxMid>
-    </FlexRow>
-  </FlexCol>
+  <CommonTopBanner title="乡源好物">
+    <FlexCol gap="gap.md" padding="padding.md">
+      <FlexRow justify="space-between" align="center" gap="gap.sm">
+        <SearchBar v-model:value="searchValue" placeholder="搜索乡源好物" :innerStyle="{ width: '270rpx' }" />
+        <FrameButton text="我要发布" @click="handlePublish" size="small" />
+        <FrameButton text="开通微信小店" size="small" />
+      </FlexRow>
+      <SimplePageListLoader :loader="goodsLoader">
+        <FlexRow wrap justify="space-around" gap="gap.sm">
+          <BoxMid
+            v-for="good in goodsLoader.list.value" :key="good.id"
+            :innerStyle="{
+              width: 'calc(50% - 80rpx)',
+            }"
+          >
+            <Touchable direction="column" gap="gap.lg" @click="handleGoodDetail(good)">
+              <Image 
+                :src="good.image"
+                :radius="20"
+                width="100%"
+                height="300rpx"
+                mode="aspectFill"
+              />
+              <Text :text="good.title" fontConfig="titleText" />
+              <FlexRow align="center" gap="gap.md">
+                <Avatar 
+                  :src="good.villageVolunteerAvatar"
+                  :size="40"
+                />
+                <Text :text="`发布人: ${good.villageVolunteerName}`" fontConfig="contentText" />
+              </FlexRow>
+            </Touchable>
+          </BoxMid>
+          <FlexCol v-if="goodsLoader.list.value.length % 2 !== 0" width="calc(50% - 40rpx)" />
+        </FlexRow>
+      </SimplePageListLoader>
+    </FlexCol>
+  </CommonTopBanner>
 </template>
 
 <script setup lang="ts">
 import { navTo } from '@/components/utils/PageAction';
-import { ref } from 'vue';
-import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
+import { onMounted, ref } from 'vue';
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
+import { useUserTools } from '@/common/composeabe/UserTools';
 import BoxMid from '@/common/components/box/BoxMid.vue';
-import Construction from '@/common/components/Construction.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import Image from '@/components/basic/Image.vue';
 import Text from '@/components/basic/Text.vue';
@@ -47,61 +54,71 @@ import Touchable from '@/components/feedback/Touchable.vue';
 import SearchBar from '@/components/form/SearchBar.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
+import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
+import VillageInfoApi from '@/api/inhert/VillageInfoApi';
+import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
+import { confirm } from '@/components/utils/DialogAction';
 
-const goodsLoader = useSimpleDataLoader(async () => {
-  let games = [
-    {
-      id: 1,
-      name: '知识竞赛',
-      image: 'https://xy.wenlvti.net/app_static/images/home/games/Games1.png',
-      avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games1.png',
-      userName: '张三',
-    },
-    {
-      id: 2,
-      name: '乡源寻美景',
-      image: 'https://xy.wenlvti.net/app_static/images/home/games/Games2.png',
-      avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games2.png',
-      userName: '李四',
-    },
-    {
-      id: 3,
-      name: '农耕小拼图',
-      image: 'https://xy.wenlvti.net/app_static/images/home/games/Games3.png',
-      avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games3.png',
-      userName: '王五',
-    },
-    {
-      id: 4,
-      name: '乡情口令接龙',
-      image: 'https://xy.wenlvti.net/app_static/images/home/games/Games4.png',
-      avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games4.png',
-      userName: '赵六',
-    },
-    {
-      id: 5,
-      name: '农耕小拼图',
-      image: 'https://xy.wenlvti.net/app_static/images/home/games/Games5.png',
-      avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games5.png',
-      userName: '孙七',
-    },
-    {
-      id: 6,
-      name: '乡情口令接龙',
-      image: 'https://xy.wenlvti.net/app_static/images/home/games/Games6.png',
-      avatar: 'https://xy.wenlvti.net/app_static/images/home/games/Games6.png',
-      userName: '周八',
-    },
-  ];
+const { querys } = useLoadQuerys({
+  villageId: 0,
+});
+
+const { getIsVolunteer, getIsJoinedVillage, volunteerInfo } = useUserTools();
+const isJoined = ref(false);
+const CollectModuleId = 24; // 乡源好物模块id
 
-  games = games.concat(games);
-  return games;
+const goodsLoader = useSimplePageListLoader(20, async (page, pageSize, params) => {
+  return await VillageInfoApi.getList({
+    collectModuleId: CollectModuleId,
+    villageId: querys.value.villageId,
+    page, pageSize,
+    keywords: searchValue.value,
+  });
 });
 const searchValue = ref('');
 
+function handleJoin() {
+  navTo('/pages/home/light/submit', {
+    villageId: querys.value.villageId,
+  });
+}
 const handleGoodDetail = (good: { id: number }) => {
   navTo('./detail', {
     id: good.id,
   });
 };
+const handlePublish = () => {
+  if (!isJoined.value) {
+    confirm({ 
+      title: '提示', 
+      content: "您还不是当前村社的志愿者,请先加入志愿者队伍才能采编信息哦", 
+      confirmText: '去加入',
+    }).then((res) => {
+      if (res) {
+        handleJoin();
+      }
+    });
+    return;
+  }
+  navTo('/pages/dig/forms/common', { 
+    id: -1,
+    villageId: querys.value.villageId,  
+    villageVolunteerId: volunteerInfo.value?.id || 0,  
+    collectModuleId: CollectModuleId,  
+    subTitle: '乡源好物',
+  });
+}
+
+onMounted(async () => {
+  await getIsVolunteer();
+  isJoined.value = await getIsJoinedVillage(querys.value.villageId);
+  await goodsLoader.load();
+});
+
+defineExpose({
+  onPageBack(name: string, param: any) {
+    if (param && param.needRefresh)
+      goodsLoader.reload();
+  },
+});
 </script>

+ 1 - 1
src/pages/home/village/introd/card.vue

@@ -196,7 +196,7 @@
     }">
       <Grid :borderGrid="false" :mainAxisCount="4">
         <GridItem title="乡源荣光" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeHornor.png" touchable @click="handleGoCollect(23, '乡源荣光')" />
-        <GridItem title="乡源好物" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeGoods.png" touchable @click="navTo('/pages/home/village/goods/index')" />
+        <GridItem title="乡源好物" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeGoods.png" touchable @click="navTo('/pages/home/village/goods/index', { villageId: villageStore.currentVillage?.id ?? undefined })" />
         <GridItem title="乡源树" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeTree.png" touchable @click="emit('goTree')" />
         <!-- <GridItem title="政贤连心" icon="https://xy.wenlvti.net/app_static/images/village/IconGovAffairs.png" touchable @click="navTo('/pages/home/village/gov/index')" /> -->
         <GridItem title="互动游戏" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeGame.png" touchable @click="navTo('/pages/home/village/games/index')" />

+ 1 - 1
src/pages/index.vue

@@ -155,7 +155,7 @@ onShareTimeline(() => {
 })
 onMounted(() => {
   if (isDevEnv) {
-    //tabIndex.value = 1;
+    tabIndex.value = 1;
   }
 })
 </script>