瀏覽代碼

📦 文化地图页面

imengyu 1 月之前
父節點
當前提交
8effbc62a1

+ 10 - 0
src/api/inheritor/SeminarContent.ts

@@ -0,0 +1,10 @@
+import { CommonContentApi } from '../CommonContent';
+
+export class SeminarContentApi extends CommonContentApi {
+
+  constructor() {
+    super(undefined, 17, "非遗保护名录-非遗传习中心(所)", 221);
+  }
+}
+
+export default new SeminarContentApi();

+ 7 - 0
src/common/composeabe/SimpleDataLoader.ts

@@ -10,6 +10,7 @@ export function useSimpleDataLoader<T, P = any>(
   loader: (params?: P) => Promise<T>,
   loadWhenMounted = true,
   emptyIfArrayEmpty = true,
+  showGlobalLoading = false,
 )  : ISimpleDataLoader<T, P>
  {
 
@@ -23,6 +24,9 @@ export function useSimpleDataLoader<T, P = any>(
     if (params)
       lastParams = params;
     loadStatus.value = 'loading';
+    if (showGlobalLoading)
+      uni.showLoading({ title: '加载中...' });
+
     try {
       const res = (await loader(params ?? lastParams)) as T;
       content.value = res;
@@ -36,6 +40,9 @@ export function useSimpleDataLoader<T, P = any>(
       loadStatus.value = 'error';
       console.log(e);
       
+    } finally {
+      if (showGlobalLoading)
+        uni.hideLoading();
     }
   }
 

+ 8 - 1
src/common/composeabe/SimplePageListLoader.ts

@@ -9,7 +9,9 @@ export interface ISimplePageListLoader<T, P> extends ILoaderCommon<P> {
 
 export function useSimplePageListLoader<T, P = any>(
   pageSize: number, 
-  loader: (page: number, pageSize: number, params?: P) => Promise<T[]>)  : ISimplePageListLoader<T, P>
+  loader: (page: number, pageSize: number, params?: P) => Promise<T[]>,
+  showGlobalLoading = false,
+)  : ISimplePageListLoader<T, P>
 {
   
   const loadStatus = ref<LoaderLoadType>('loading');
@@ -32,6 +34,8 @@ export function useSimplePageListLoader<T, P = any>(
     page.value++;
     loadStatus.value = 'loading';
     loading = true;
+    if (showGlobalLoading)
+      uni.showLoading({ title: '加载中...' });
 
     try {
       const res = (await loader(page.value, pageSize, lastParams)) as T[];
@@ -44,6 +48,9 @@ export function useSimplePageListLoader<T, P = any>(
       loadError.value = '' + e;
       loadStatus.value = 'error';
       loading = false;
+    } finally {
+      if (showGlobalLoading)
+        uni.hideLoading();
     }
   }
 

+ 6 - 0
src/pages.json

@@ -96,6 +96,12 @@
       }
     },
     {
+      "path": "pages/inhert/map/index",
+      "style": {
+        "navigationBarTitleText": "文化地图"
+      }
+    },
+    {
       "path": "pages/inhert/village/list",
       "style": {
         "navigationBarTitleText": "村落列表"

+ 48 - 7
src/pages/home.vue

@@ -59,20 +59,22 @@
       <HomeTitle title="文化地图" />
       <view class="position-relative radius-l overflow-hidden">
         <map 
+          id="map"
           class="w-100 height-400"
+          :markers="mapLoader.content.value || []"
+          :enable-zoom="false"
+          :enable-scroll="false"
+          :scale="15"
+          @click="navTo('inhert/map/index')"
         />
         <view class="position-absolute map-tags d-flex flex-row">
-          <view class="active">
+          <view :class="mapTab == 1 ? 'active' : ''" @click="mapTab=1">
             <text class="iconfont icon-read" />
             文物
           </view>
-          <view>
+          <view :class="mapTab == 2 ? 'active' : ''" @click="mapTab=2">
             <text class="iconfont icon-task-trip" />
-            非遗
-          </view>
-          <view>
-            <text class="iconfont icon-tougao-01" />
-            传习所
+            非遗传习所
           </view>
         </view>
       </view>
@@ -157,6 +159,9 @@ import SimplePageContentLoader from "@/common/components/SimplePageContentLoader
 import { navTo } from '@/common/utils/PageAction';
 import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
 import CommonContent, { GetContentListParams } from '@/api/CommonContent';
+import { ref, watch } from 'vue';
+import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
+import SeminarContent from '@/api/inheritor/SeminarContent';
 
 const subTabs1 = [
   { 
@@ -229,6 +234,42 @@ const subTabs2 = [
   },
 ]
 
+const mapCtx = uni.createMapContext('map');
+const mapTab = ref(1);
+const mapLoader = useSimpleDataLoader(async () => {
+  let list ;
+  switch (mapTab.value) {
+    default:
+    case 1:
+      list = (await UnmoveableContent.getContentList(new GetContentListParams(), 1, 6)).list
+      break;
+    case 2:
+      list = (await SeminarContent.getContentList(new GetContentListParams(), 1, 6)).list
+      break;
+  }  
+  const res = list.map((p) => {
+    return {
+      ...p,
+      id: p.id,
+      longitude: Number(p.longitude),
+      latitude: Number(p.latitude),
+      iconPath: p.thumbnail,
+      width: 40,
+      height: 40,
+    };
+  });
+  mapCtx.includePoints({
+    points: res.map(p => ({
+      latitude: p.latitude,
+      longitude: p.longitude,
+    })),
+    padding: [20, 20, 20, 20],
+  });
+  return res;
+}, true, undefined, true);
+
+watch(mapTab, () => mapLoader.loadData(undefined, true));
+
 const activityLoader = useSimpleDataLoader(async () => {
   //TODO: 活动接口
   return [

+ 133 - 0
src/pages/inhert/map/index.vue

@@ -0,0 +1,133 @@
+<template>
+  <view class="d-flex flex-col bg-base">
+    <view class="d-flex flex-col p-2">
+      <uni-search-bar 
+        v-model="searchValue"
+        radius="100" 
+        bgColor="#fff" 
+        placeholder="搜索文物" 
+        clearButton="auto" 
+        cancelButton="none"
+        @confirm="doSearch"
+      />
+    </view>
+    <view class="d-flex flex-row justify-around p-2 pt-0">
+      <SimpleDropDownPicker v-model="selectedTag" :columns="categoryData.content.value" />
+      <SimpleDropDownPicker v-model="selectedLevel" :columns="levelData.content.value" />
+      <SimpleDropDownPicker v-model="selectedRegion" :columns="regionData.content.value" />
+    </view>
+    <view class="d-flex flex-row flex-wrap justify-between">
+      <map 
+        id="map"
+        class="w-100 h-100vh"
+        :markers="listLoader.list.value || []"
+        :scale="15"
+        @markertap="onMarkerTap"
+      />
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, watch } from 'vue';
+import CommonContent, { GetContentListParams } from '@/api/CommonContent';
+import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
+import { navTo } from '@/common/utils/PageAction';
+import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
+import SimpleDropDownPicker from '@/common/components/SimpleDropDownPicker.vue';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+
+const mapCtx = uni.createMapContext('map');
+const categoryData = useSimpleDataLoader(async () => 
+  [{
+    id: 0, 
+    name: '全部分类'
+  }].concat((await CommonContent.getCategoryList(3)).map((item) => ({
+    id: item.id,
+    name: item.title,
+  })))
+, true);
+const levelData = useSimpleDataLoader(async () => 
+  [{
+    id: 0, 
+    name: '全部级别'
+  }].concat((await CommonContent.getCategoryList(2)).map((item) => ({
+    id: item.id,
+    name: item.title,
+  })))
+, true);
+const regionData = useSimpleDataLoader(async () => 
+  [{
+    id: 0, 
+    name: '全部区域'
+  }].concat((await CommonContent.getCategoryList(1)).map((item) => ({
+    id: item.id,
+    name: item.title,
+  })))
+, true);
+const selectedTag = ref(0);
+const selectedLevel = ref(0);
+const selectedRegion = ref(0);
+const searchValue = ref('');
+const listLoader = useSimplePageListLoader(8, async (page, pageSize) => {
+  const res = (await UnmoveableContent.getContentList(new GetContentListParams().setSelfValues({
+    crType: selectedTag.value == 0 ? undefined: selectedTag.value,
+    level: selectedLevel.value == 0 ? undefined: selectedLevel.value,
+    region: selectedRegion.value == 0 ? undefined: selectedRegion.value,
+    keywords: searchValue.value,
+  }), page, pageSize)).list.map((p) => {
+    return {
+      ...p,
+      id: p.id,
+      longitude: Number(p.longitude),
+      latitude: Number(p.latitude),
+      iconPath: p.thumbnail,
+      width: 40,
+      height: 40,
+      callout: {
+        content: p.title,
+        color: "#ffffff",
+        fontSize: 15,
+        borderRadius: 15,
+        padding: "10",
+        bgColor: "#d9492e",
+        display: "ALWAYS",
+      },
+    }
+  })
+  
+  mapCtx.includePoints({
+    points: res.map(p => ({
+      latitude: p.latitude,
+      longitude: p.longitude,
+    })),
+    padding: [20, 20, 20, 20],
+  });
+
+  return res;
+}, true);
+
+watch(selectedLevel, () => {
+  listLoader.loadData(undefined, true);
+});
+watch(selectedRegion, () => {
+  listLoader.loadData(undefined, true);
+});
+watch(selectedTag, () => {
+  listLoader.loadData(undefined, true);
+});
+
+onMounted(() => {
+  listLoader.loadData(undefined, true);
+})
+
+function doSearch() {
+  listLoader.loadData(undefined, true);
+}
+function onMarkerTap(e: { markerId: number }) {
+  goDetails(e.markerId);
+}
+function goDetails(id: number) {
+  navTo('/pages/inhert/artifact/details', { id })
+}
+</script>