|
@@ -0,0 +1,369 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <CommonRoot>
|
|
|
|
|
+ <map
|
|
|
|
|
+ id="listMap"
|
|
|
|
|
+ map-id="listMap"
|
|
|
|
|
+ class="list-map"
|
|
|
|
|
+ :longitude="center[0]"
|
|
|
|
|
+ :latitude="center[1]"
|
|
|
|
|
+ :scale="scale"
|
|
|
|
|
+ :markers="markers"
|
|
|
|
|
+ @markertap="onMarkerTap"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <FlexCol position="fixed" :top="0" :left="0" :right="0" :zIndex="1000" backgroundColor="white">
|
|
|
|
|
+ <StatusBarSpace backgroundColor="white" />
|
|
|
|
|
+ <NavBar
|
|
|
|
|
+ leftButton="back"
|
|
|
|
|
+ :title="currentTitle"
|
|
|
|
|
+ :titleStyle="{
|
|
|
|
|
+ fontSize: '40rpx',
|
|
|
|
|
+ fontFamily: 'SongtiSCBlack',
|
|
|
|
|
+ }"
|
|
|
|
|
+ textColor="text.title"
|
|
|
|
|
+ :leftButtonProps="{
|
|
|
|
|
+ buttonStyle: { marginLeft: '20rpx' },
|
|
|
|
|
+ shape: 'round-full',
|
|
|
|
|
+ backgroundColor: 'background.primary',
|
|
|
|
|
+ }"
|
|
|
|
|
+ />
|
|
|
|
|
+ <FlexRow center justify="space-between" gap="space.sm" :padding="[10, 20, 20, 20]">
|
|
|
|
|
+ <FlexRow center gap="space.sm" backgroundColor="background.primary" radius="50" flex="1" :padding="[0, 20, 0, 0]">
|
|
|
|
|
+ <SearchBar
|
|
|
|
|
+ v-model="searchText"
|
|
|
|
|
+ placeholder="搜一搜"
|
|
|
|
|
+ :innerStyle="{ flex: 1 }"
|
|
|
|
|
+ @search="search"
|
|
|
|
|
+ />
|
|
|
|
|
+ <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="140" />
|
|
|
|
|
+ <Icon icon="arrow-down" :size="40" />
|
|
|
|
|
+ </FlexRow>
|
|
|
|
|
+ </picker>
|
|
|
|
|
+ <Width :width="10" />
|
|
|
|
|
+ </FlexRow>
|
|
|
|
|
+ <PrimaryButton
|
|
|
|
|
+ text="+ 编写"
|
|
|
|
|
+ @click="newData"
|
|
|
|
|
+ />
|
|
|
|
|
+ </FlexRow>
|
|
|
|
|
+ </FlexCol>
|
|
|
|
|
+
|
|
|
|
|
+ <FlexCol v-if="mapLoader.error.value" position="fixed" :top="0" :left="0" :right="0" :bottom="0" :zIndex="900" center>
|
|
|
|
|
+ <Result :title="mapLoader.error.value" />
|
|
|
|
|
+ </FlexCol>
|
|
|
|
|
+ </CommonRoot>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { computed, getCurrentInstance, ref, watch } from 'vue';
|
|
|
|
|
+import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
|
|
|
|
|
+import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
|
|
|
|
|
+import { useAuthStore } from '@/store/auth';
|
|
|
|
|
+import { useUserTools } from '@/common/composeabe/UserTools';
|
|
|
|
|
+import { navTo } from '@/components/utils/PageAction';
|
|
|
|
|
+import { confirm } from '@/components/utils/DialogAction';
|
|
|
|
|
+import { getVillageInfoForm } from './forms';
|
|
|
|
|
+import { CollectableModulesIdMap } from "@/common/data/CollectableModulesIdMap";
|
|
|
|
|
+import { type TaskMenuDefGoForm } from './tasks';
|
|
|
|
|
+import VillageInfoApi from '@/api/inhert/VillageInfoApi';
|
|
|
|
|
+import VillageApi, { VillageCatalogListItem } from '@/api/inhert/VillageApi';
|
|
|
|
|
+import { isValidLonLat } from '@/pages/home/composeabe/LonLat';
|
|
|
|
|
+import type { MapMarker } from '@/types/Map';
|
|
|
|
|
+import AppCofig from '@/common/config/AppCofig';
|
|
|
|
|
+import ImagesUrls from '@/common/config/ImagesUrls';
|
|
|
|
|
+import CommonRoot from '@/components/dialog/CommonRoot.vue';
|
|
|
|
|
+import FlexCol from '@/components/layout/FlexCol.vue';
|
|
|
|
|
+import FlexRow from '@/components/layout/FlexRow.vue';
|
|
|
|
|
+import Text from '@/components/basic/Text.vue';
|
|
|
|
|
+import Icon from '@/components/basic/Icon.vue';
|
|
|
|
|
+import Width from '@/components/layout/space/Width.vue';
|
|
|
|
|
+import SearchBar from '@/components/form/SearchBar.vue';
|
|
|
|
|
+import PrimaryButton from '@/common/components/PrimaryButton.vue';
|
|
|
|
|
+import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
|
|
|
|
|
+import NavBar from '@/components/nav/NavBar.vue';
|
|
|
|
|
+import Result from '@/components/feedback/Result.vue';
|
|
|
|
|
+
|
|
|
|
|
+interface MapDataItem {
|
|
|
|
|
+ id: number;
|
|
|
|
|
+ image: string;
|
|
|
|
|
+ title: string;
|
|
|
|
|
+ villageVolunteerId: number;
|
|
|
|
|
+ longitude: number;
|
|
|
|
|
+ latitude: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const instance = getCurrentInstance();
|
|
|
|
|
+const mapCtx = uni.createMapContext('listMap', instance);
|
|
|
|
|
+
|
|
|
|
|
+const subTitle = ref('');
|
|
|
|
|
+const searchText = ref('');
|
|
|
|
|
+const { getIsVolunteer, getCanCollect, getIsManagement, volunteerInfo } = useUserTools();
|
|
|
|
|
+const canCollect = ref(false);
|
|
|
|
|
+const isManagement = ref(false);
|
|
|
|
|
+const authStore = useAuthStore();
|
|
|
|
|
+const error = ref('');
|
|
|
|
|
+
|
|
|
|
|
+const center = ref<[number, number]>([AppCofig.defaultLonLat[0], AppCofig.defaultLonLat[1]]);
|
|
|
|
|
+const scale = ref(12);
|
|
|
|
|
+
|
|
|
|
|
+const mapLoader = useSimpleDataLoader<MapDataItem[]>(async () => {
|
|
|
|
|
+ const params = currentLoadData.value;
|
|
|
|
|
+ if (!params.collectModuleId)
|
|
|
|
|
+ throw new Error("params.collectModuleId");
|
|
|
|
|
+ if (!params.villageId)
|
|
|
|
|
+ throw new Error("params.villageId");
|
|
|
|
|
+ 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: 1,
|
|
|
|
|
+ pageSize: 200,
|
|
|
|
|
+ keywords: searchText.value,
|
|
|
|
|
+ });
|
|
|
|
|
+ return info.list
|
|
|
|
|
+ .map((item) => ({
|
|
|
|
|
+ id: item.id,
|
|
|
|
|
+ image: item.image,
|
|
|
|
|
+ title: item.title,
|
|
|
|
|
+ villageVolunteerId: item.villageVolunteerId,
|
|
|
|
|
+ longitude: Number(item.longitude),
|
|
|
|
|
+ latitude: Number(item.latitude),
|
|
|
|
|
+ }))
|
|
|
|
|
+ .filter((item) => isValidLonLat({ longitude: item.longitude, latitude: item.latitude }));
|
|
|
|
|
+}, false);
|
|
|
|
|
+
|
|
|
|
|
+const markers = computed<MapMarker[]>(() => {
|
|
|
|
|
+ return (mapLoader.content.value || []).map((item) => ({
|
|
|
|
|
+ id: item.id,
|
|
|
|
|
+ title: item.title,
|
|
|
|
|
+ longitude: item.longitude,
|
|
|
|
|
+ latitude: item.latitude,
|
|
|
|
|
+ iconPath: ImagesUrls.IconMarker,
|
|
|
|
|
+ width: 30,
|
|
|
|
|
+ height: 30,
|
|
|
|
|
+ callout: {
|
|
|
|
|
+ display: 'BYCLICK',
|
|
|
|
|
+ content: item.title,
|
|
|
|
|
+ color: '#000000',
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ padding: 5,
|
|
|
|
|
+ bgColor: '#ffffff',
|
|
|
|
|
+ borderRadius: 5,
|
|
|
|
|
+ },
|
|
|
|
|
+ }));
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+watch(markers, () => {
|
|
|
|
|
+ if (markers.value.length === 0) {
|
|
|
|
|
+ center.value = [AppCofig.defaultLonLat[0], AppCofig.defaultLonLat[1]];
|
|
|
|
|
+ scale.value = 12;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ mapCtx.includePoints({
|
|
|
|
|
+ points: markers.value.map((p) => ({
|
|
|
|
|
+ latitude: p.latitude,
|
|
|
|
|
+ longitude: p.longitude,
|
|
|
|
|
+ })),
|
|
|
|
|
+ padding: [40, 40, 40, 40],
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 200);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+function newData() {
|
|
|
|
|
+ if (!canCollect.value) {
|
|
|
|
|
+ confirm({
|
|
|
|
|
+ title: '提示',
|
|
|
|
|
+ content: "您还不是当前村社的志愿者,无法采编信息,请先加入志愿者队伍哦",
|
|
|
|
|
+ confirmText: '去加入',
|
|
|
|
|
+ }).then((res) => {
|
|
|
|
|
+ if (res) {
|
|
|
|
|
+ goJoin();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ navTo('common', {
|
|
|
|
|
+ id: -1,
|
|
|
|
|
+ villageId: querys.value.villageId,
|
|
|
|
|
+ villageVolunteerId: volunteerInfo.value?.id || 0,
|
|
|
|
|
+ catalogId: currentCatalog.value?.id || 0,
|
|
|
|
|
+ collectModuleId: currentLoadData.value.collectModuleId,
|
|
|
|
|
+ subId: currentLoadData.value.subId,
|
|
|
|
|
+ subTitle: currentLoadData.value.subTitle,
|
|
|
|
|
+ subKey: currentLoadData.value.subKey,
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+function goDetail(item: { id: number }) {
|
|
|
|
|
+ navTo('/pages/home/discover/details', {
|
|
|
|
|
+ villageId: querys.value.villageId,
|
|
|
|
|
+ id: item.id,
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+function goEdit(item: { id: number, villageVolunteerId: number }) {
|
|
|
|
|
+ navTo('common', {
|
|
|
|
|
+ id: item.id,
|
|
|
|
|
+ villageId: querys.value.villageId,
|
|
|
|
|
+ villageVolunteerId: item.villageVolunteerId,
|
|
|
|
|
+ catalogId: currentLoadData.value.catalogId,
|
|
|
|
|
+ collectModuleId: querys.value.collectModuleId,
|
|
|
|
|
+ subKey: currentLoadData.value.subKey,
|
|
|
|
|
+ subId: currentLoadData.value.subId,
|
|
|
|
|
+ subTitle: currentLoadData.value.subTitle,
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+function search() {
|
|
|
|
|
+ mapLoader.reload();
|
|
|
|
|
+}
|
|
|
|
|
+function goJoin() {
|
|
|
|
|
+ navTo('/pages/home/light/submit-volunteer', {
|
|
|
|
|
+ villageId: querys.value.villageId,
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+function onMarkerTap(e: any) {
|
|
|
|
|
+ const markerId = e?.markerId ?? e?.detail?.markerId;
|
|
|
|
|
+ const item = mapLoader.content.value?.find((p) => p.id === markerId);
|
|
|
|
|
+ if (item)
|
|
|
|
|
+ goDetail(item);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const currentTitle = ref('');
|
|
|
|
|
+const catalogs = ref<VillageCatalogListItem[]>([]);
|
|
|
|
|
+const currentCatalogIndex = ref(0);
|
|
|
|
|
+const currentCatalogList = computed(() => {
|
|
|
|
|
+ return catalogs.value.map((p) => ({
|
|
|
|
|
+ id: p.id,
|
|
|
|
|
+ name: p.title,
|
|
|
|
|
+ }));
|
|
|
|
|
+});
|
|
|
|
|
+const currentCatalog = ref<VillageCatalogListItem | null>(null);
|
|
|
|
|
+const currentLoadData = ref({
|
|
|
|
|
+ collectModuleId: 0,
|
|
|
|
|
+ subId: 0,
|
|
|
|
|
+ subKey: '',
|
|
|
|
|
+ subTitle: '',
|
|
|
|
|
+ catalogId: 0 as number|undefined,
|
|
|
|
|
+ villageId: 0,
|
|
|
|
|
+ villageVolunteerId: 0,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+function handleCatalogChange(e: any) {
|
|
|
|
|
+ currentCatalogIndex.value = e.detail.value;
|
|
|
|
|
+ loadListCatalog(catalogs.value[currentCatalogIndex.value] as VillageCatalogListItem);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function loadListCatalog(catalog: VillageCatalogListItem) {
|
|
|
|
|
+ if (currentCatalog.value?.id === catalog.id)
|
|
|
|
|
+ return;
|
|
|
|
|
+ currentCatalog.value = catalog;
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (catalog.id === 0) {
|
|
|
|
|
+ currentLoadData.value = {
|
|
|
|
|
+ collectModuleId: querys.value.collectModuleId,
|
|
|
|
|
+ subId: -1,
|
|
|
|
|
+ subKey: 'type',
|
|
|
|
|
+ subTitle: querys.value.title,
|
|
|
|
|
+ catalogId: undefined,
|
|
|
|
|
+ villageId: querys.value.villageId,
|
|
|
|
|
+ villageVolunteerId: volunteerInfo.value?.id || 0,
|
|
|
|
|
+ }
|
|
|
|
|
+ mapLoader.load(true)
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const formDefine = getVillageInfoForm(querys.value.collectModuleId, -1);
|
|
|
|
|
+ const goForm = [
|
|
|
|
|
+ querys.value.collectModuleId,
|
|
|
|
|
+ catalog.typeId ?? -1,
|
|
|
|
|
+ formDefine?.[2].typeName,
|
|
|
|
|
+ querys.value.collectModuleId === CollectableModulesIdMap['overview'] ? 'common' : undefined,
|
|
|
|
|
+ catalog.title,
|
|
|
|
|
+ catalog.id
|
|
|
|
|
+ ] 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;
|
|
|
|
|
+ }
|
|
|
|
|
+ mapLoader.load(true)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function loadVolunteerInfo() {
|
|
|
|
|
+ isManagement.value = await getIsManagement(querys.value.villageId);
|
|
|
|
|
+ try {
|
|
|
|
|
+ //普通用户进入预览模式
|
|
|
|
|
+ await getIsVolunteer();
|
|
|
|
|
+ canCollect.value = await getCanCollect(querys.value.villageId);
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ canCollect.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const { querys } = useLoadQuerys({
|
|
|
|
|
+ collectModuleId: 0,
|
|
|
|
|
+ villageId: 0,
|
|
|
|
|
+ title: '',
|
|
|
|
|
+}, async (querys) => {
|
|
|
|
|
+ await loadVolunteerInfo();
|
|
|
|
|
+
|
|
|
|
|
+ function pushCatalogWithCurrentCatalog(catalog: VillageCatalogListItem) {
|
|
|
|
|
+ if (catalog.collectModuleId === querys.collectModuleId) {
|
|
|
|
|
+ catalogs.value.push(catalog);
|
|
|
|
|
+ }
|
|
|
|
|
+ catalog.childlist.forEach((c) => {
|
|
|
|
|
+ pushCatalogWithCurrentCatalog(c);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ (await VillageApi.getCatalogList(
|
|
|
|
|
+ querys.villageId,
|
|
|
|
|
+ authStore.isAdmin || isManagement.value ? undefined : volunteerInfo.value?.id || 0,
|
|
|
|
|
+ )).forEach((catalog) => {
|
|
|
|
|
+ pushCatalogWithCurrentCatalog(catalog);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ catalogs.value.unshift(new VillageCatalogListItem().setSelfValues({
|
|
|
|
|
+ id: 0,
|
|
|
|
|
+ title: '全部',
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ loadListCatalog(catalogs.value[0] as VillageCatalogListItem);
|
|
|
|
|
+ currentTitle.value = querys.title || '共编村史';
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+defineExpose({
|
|
|
|
|
+ onPageBack(name: string, param: any) {
|
|
|
|
|
+ if (param && param.needRefresh)
|
|
|
|
|
+ mapLoader.reload();
|
|
|
|
|
+ if (name === 'registerDone')
|
|
|
|
|
+ loadVolunteerInfo();
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.list-map {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100vw;
|
|
|
|
|
+ height: 100vh;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|