소스 검색

📦 对接新地图接口

快乐的梦鱼 20 시간 전
부모
커밋
f1785ba255
5개의 변경된 파일156개의 추가작업 그리고 45개의 파일을 삭제
  1. 28 12
      src/api/light/LightVillageApi.ts
  2. 33 18
      src/pages/home/components/LightMap.vue
  3. 18 2
      src/pages/home/index.vue
  4. 59 13
      src/pages/home/light/create-village.vue
  5. 18 0
      src/pages/home/light/submit-map.vue

+ 28 - 12
src/api/light/LightVillageApi.ts

@@ -277,6 +277,31 @@ export interface VillageTreeAnimProps {
   }>,
 }
 
+export class VillageMapItem extends DataModel<VillageMapItem> {
+  constructor() {
+    super(VillageMapItem, "村社地图");
+    this.setNameMapperCase('Camel', 'Snake');
+    this._convertTable = {
+      villageId: { clientSide: 'number' },
+      isLight: { clientSide: 'boolean' },
+      latitude: { clientSide: 'number' },
+      longitude: { clientSide: 'number' },
+    };
+  }
+
+
+  villageId!: number|null;
+  villageName = '';
+  isLight = false;
+  areaId = 0;
+  areaCode = 0;
+  mergerName = '';
+  longitude = 0;
+  latitude = 0;
+  lightValue = 0;
+  name = '';
+}
+
 export class LightVillageApi extends AppServerRequestModule<DataModel> {
 
   constructor() {
@@ -408,6 +433,7 @@ export class LightVillageApi extends AppServerRequestModule<DataModel> {
     name: string,
     longitude: string,
     latitude: string,
+    desc: string,
     area_code: number,
     /**
      * 村落类型:
@@ -428,20 +454,10 @@ export class LightVillageApi extends AppServerRequestModule<DataModel> {
     /** 地区code */
     areaCode: number;
   }) {
-    const res = await this.post<{
-      village_id: number | null;
-      is_light: number | null;
-      village_name: string | null;
-      area_id: number;
-      area_code: number;
-      merger_name: string;
-      longitude: string;
-      latitude: string;
-      name: string;
-    }[]>('/village/village/mapVillage', '村社地图', {
+    const res = await this.post<KeyValue[]>('/village/village/mapVillage', '村社地图', {
       area_code: params.areaCode,
     });
-    return res.requireData();
+    return transformArrayDataModel<VillageMapItem>(VillageMapItem, res.requireData(), '村社地图条目', true);
   }
 
   async updateStorage(params: {

+ 33 - 18
src/pages/home/components/LightMap.vue

@@ -96,10 +96,10 @@
 
 <script setup lang="ts">
 import { getCurrentInstance, onMounted, ref, watch } from 'vue';
-import { waitTimeOut } from '@imengyu/imengyu-utils';
+import { assertNotNull, waitTimeOut } from '@imengyu/imengyu-utils';
 import { toast } from '@/components/dialog/CommonRoot';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
-import LightVillageApi, { VillageListItem } from '@/api/light/LightVillageApi';
+import LightVillageApi, { VillageListItem, type VillageMapItem } from '@/api/light/LightVillageApi';
 import AppCofig from '@/common/config/AppCofig';
 import SimpleDropDownPicker from '@/common/components/SimpleDropDownPicker.vue';
 import NButton from '@/components/basic/Button.vue';
@@ -113,12 +113,14 @@ import FlexRow from '@/components/layout/FlexRow.vue';
 import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
 import RegionApi from '@/api/map/RegionApi';
 import type { MapMarker } from '@/types/Map';
+import { hideLoading, loading } from '@/components/utils/DialogAction';
+import { showError } from '@/common/composeabe/ErrorDisplay';
 
 const instance = getCurrentInstance();
 const mapCtx = uni.createMapContext('prevMap', instance);
 
 const selectedRegion = ref<number>();
-const villageData = new Map<number, VillageListItem>();
+const villageData = new Map<number, VillageMapItem>();
 
 const ready = ref(false);
 const hasResItems = ref(false);
@@ -134,6 +136,7 @@ const emit = defineEmits([
   'selectVillage',
   'regionChanged',
   'lightVillage',
+  'createVillage',
   'changeCity',
 ]);
 
@@ -166,18 +169,19 @@ const mapLoader = useSimpleDataLoader<MapMarker[]>(async () => {
   if (!selectedRegion.value)
     return [];
   await waitTimeOut(100);
-  const res = (await LightVillageApi.getVillageList({
+  let res = (await LightVillageApi.getMapVillage({
     areaCode: selectedRegion.value,
-    keyword: searchKeyword.value.trim() || undefined,
-    page: 1,
-    pageSize: 1000
-  })).list;
+  }));
+  if (searchKeyword.value) {
+    res = res.filter(p => p.villageName.includes(searchKeyword.value));
+  }
   //如果为空则尝试获取子级
   hasResItems.value = res.length > 0;
   const list = res.map((p, i) => {
-    villageData.set(p.id, p);
+    const id = p.villageId ?? i;
+    villageData.set(id, p);
     const maker : MapMarker = {
-      id: p.id ?? i,
+      id,
       title: p.name,
       longitude: Number(p.longitude),
       latitude: Number(p.latitude),
@@ -285,18 +289,29 @@ async function asyncAddMarkers(list: MapMarker[]) {
   }
 }
 
-function onMarkerTap(e: any) {
-  if (props.isLightMode) {
-    emit('update:isLightMode', false);
-    const village = villageData.get(e.markerId);
-    if (village) {
+async function onMarkerTap(e: any) {
+  try {
+    loading();
+    const villageMapInfo = villageData.get(e.markerId);
+    assertNotNull(villageMapInfo, 'markerId错误');
+    if (!villageMapInfo.villageId) {
+      emit('createVillage', villageMapInfo);
+      return;
+    }
+    const village = await LightVillageApi.getVillageDetails(villageMapInfo.villageId);
+    assertNotNull(village, '获取村社详情失败');
+
+    if (props.isLightMode) {
+      emit('update:isLightMode', false);
       emit('lightVillage', village);
       return;
     }
-  }
-  const village = villageData.get(e.markerId);
-  if (village) {
+
     emit('selectVillage', village);
+  } catch (error) {
+    showError(error);
+  } finally {
+    hideLoading();
   }
 }
 function onSelectedRegion(regionId: number) {

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

@@ -63,6 +63,7 @@
         v-model:district="currentDistrict"
         :lonlat="currentLocation.currentLonlat.value"
         @getCurrentLonlat="currentLocation.getCurrentExactLocation"
+        @createVillage="handleGoCreateVillage"
         @selectVillage="handleGoVillageDetails"
         @changeCity="showCityPopup=true"
       >
@@ -219,7 +220,7 @@ import { useUserTools } from '@/common/composeabe/UserTools';
 import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
 import { useGetNotice } from './village/composeabe/GetNotice';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
-import { toast, loading, hideLoading } from '@/components/utils/DialogAction';
+import { toast, loading, hideLoading, confirm } from '@/components/utils/DialogAction';
 import { navTo } from '@/components/utils/PageAction';
 import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
 import Image from '@/components/basic/Image.vue';
@@ -237,7 +238,7 @@ import VillageMyFollow from './components/VillageMyFollow.vue';
 import LightMap from './components/LightMap.vue';
 import NoticeBar from '@/components/display/NoticeBar.vue';
 import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
-import LightVillageApi, { VillageListItem } from '@/api/light/LightVillageApi';
+import LightVillageApi, { VillageListItem, type VillageMapItem } from '@/api/light/LightVillageApi';
 import Width from '@/components/layout/space/Width.vue';
 import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
 import IntroClamTip from './village/dialogs/IntroClamTip.vue';
@@ -334,6 +335,21 @@ async function handleGoVillageDetails(item: VillageListItem) {
   await waitTimeOut(100);
   emit('goVillage')
 }
+async function handleGoCreateVillage(item: VillageMapItem) {
+  const con = await confirm({
+    title: '提示',
+    content: '您选择的村社尚未建村,是否去一键建村?',
+    confirmText: '去建村',
+  });
+  if (con) {
+    navTo('/pages/home/light/create-village', {
+      villageName: item.name,
+      areaCode: item.areaCode,
+      longitude: item.longitude,
+      latitude: item.latitude,
+    });
+  }
+}
 function handleSelectCity(city: RegionItem) {
   currentCity.value = city.name;
   currentCityCode.value = city.areaCode;

+ 59 - 13
src/pages/home/light/create-village.vue

@@ -20,6 +20,14 @@
           <Text>请输入家乡名称,然后选择地图位置定位哦</Text>
         </FlexRow>
         <Field v-model="currentVillageName" placeholder="请输入家乡名称,例如:大庆村" />
+        <Field 
+          v-model="currentVillageDesc" 
+          placeholder="输入家乡的介绍,可以让大家了解更多" 
+          multiline 
+          showWordLimit 
+          :maxLength="300" 
+          :inputStyle="{ height: '100px' }"
+        />
         <Field label="类型" placeholder="请选择村社类型">
           <FlexRow>
             <RadioGroup v-model="currentVillageType">
@@ -52,7 +60,7 @@
             :enable-satellite="enableSatellite"
             :style="{
               width: '100%',
-              height: '500px',
+              height: '340px',
             }"
             @regionchange="handleRegionchange"
           >
@@ -62,7 +70,7 @@
           <Button :text="'切换' + (enableSatellite ? '地图' : '卫星')" @click="enableSatellite = !enableSatellite" />
         </FlexRow>
         <FlexCol gap="gap.md">
-          <Button text="返回上一步" @click="step = 'selectArea'" />
+          <Button text="返回上一步" @click="handleBack" />
           <Button text="立即建村" type="primary" @click="handleConfirm()" />
         </FlexCol>
       </template>
@@ -109,7 +117,7 @@ import Text from '@/components/basic/Text.vue';
 import Button from '@/components/basic/Button.vue';
 import Field from '@/components/form/Field.vue';
 import LightVillageApi, { type VillageListItem } from '@/api/light/LightVillageApi';
-import { backAndCallOnPageBack } from '@/components/utils/PageAction';
+import { back, backAndCallOnPageBack } from '@/components/utils/PageAction';
 import RadioGroup from '@/components/form/RadioGroup.vue';
 import Radio from '@/components/form/Radio.vue';
 import CommonDialog from '@/common/components/CommonDialog.vue';
@@ -118,14 +126,45 @@ import Touchable from '@/components/feedback/Touchable.vue';
 import Image from '@/components/basic/Image.vue';
 import { getCascaderItemByValue } from '@/components/form/CascaderUtils';
 import { isValidLonLat } from '../composeabe/LonLat';
+import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
+
+const { querys } = useLoadQuerys({
+  villageName: '',
+  areaCode: 0,
+  longitude: 0,
+  latitude: 0,
+}, (query) => {
+  if (query.villageName && query.areaCode) {
+    
+    step.value = 'inputInfo';
+    currentVillageName.value = query.villageName;
+    currentAreaCode.value = query.areaCode;
+    currentFromPreData.value = true;
+
+    if (!isValidLonLat(query)) {
+      alert({
+        title: '提示',
+        content: '您的家乡暂时没有经纬度信息,麻烦您拖动地图至您的家乡准确位置',
+        confirmText: '好',
+      })
+    } else {
+      mapCtx.moveToLocation({
+        longitude: Number(query.longitude),
+        latitude: Number(query.latitude),
+      });
+    }
+  }
+});
 
 const mapCtx = uni.createMapContext('prevMap');
 
 const step = ref<'selectArea'|'inputInfo'>('selectArea');
-const selectedRegion = ref<RegionItem>();
+const currentFromPreData = ref(false);
 const currentLonLat = ref({ longitude: 0, latitude: 0 });
 const currentVillageName = ref('')
+const currentVillageDesc = ref('')
 const currentVillageType = ref<number>(95);
+const currentAreaCode = ref(0);
 
 const showSearchedList = ref(false);
 const searchedList = ref<VillageListItem[]>([]);
@@ -147,6 +186,13 @@ function getReSelectAddress() {
   };
 }
 
+function handleBack() {
+  if (currentFromPreData.value) {
+    back();
+  } else {
+    step.value = 'selectArea';
+  }
+}
 async function asyncLoadData(item: CascaderItem) {
   const list = await RegionApi.getChildList(Number(item.value));
   return list.map(region => ({
@@ -157,7 +203,6 @@ async function asyncLoadData(item: CascaderItem) {
 }
 async function handlePickEnd(values: CascaderItem[]) {
   if (values.length > 0) {
-    selectedRegion.value = values[values.length - 1].data;
     let i = values.length - 1;
     for (; i >= 0; i--) {
       const lonlat = {
@@ -170,16 +215,16 @@ async function handlePickEnd(values: CascaderItem[]) {
       }
     }
 
-    const areaCode = Number(selectedValue.value[selectedValue.value.length - 1]);
+    currentAreaCode.value = Number(selectedValue.value[selectedValue.value.length - 1]);
     try {
-      const mapVillages = await LightVillageApi.getMapVillage({ areaCode });
-      const existingVillages = mapVillages.filter(v => v.village_id !== null);
+      const mapVillages = await LightVillageApi.getMapVillage({ areaCode: currentAreaCode.value });
+      const existingVillages = mapVillages.filter(v => v.villageId !== null);
       if (existingVillages.length > 0) {
         searchedList.value = existingVillages.map(v => ({
-          id: v.village_id!,
-          name: v.village_name || v.name,
+          id: v.villageId!,
+          name: v.villageName || v.name,
           image: '',
-          address: v.merger_name?.replace(/,/g, '') || '',
+          address: v.mergerName?.replace(/,/g, '') || '',
         }) as unknown as VillageListItem);
         showSearchedList.value = true;
         return;
@@ -220,7 +265,7 @@ async function handleConfirm(skipSearch?: boolean) {
     //先尝试搜索已有村社 
     if (!skipSearch) {
       const searchRes = (await LightVillageApi.getVillageList({
-        areaCode: selectedValue.value[2] as number,
+        areaCode: currentAreaCode.value,
         keyword: currentVillageName.value.trim() || undefined,
         page: 1,
         pageSize: 10
@@ -236,9 +281,10 @@ async function handleConfirm(skipSearch?: boolean) {
     //否则添加村社
     const res = (await LightVillageApi.createVillage({ 
       name: currentVillageName.value,
+      desc: currentVillageDesc.value,
       longitude: String(currentLonLat.value.longitude),
       latitude: String(currentLonLat.value.latitude),
-      area_code: selectedValue.value[selectedValue.value.length - 1] as number,
+      area_code: currentAreaCode.value,
       village_type: currentVillageType.value,
     })).data;
 

+ 18 - 0
src/pages/home/light/submit-map.vue

@@ -17,6 +17,8 @@ import CitySelect from '../components/CitySelect.vue';
 import Popup from '@/components/dialog/Popup.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import type { RegionItem } from '@/api/map/RegionApi';
+import type { VillageMapItem } from '@/api/light/LightVillageApi';
+import { confirm } from '@/components/utils/DialogAction';
 
 const { querys } = useLoadQuerys({
   latitude: AppCofig.defaultLonLat[1],
@@ -42,6 +44,21 @@ function handleLightVillage(villageId: number) {
   joinCurrentVillageId.value = villageId;
   joinDialog.value?.show();
 }
+async function handleCreateVillage(item: VillageMapItem) {
+  const con = await confirm({
+    title: '提示',
+    content: '您选择的村社尚未建村,是否去一键建村?',
+    confirmText: '去建村',
+  });
+  if (con) {
+    navTo('/pages/home/light/create-village', {
+      villageName: item.name,
+      areaCode: item.areaCode,
+      longitude: item.longitude,
+      latitude: item.latitude,
+    });
+  }
+}
 function handleJoinFinish() { 
   backAndCallOnPageBack('goVillage', { id: joinCurrentVillageId.value });
   joinCurrentVillageId.value = 0;
@@ -134,6 +151,7 @@ defineExpose({
     :lonlat="currentLocation.currentLonlat.value"
     :isLightMode="true" 
     @lightVillage="handleLightVillage"
+    @createVillage="handleCreateVillage"
     @getCurrentLonlat="currentLocation.getCurrentExactLocation"
     @changeCity="showCityPopup=true"
   />