Forráskód Böngészése

🎨 修改细节问题

快乐的梦鱼 1 hete
szülő
commit
b520c265ce

+ 4 - 4
package-lock.json

@@ -24,7 +24,7 @@
         "@dcloudio/uni-mp-weixin": "3.0.0-4080720251210001",
         "@dcloudio/uni-mp-xhs": "3.0.0-4080720251210001",
         "@dcloudio/uni-quickapp-webview": "3.0.0-4080720251210001",
-        "@imengyu/imengyu-utils": "^0.0.24",
+        "@imengyu/imengyu-utils": "^0.0.26",
         "@imengyu/js-request-transform": "^0.3.7",
         "async-validator": "^4.2.5",
         "pinia": "^3.0.1",
@@ -3596,9 +3596,9 @@
       }
     },
     "node_modules/@imengyu/imengyu-utils": {
-      "version": "0.0.24",
-      "resolved": "https://registry.npmmirror.com/@imengyu/imengyu-utils/-/imengyu-utils-0.0.24.tgz",
-      "integrity": "sha512-IFlN6DUmSqrD1pUQ8jhU98FV+0woS8fxJ0fR0f8cwDgh2AW7eIrYtDKZ6ouC8r6ytWncHkwRDQrfwBTiS0NR0g==",
+      "version": "0.0.26",
+      "resolved": "https://registry.npmmirror.com/@imengyu/imengyu-utils/-/imengyu-utils-0.0.26.tgz",
+      "integrity": "sha512-cveTHptpu5ISLgIBroY/Ke+YZOE2lwybfq0HdPVx+vvttMzEhSkejesYTWF2FKY+5hOwYmWmOglutS143DUBFA==",
       "license": "MIT",
       "dependencies": {
         "@imengyu/js-request-transform": "^0.3.6"

+ 1 - 1
package.json

@@ -51,7 +51,7 @@
     "@dcloudio/uni-mp-weixin": "3.0.0-4080720251210001",
     "@dcloudio/uni-mp-xhs": "3.0.0-4080720251210001",
     "@dcloudio/uni-quickapp-webview": "3.0.0-4080720251210001",
-    "@imengyu/imengyu-utils": "^0.0.24",
+    "@imengyu/imengyu-utils": "^0.0.26",
     "@imengyu/js-request-transform": "^0.3.7",
     "async-validator": "^4.2.5",
     "pinia": "^3.0.1",

+ 26 - 2
src/api/BaseAppServerRequestModule.ts

@@ -1,4 +1,5 @@
 import BugReporter from "@/common/BugReporter";
+import type { MpErrorInfo } from "@/common/composeabe/ErrorDisplay";
 import ApiCofig from "@/common/config/ApiCofig";
 import AppCofig, { isDev } from "@/common/config/AppCofig";
 import { RequestCoreInstance, RequestApiError, UniappImplementer, StringUtils, appendGetUrlParams, appendPostParams, RequestResponse, RequestOptions, type RequestApiInfoStruct, RequestApiResult, type RequestApiErrorType, defaultResponseDataGetErrorInfo, defaultResponseDataHandlerCatch } from "@imengyu/imengyu-utils";
@@ -79,7 +80,7 @@ export class BaseAppServerRequestModule<T extends DataModel> extends RequestCore
     this.config.baseUrl = baseUrl;
     this.config.errCodes = [];
     //请求拦截器
-    this.config.requestInceptor = (url, req) => {
+    this.config.requestInterceptor = (url, req) => {
       //获取app中的token,追加到头;
       const app = getApp();
       if (StringUtils.isNullOrEmpty((req.headers as KeyValue).token as string)) {
@@ -214,8 +215,31 @@ export class BaseAppServerRequestModule<T extends DataModel> extends RequestCore
         });
       }
     };
+    //响应错误处理函数
+    this.config.responseErrorHandler = (err, instance, apiInfo) => {
+      if (err instanceof RequestApiError)
+        throw err;
+      function createError(type: RequestApiErrorType, message: string) {
+        return new RequestApiError(type, message, '', -1, undefined, err, undefined, apiInfo);
+      }
+      if (err instanceof RequestApiError)
+        return err;
+      if (err instanceof Error)
+        return createError('unknow', err.message);
+      if (typeof err === 'object' && (err as MpErrorInfo)?.errMsg) {
+        const message = (err as MpErrorInfo).errMsg;
+        if (message.includes('timeout') || message.includes('aborted without reason'))
+          return createError('networkError', '请求超时或被取消');
+        if (message.includes('request:fail') && message.includes('ssl'))
+          return createError('networkError', '网络异常,可能是服务器过期或您的本地时间设置不正确');
+        if (message.includes('Network Error') || message.includes('request:fail'))
+          return createError('networkError', '网络异常,请检查网络设置');
+        return createError('unknow', '未知异常: ' + message);
+      }
+      return createError('unknow', '未知异常: ' + JSON.stringify(err));
+    };
     //错误报告处理
-    this.config.responseErrReoprtInceptor = (instance, response) => {
+    this.config.responseErrorReportInterceptor = (instance, response) => {
       return (
         (response.errorType !== 'businessError' && response.errorType !== 'networkError') ||
         matchNotReportMessage(response.code, response.errorMessage) === true

+ 1 - 1
src/api/introduction/SeaContent.ts

@@ -3,7 +3,7 @@ import { CommonContentApi } from '../CommonContent';
 export class SeaContentApi extends CommonContentApi {
 
   constructor() {
-    super(undefined, 3, "闽南文化-海洋文化", 252);
+    super(undefined, 3, "闽南文化-海洋文化", 254);
   }
 }
 

+ 59 - 0
src/common/components/tabs/Tabbar.vue

@@ -0,0 +1,59 @@
+<template>
+  <TabBar
+    :selectedTabIndex="current"
+    @update:selectedTabIndex="changeTab"
+    fixed
+    xbarSpace
+    :innerStyle="{ 
+      zIndex: 999 ,
+      boxShadow: '0 -2rpx 4rpx rgba(0, 0, 0, 0.1)',
+      backdropFilter: 'blur(10px)',
+      backgroundColor: 'rgba(246, 242, 231, 0.7)',
+    }"
+  >
+    <TabBarItem icon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_home_off.png" activeIcon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_home_on.png" text="首页" />
+    <TabBarItem icon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_discover_off.png" activeIcon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_discover_on.png" text="资讯" />
+    <TabBarItem icon="https://mn.wenlvti.net/app_static/minnan/images/tabs/icon_inhert_off.png" activeIcon="https://mn.wenlvti.net/app_static/minnan/images/tabs/icon_inhert_on.png" hump :humpHeight="[0,0]" :humpSpace="[20,20]" :iconSize="140" text="传承" />
+    <TabBarItem icon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_shop_off.png" activeIcon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_shop_on.png" text="乐游" />
+    <TabBarItem icon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_profile_off.png" activeIcon="https://mncdn.wenlvti.net/app_static/minnan/images/tabs/icon_profile_on.png" text="我的" />
+  </TabBar>
+</template>
+
+<script setup lang="ts">
+import TabBar from '@/components/nav/TabBar.vue';
+import TabBarItem from '@/components/nav/TabBarItem.vue';
+
+const props = defineProps({
+  current: {
+    type: Number,
+    default: 0
+  }
+});
+function changeTab(newVal: number) {
+  switch(newVal) {
+    case 0:
+      switchTab('/pages/home/index', 0);
+      break;
+    case 1:
+      switchTab('/pages/article/index', 1);
+      break;
+    case 2:
+      switchTab('/pages/inhert/index', 2);
+      break;
+    case 3:
+      switchTab('/pages/travel/index', 3);
+      break;
+    case 4:
+      switchTab('/pages/user/index', 4);
+      break;
+  }
+}
+
+function switchTab(path: string, index: number) {
+  if (props.current === index) 
+    return;
+  uni.switchTab({
+    url: path
+  });
+}
+</script>

+ 4 - 2
src/common/composeabe/ErrorDisplay.ts

@@ -17,9 +17,11 @@ export function showError(e: any, title = '糟糕,出错了', callback?: () =>
   })
   uni.hideLoading();
 }
+
+export interface MpErrorInfo {
+  errMsg: string;
+}
 export function formatError(e: any) {
-  if (e?.errMsg) 
-    return e.errMsg;
   if (e instanceof RequestApiError) 
     return e.errorMessage + (e.errorCodeMessage ? ` (${e.errorCodeMessage})` : '');
   if (e instanceof Error) 

+ 4 - 0
src/common/scss/common.scss

@@ -39,6 +39,10 @@
   top: -2px;
   z-index: 10;
 }
+.text-nowrap {
+  flex-shrink: 0;
+  white-space: nowrap;
+}
 
 //Fix
 

+ 5 - 5
src/pages.json

@@ -29,34 +29,34 @@
     {
       "path": "pages/introduction/news",
       "style": {
-        "navigationBarTitleText": "热点新鲜事",
+        "navigationBarTitleText": "闽南资讯",
         "enablePullDownRefresh": true
       }
     },
     {
       "path": "pages/introduction/recommend-news",
       "style": {
-        "navigationBarTitleText": "闽南走透透",
+        "navigationBarTitleText": "世界闽南",
         "enablePullDownRefresh": true
       }
     },
     {
       "path": "pages/introduction/explore",
       "style": {
-        "navigationBarTitleText": "探索闽南文化",
+        "navigationBarTitleText": "闽南百科",
         "enablePullDownRefresh": true
       }
     },
     {
       "path": "pages/introduction/inhert",
       "style": {
-        "navigationBarTitleText": "保护与传承"
+        "navigationBarTitleText": "文化遗产"
       }
     },
     {
       "path": "pages/introduction/travel",
       "style": {
-        "navigationBarTitleText": "文旅探世界"
+        "navigationBarTitleText": "乐游闽南"
       }
     },
     {

+ 1 - 1
src/pages/article/details.vue

@@ -18,7 +18,7 @@
             <view class="size-ll color-title-text">{{ loader.content.value.title }}</view>
             <view class="d-flex flex-row mt-2">
               <text v-if="loader.content.value.from" class="size-s color-text-content-second mr-2 ">来源:{{ loader.content.value.from }}</text>
-              <text class="size-s color-text-content-second">{{ DataDateUtils.formatDate(loader.content.value.publishAt, 'YYYY-MM-dd') }}</text>
+              <text class="size-s color-text-content-second text-nowrap">{{ DataDateUtils.formatDate(loader.content.value.publishAt, 'YYYY-MM-dd') }}</text>
             </view>
           </view>
           <view class="p-3 radius-ll bg-light mt-3">

+ 10 - 13
src/pages/home/index.vue

@@ -17,7 +17,7 @@
           <text class="title">闽南文化生态保护区(厦门市)</text>
           <text>世界闽南文化交流中心</text>
           <view class="more">
-            <text>查看详情</text>
+            <text>保护区概况</text>
           </view>
           <Image 
             innerClass="footer"
@@ -27,7 +27,7 @@
         </view>
         
         <HomeButton
-          title="探索闽南文化"
+          title="闽南百科"
           icon="https://mncdn.wenlvti.net/app_static/minnan/images/home/IconMap.png"
           bg="https://mncdn.wenlvti.net/app_static/minnan/images/home/ButtonMapBg.png"
           large
@@ -36,22 +36,22 @@
 
         <view class="position-relative d-flex flex-row flex-wrap justify-between mt-25 row-gap-sss">
           <HomeButton
-            title="热点新鲜事"
+            title="闽南资讯"
             icon="https://mncdn.wenlvti.net/app_static/minnan/images/home/IconDoc.png"
             @click="navTo('/pages/introduction/news')"
           />
           <HomeButton
-            title="保护与传承"
+            title="文化遗产"
             icon="https://mncdn.wenlvti.net/app_static/minnan/images/home/IconIch.png"
             @click="navTo('/pages/introduction/inhert')"
           />
           <HomeButton
-            title="闽南走透透"
+            title="世界闽南"
             icon="https://mncdn.wenlvti.net/app_static/minnan/images/home/IconArtifact.png"
             @click="navTo('/pages/introduction/recommend-news')"
           />
           <HomeButton
-            title="文旅探世界"
+            title="乐游闽南"
             icon="https://mncdn.wenlvti.net/app_static/minnan/images/home/IconDiscover.png"
             @click="navTo('/pages/introduction/travel')"
           />
@@ -315,13 +315,10 @@ const statsLoader = useSimpleDataLoader(async () => {
       title: item.level_text,
       value: item.total,
       titleSuffix: '项',
-      //subText: '\u00a0',
       type: 'forth',
       onClick: () => navTo('/pages/inhert/intangible/list', { tab: 0, level: item.level }),
     } as StatsTextItem
   });
-  //projects.shift();
-  //projects[0].subText = `人类非遗 ${topLevelProject}`;
   const inheritors = data.inheritorData.filter((p: any) => [ '国家级', '省级', '市级' ].includes(p.title)).map((item: any) => {
     sumInheritor += item.total;
     return {
@@ -500,8 +497,8 @@ onShareAppMessage(() => {
     }
     .more {
       margin-top: 30rpx;
-      padding: 10rpx 20rpx;
-      width: 150rpx;
+      padding: 10rpx 18rpx;
+      width: 180rpx;
       background-image: url('https://mncdn.wenlvti.net/app_static/minnan/images/home/MainBanner.png');
       background-size: 100% auto;
       background-repeat: no-repeat;
@@ -514,8 +511,8 @@ onShareAppMessage(() => {
     .footer {
       position: absolute;
       right: 0;
-      bottom: 0;
-      width: 370rpx;
+      bottom: -10rpx;
+      width: 350rpx;
       z-index: 2;
       height: auto;
     }

+ 1 - 1
src/pages/home/introduction.vue

@@ -95,7 +95,7 @@ const listLoader = useSimplePageListLoader<{
 }>(8, async (page, pageSize, params) => {
   const res = await CommonContent.getContentList(new GetContentListParams().setSelfValues({
     modelId: 17, 
-    mainBodyColumnId: '255,283',
+    mainBodyColumnId: '255',
   }), page, pageSize);
   return { list: res.list.map((item) => {
     return {

+ 82 - 65
src/pages/introduction/explore.vue

@@ -11,17 +11,27 @@
         />
         <SimplePageContentLoader :loader="category.data" >
           <FlexCol>
-            <Box2LineImageRightShadow
-              v-for="(item, i) in category.data.content.value"
-              titleColor="title-text"
-              fixSize
-              :key="i"
-              :title="item.title"
-              :desc="item.desc"
-              :image="item.image"
-              :tags="item.bottomTags"
-              @click="category.detailPage(item.id)"
-            />
+            <template v-if="category.type !== 'article'">
+              <Box2LineImageRightShadow
+                v-for="(item, i) in category.data.content.value"
+                titleColor="title-text"
+                fixSize
+                :key="i"
+                :title="item.title"
+                :desc="item.desc"
+                :image="item.image"
+                @click="category.detailPage(item.id)"
+              />
+            </template>
+            <template v-else>
+              <Box2LineRightShadow
+                v-for="(item, i) in category.data.content.value" 
+                :key="i" 
+                :title="item.title"
+                :desc="item.desc"
+                @click="category.detailPage(item.id)"
+              />
+            </template>
           </FlexCol>
         </SimplePageContentLoader>  
       </template>
@@ -58,20 +68,6 @@
           </FlexRow>
         </FlexCol>
       </SimplePageContentLoader>   -->
-      
-      <!-- 闽南文化百科 -->
-      <view class="d-flex flex-col">
-        <HomeTitle title="闽南文化百科" showMore @clickMore="goTopicsList" />
-        <SimplePageContentLoader :loader="topicsData">
-          <Box2LineRightShadow
-            v-for="(item, i) in topicsData.content.value" 
-            :key="i" 
-            :title="item.title"
-            :desc="item.desc"
-            @click="goTopicsDetail(item.id)"
-          />
-        </SimplePageContentLoader>
-      </view>
 
       <Footer text="我也是有底线的~" />
     </FlexCol>
@@ -86,7 +82,7 @@ import HomeTitle from '../parts/HomeTitle.vue';
 import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
 import { navTo } from '@/components/utils/PageAction';
 import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
-import { GetColumListParams, GetContentListParams } from '@/api/CommonContent';
+import { CommonContentApi, GetColumListParams, GetContentListParams } from '@/api/CommonContent';
 import { navHomePageMiniCommonDetailGo, navHomePageMiniCommonListGo, useHomePageMiniCommonListGoMoreAndGoDetail } from '../article/common/CommonContent';
 import CharacterContent from '@/api/introduction/CharacterContent';
 import Box2LineImageRightShadow from '../parts/Box2LineImageRightShadow.vue';
@@ -110,86 +106,118 @@ const categoryDefine = [
   {
     title: '文化概况',
     content: HistoryContent,
+    type: '',
+  },
+  {
+    title: '闽南文化百科',
+    content: useHomePageMiniCommonListGoMoreAndGoDetail({
+      title: '闽南文化百科',
+      mainBodyColumnId: 320,
+      modelId: 18,
+      itemType: 'article-common',
+      detailsPage: '/pages/article/details',
+    }),
+    type: 'article',
   },
   {
     title: '历史人物',
     content: CharacterContent,
     detailPage: '/pages/introduction/character/details',
     morePage: '/pages/introduction/character/list',
+    type: '',
   },
   // {
   //   title: '语言文化',
   //   content: LanguageContent,
+  //   type: '',
   // },
   {
     title: '民间习俗',
     content: CustomContent,
     morePage: '/pages/introduction/custom/list',
+    type: '',
   },
   {
     title: '艺术特色',
     content: FeatureContent,
+    type: '',
   },
   /* {
     title: '建筑文化',
     content: BulidingContent,
+    type: '',
   },
   {
     title: '饮食文化',
     content: VictualsContent,
+    type: '',
   },
   {
     title: '海洋文化',
     content: SeaContent,
+    type: '',
   },
   {
     title: '政策法规',
     content: PolicyContent,
+    type: '',
   },*/
 ]
 const categoryDatas = categoryDefine.map(item => ({
   ...item,
   detailPage: (id: number) => {
-    if (item.detailPage) {
-      navTo(item.detailPage, { id });
+    if (item.content instanceof CommonContentApi) {
+      if (item.detailPage) {
+        navTo(item.detailPage, { id });
+      } else {
+        navHomePageMiniCommonDetailGo({
+          id,
+          mainBodyColumnId: item.content.mainBodyColumnId,
+          modelId: item.content.modelId,
+        })
+      }
     } else {
-      navHomePageMiniCommonDetailGo({
-        id,
-        mainBodyColumnId: item.content.mainBodyColumnId,
-        modelId: item.content.modelId,
-      })
+      item.content.goDetail(id);
     }
   },
   morePage: () => {
-    if (item.morePage) {
-      navTo(item.morePage, {});
+    if (item.content instanceof CommonContentApi) {
+      if (item.morePage) {
+        navTo(item.morePage, {});
+      } else {
+        navHomePageMiniCommonListGo({
+          title: item.title,
+          mainBodyColumnId: item.content.mainBodyColumnId,
+          modelId: item.content.modelId,
+          detailsPage: item.detailPage,
+        })
+      }
     } else {
-      navHomePageMiniCommonListGo({
-        title: item.title,
-        mainBodyColumnId: item.content.mainBodyColumnId,
-        modelId: item.content.modelId,
-        detailsPage: item.detailPage,
-      })
+      item.content.goList();
     }
   },
-  data: useSimpleDataLoader(async () => 
-    (await item.content.getContentList(new GetContentListParams(), 1, 3)).list.map(p => ({
-      id: p.id,
-      title: p.title, 
-      desc: `来源:${p.from || '暂无'}\n` + (p.desc || ''), 
-      image: p.thumbnail || p.image,
-      bottomTags: p.keywords as string[],
-    }))
-  ),
+  data: item.content instanceof CommonContentApi ? useSimpleDataLoader(async () => {
+    return (await (item.content as CommonContentApi)
+      .getContentList(new GetContentListParams(), 1, 3))
+      .list.map(p => ({
+        id: p.id,
+        title: p.title, 
+        desc: `来源:${p.from || '暂无'}\n` + (p.desc || ''), 
+        image: p.thumbnail || p.image,
+        bottomTags: p.keywords as string[],
+      }))
+  }) : item.content.loader,
 }));
 const introdData = useSimpleDataLoader(async () => {
   let i = 0;
   const promises = [];
   for (const item of categoryDefine) {
-    promises.push(IndexContent.getColumList(new GetColumListParams().setSelfValues({
-      modelId: item.content.modelId,
-      mainBodyColumnId: item.content.mainBodyColumnId,
-    })))
+    if (item.content instanceof CommonContentApi) {
+      promises.push(IndexContent.getColumList(new GetColumListParams().setSelfValues({
+        modelId: item.content.modelId,
+        mainBodyColumnId: item.content.mainBodyColumnId,
+      })))
+    }
   }
   const result = await Promise.all(promises);
   return result.map((data, i) => {
@@ -204,15 +232,4 @@ const introdData = useSimpleDataLoader(async () => {
     }
   });
 });
-const {
-  loader: topicsData,
-  goList: goTopicsList,
-  goDetail: goTopicsDetail,
-} = useHomePageMiniCommonListGoMoreAndGoDetail({
-  title: '闽南文化百科',
-  mainBodyColumnId: 320,
-  modelId: 18,
-  itemType: 'article-common',
-  detailsPage: '/pages/article/details',
-});
 </script>

+ 136 - 110
src/pages/introduction/inhert.vue

@@ -1,132 +1,154 @@
 <template>
-  <FlexCol :padding="30" backgroundColor="background.page">
+  <FlexCol :padding="[0, 30]" backgroundColor="background.page">
     
-    <!-- 非遗项目 -->
-    <HomeTitle title="非遗项目" showMore @clickMore="navTo('/pages/inhert/intangible/list')" />
-    <SimplePageContentLoader :loader="intangibleData" >
-      <scroll-view scroll-x>
-        <FlexRow>
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in intangibleData.content.value"
-            classNames="width-2-3 mr-2"
+    <Tabs
+      v-model:currentIndex="activeIndex"
+      :width="690"
+      :tabs="[
+        {
+          text: '非物质文化遗产',
+        },
+        {
+          text: '物质文化遗产',
+        },
+      ]"
+    />
+
+    <template v-if="activeIndex === 0">
+      <HomeTitle title="非物质文化遗产" showMore @clickMore="navTo('/pages/inhert/intangible/list')" />
+      <!-- 非遗项目 -->
+      <SimplePageContentLoader :loader="intangibleData" >
+        <scroll-view scroll-x>
+          <FlexRow>
+            <Box2LineLargeImageUserShadow
+              v-for="(item, i) in intangibleData.content.value"
+              classNames="width-2-3 mr-2"
+              titleColor="title-text"
+              fixSize
+              title1
+              :key="i"
+              :title="item.title"
+              :desc="item.desc"
+              :image="item.image"
+              :tags="item.bottomTags"
+              @click="navTo('/pages/inhert/intangible/details', { id: item.id })"
+            />
+          </FlexRow>
+        </scroll-view>
+      </SimplePageContentLoader>
+
+      <!-- 非遗传承人 -->
+      <HomeTitle title="非遗传承人" showMore @clickMore="navTo('/pages/inhert/inheritor/list')" />
+      <SimplePageContentLoader :loader="inheritorData">
+        <FlexCol>
+          <Box2LineImageRightShadow
+            v-for="(item, i) in inheritorData.content.value"
             titleColor="title-text"
             fixSize
-            title1
             :key="i"
             :title="item.title"
             :desc="item.desc"
             :image="item.image"
             :tags="item.bottomTags"
-            @click="navTo('/pages/inhert/intangible/details', { id: item.id })"
+            @click="navTo('/pages/inhert/inheritor/details', { id: item.id })"
           />
-        </FlexRow>
-      </scroll-view>
-    </SimplePageContentLoader>
-    
-    <!-- 非遗传承人 -->
-    <HomeTitle title="非遗传承人" showMore @clickMore="navTo('/pages/inhert/inheritor/list')" />
-    <SimplePageContentLoader :loader="inheritorData">
-      <FlexCol>
-        <Box2LineImageRightShadow
-          v-for="(item, i) in inheritorData.content.value"
-          titleColor="title-text"
-          fixSize
-          :key="i"
-          :title="item.title"
-          :desc="item.desc"
-          :image="item.image"
-          :tags="item.bottomTags"
-          @click="navTo('/pages/inhert/inheritor/details', { id: item.id })"
-        />
-      </FlexCol>
-    </SimplePageContentLoader>
+        </FlexCol>
+      </SimplePageContentLoader>
 
-    <!-- 保护单位 -->
-    <HomeTitle title="保护单位" showMore @clickMore="navTo('/pages/inhert/unit/list')" />
-    <SimplePageContentLoader :loader="unitData">
-      <FlexCol>
-        <Box2LineImageRightShadow
-          v-for="(item, i) in unitData.content.value"
-          titleColor="title-text"
-          :border="false"
-          fixSize
-          :key="i"
-          :title="item.title"
-          :desc="item.desc"
-          :showImage="false"
-          :tags="item.bottomTags"
-        />
-      </FlexCol>
-    </SimplePageContentLoader>
-
-    <!-- 非遗传习所 -->
-    <HomeTitle title="非遗传习所" showMore @clickMore="navHomePageMiniCommonListGo({
-      title: '非遗传习所',
-      modelId: SeminarContent.modelId,
-      mainBodyColumnId: SeminarContent.mainBodyColumnId,
-      detailsPage: '/pages/inhert/seminar/details',
-    })" />
-    <SimplePageContentLoader :loader="seminarData">
-      <FlexCol overflow="visible">
-        <Box2LineImageRightShadow
-          v-for="(item, i) in seminarData.content.value"
-          titleColor="title-text"
-          fixSize
-          :key="i"
-          :title="item.title"
-          :desc="item.desc"
-          :image="item.image"
-          :tags="item.bottomTags"
-          @click="navTo('/pages/inhert/seminar/details', { id: item.id })"
-        />
-      </FlexCol>
-    </SimplePageContentLoader>
+      <!-- 保护单位 -->
+      <HomeTitle title="保护单位" showMore @clickMore="navTo('/pages/inhert/unit/list')" />
+      <SimplePageContentLoader :loader="unitData">
+        <FlexCol>
+          <Box2LineImageRightShadow
+            v-for="(item, i) in unitData.content.value"
+            titleColor="title-text"
+            :border="false"
+            fixSize
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :showImage="false"
+            :tags="item.bottomTags"
+          />
+        </FlexCol>
+      </SimplePageContentLoader>
 
-    <!-- 非遗活动 -->
-    <HomeTitle title="非遗活动" showMore @clickMore="goActivityList" />
-    <SimplePageContentLoader :loader="activityData">
-      <FlexRow wrap align="stretch" justify="space-between" overflow="visible">
-        <Box2LineLargeImageUserShadow
-          v-for="(item, i) in activityData.content.value"
-          titleColor="title-text"
-          width="calc(50% - 10rpx)"
-          fixSize
-          :key="i"
-          :title="item.title"
-          :desc="item.desc"
-          :image="item.image"
-          @click="goActivityDetail(item.id)"
-        />
-      </FlexRow>
-    </SimplePageContentLoader>
+      <!-- 非遗传习所 -->
+      <HomeTitle title="非遗传习所" showMore @clickMore="navHomePageMiniCommonListGo({
+        title: '非遗传习所',
+        modelId: SeminarContent.modelId,
+        mainBodyColumnId: SeminarContent.mainBodyColumnId,
+        detailsPage: '/pages/inhert/seminar/details',
+      })" />
+      <SimplePageContentLoader :loader="seminarData">
+        <FlexCol overflow="visible">
+          <Box2LineImageRightShadow
+            v-for="(item, i) in seminarData.content.value"
+            titleColor="title-text"
+            fixSize
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :tags="item.bottomTags"
+            @click="navTo('/pages/inhert/seminar/details', { id: item.id })"
+          />
+        </FlexCol>
+      </SimplePageContentLoader>
 
-    <!-- 文物 -->
-    <HomeTitle title="文物古迹" showMore @clickMore="navTo('/pages/inhert/artifact/list')" />
-    <SimplePageContentLoader :loader="artifactData">
-      <FlexRow wrap align="stretch" justify="space-between" overflow="visible">
-        <Box2LineLargeImageUserShadow
-          v-for="(item, i) in artifactData.content.value"
-          width="calc(50% - 10rpx)"
-          titleColor="title-text"
-          fixSize
-          :key="i"
-          :title="item.title"
-          :image="item.image"
-          :tags="item.tags"
-          title1
-          @click="navTo('/pages/inhert/artifact/details', { id: item.id })"
-        />
-      </FlexRow>
-    </SimplePageContentLoader>
+      <!-- 非遗活动 -->
+      <HomeTitle title="非遗活动" showMore @clickMore="goActivityList" />
+      <SimplePageContentLoader :loader="activityData">
+        <FlexRow wrap align="stretch" justify="space-between" overflow="visible">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in activityData.content.value"
+            titleColor="title-text"
+            width="calc(50% - 10rpx)"
+            fixSize
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            @click="goActivityDetail(item.id)"
+          />
+        </FlexRow>
+      </SimplePageContentLoader>
+    </template>
+    <template v-else-if="activeIndex === 1">
+      <!-- 文物 -->
+      <HomeTitle title="物质文化遗产" showMore @clickMore="navTo('/pages/inhert/artifact/list')" />
+      <SimplePageContentLoader :loader="artifactData">
+        <FlexRow wrap align="stretch" justify="space-between" overflow="visible">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in artifactData.content.value"
+            width="calc(50% - 10rpx)"
+            titleColor="title-text"
+            fixSize
+            :key="i"
+            :title="item.title"
+            :image="item.image"
+            :tags="item.tags"
+            title1
+            @click="navTo('/pages/inhert/artifact/details', { id: item.id })"
+          />
+        </FlexRow>
+        <Touchable direction="row" center :padding="10" :gap="20" @click="navTo('/pages/inhert/artifact/list')">
+          <text>查看全部</text>
+          <Icon name="arrow-right" />
+        </Touchable>
+      </SimplePageContentLoader>
+    </template>
 
-    <Footer text="我也是有底线的~" />
+    <Footer text="到底了~" />
   </FlexCol>
 </template>
 
 <script setup lang="ts">
+import { ref } from 'vue';
 import { navTo } from '@/components/utils/PageAction';
 import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
 import { GetContentListParams } from '@/api/CommonContent';
+import { navHomePageMiniCommonListGo, useHomePageMiniCommonListGoMoreAndGoDetail } from '../article/common/CommonContent';
 import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import HomeTitle from '../parts/HomeTitle.vue';
@@ -136,10 +158,14 @@ import InheritorContent from '@/api/inheritor/InheritorContent';
 import ProjectsContent from '@/api/inheritor/ProjectsContent';
 import UnitContent from '@/api/inheritor/UnitContent';
 import SeminarContent from '@/api/inheritor/SeminarContent';
-import { navHomePageMiniCommonListGo, useHomePageMiniCommonListGoMoreAndGoDetail } from '../article/common/CommonContent';
 import FlexRow from '@/components/layout/FlexRow.vue';
 import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
 import Footer from '@/components/display/Footer.vue';
+import Tabs from '@/components/nav/Tabs.vue';
+import Touchable from '@/components/feedback/Touchable.vue';
+import Icon from '@/components/basic/Icon.vue';
+
+const activeIndex = ref(0);
 
 const intangibleData = useSimpleDataLoader(async () => 
   (await ProjectsContent.getContentList(new GetContentListParams(), 1, 4)).list.map(p => ({
@@ -198,7 +224,7 @@ const seminarData = useSimpleDataLoader(async () =>
   }))
 );
 const artifactData = useSimpleDataLoader(async () => 
-  (await UnmoveableContent.getContentList(new GetContentListParams(), 1, 4)).list.map(p => ({
+  (await UnmoveableContent.getContentList(new GetContentListParams(), 1, 16)).list.map(p => ({
     id: p.id,
     title: p.title, 
     desc: '', 

+ 49 - 62
src/pages/introduction/recommend-news.vue

@@ -1,69 +1,56 @@
-
 <template>
-  <CommonRoot>
-    <FlexCol :padding="30" innerClass="bg-base">
-      <SearchBar
-        v-model="searchText"
-        inputBackgroundColor="transparent"
-        leftIcon=""
-        placeholder="搜索新闻"
-        cancelState="hidden"
-        searchState="show"
-        @search="loadNews"
-      />
-      <Box2LineImageRightShadow 
-        v-for="(item, i) in newsLoader.list.value"
-        :key="item.id"
-        :class="[
-          'position-relative d-flex flex-grow-1',
-        ]"
-        class="w-100"
-        titleColor="title-text"
-        :image="item.thumbnail || item.image"
-        :title="item.title"
-        :desc="item.from ? `来源:${item.from}` : ''"
-        :badge="item.badge"
-        :wideImage="true"
-        @click="goDetails(item, item.id)"
-      />
-      <SimplePageListLoader :loader="newsLoader" />
-    </FlexCol>
-  </CommonRoot>
+  <CommonListPage 
+    itemType="article-common"
+    :dropDownNames="dropdownNames"
+    :tabs="[
+      { id: 0, text: '传播交流' },
+      { id: 1, text: '海洋文化' },
+    ]"
+    :startTabIndex="startTab"
+    :load="loadData" 
+  />
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref } from 'vue';
-import { type GetContentListItem, GetContentListParams } from '@/api/CommonContent';
-import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
-import { navHomePageMiniCommonDetailGo } from '../article/common/CommonContent';
+import { ref } from 'vue';
+import { GetContentListParams } from '@/api/CommonContent';
+import SeaContent from '@/api/introduction/SeaContent';
 import NewsIndexContent from '@/api/news/NewsIndexContent';
-import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
-import CommonRoot from '@/components/dialog/CommonRoot';
-import FlexCol from '@/components/layout/FlexCol.vue';
-import SearchBar from '@/components/form/SearchBar.vue';
-import Box2LineImageRightShadow from '../parts/Box2LineImageRightShadow.vue';
-
-const searchText = ref('');
-
-const newsLoader = useSimplePageListLoader(10, async (page, pageSize) => {
-  return await NewsIndexContent.getContentList(new GetContentListParams()
-    .setKeywords(searchText.value)
-    .setMainBodyColumnId([260, 261, 262])
-  , page, pageSize);
-});
+import CommonListPage, { type DropDownNames } from '@/pages/article/common/CommonListPage.vue';
 
-function loadNews() {
-  newsLoader.loadData(undefined, true);
+const dropdownNames = ref<DropDownNames[]>([]);
+const startTab = ref(0);
+async function loadData(
+  page: number, 
+  pageSize: number,
+  searchText: string,
+  dropDownValues: number[],
+  tabSelect: number,
+) {
+  let res;
+  switch (tabSelect) {
+    case 0: 
+      res = (await NewsIndexContent.getContentList(new GetContentListParams()
+        .setKeywords(searchText)
+        .setMainBodyColumnId([260, 261, 262])
+      , page, pageSize))
+      break;
+    default:
+    case 1: 
+      res = (await SeaContent.getContentList(new GetContentListParams()
+        .setKeywords(searchText)
+      , page, pageSize));
+    break;
+  }
+  res.list.forEach((item) => {
+    item.desc = item.from ? `来源:${item.from}` : '';
+    item.bottomTags = [
+      item.levelText, 
+      item.mainBodyColumnName, 
+      item.ichTypeText, 
+      item.batchText,
+    ]
+  })
+  return res;
 }
-function goDetails(item: GetContentListItem, id: number) {
-  navHomePageMiniCommonDetailGo({
-    id,
-    mainBodyColumnId: item.mainBodyColumnId,
-    modelId: item.modelId,
-  });
-}
-
-onMounted(() => {
-  loadNews();
-});
-</script>
+</script>

+ 65 - 36
src/pages/introduction/travel.vue

@@ -1,29 +1,25 @@
 <template>
   <FlexCol :padding="30" backgroundColor="background.page">
-    
-    <!-- 闽南节庆日历 -->
-    <HomeTitle title="闽南节庆日历" showMore @clickMore="navTo('/pages/travel/calendar/index')" />
-    <CalendarBlock />
 
-    <!-- 闽南文化景区、景点 -->
-    <HomeTitle title="闽南文化景区、景点" showMore @clickMore="navTo('/pages/travel/scenic-spot/list')" />
-    <SimplePageContentLoader :loader="spotData">
+    <!-- 闽南语在线课程-->
+    <HomeTitle title="闽南语在线课程" :showMore="false" @clickMore="goCourseList" />
+    <SimplePageContentLoader :loader="corseData" >
       <scroll-view scroll-x>
-        <FlexCol>
-          <Box2LineImageRightShadow
-            v-for="(item, i) in spotData.content.value"
+        <view class="pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in corseData.content.value"
+            classNames="width-2-3 mr-2"
             titleColor="title-text"
             fixSize
             :key="i"
             :title="item.title"
             :desc="item.desc"
-            :image="item.image"
-            :tags="item.bottomTags"
-            @click="navTo('/pages/inhert/intangible/details', { id: item.id })"
+            :image="item.thumbnail || item.image"
+            @click="goCourseDetail(item.id)"
           />
-        </FlexCol>
+        </view>
       </scroll-view>
-    </SimplePageContentLoader>
+    </SimplePageContentLoader>   
 
     <!-- 闽南歌曲 -->
     <HomeTitle title="闽南歌曲" showMore @clickMore="navTo('/pages/travel/fashion/list')" />
@@ -41,62 +37,83 @@
           @click="goSongsDetail(item.id)"
         />
       </FlexRow>
+    </SimplePageContentLoader>    
+
+    <!-- 闽南节庆日历 -->
+    <HomeTitle title="闽南节庆日历" showMore @clickMore="navTo('/pages/travel/calendar/index')" />
+    <CalendarBlock />
+
+    <!-- 闽南美食 -->
+    <HomeTitle title="闽南美食" showMore @clickMore="goFoodList" />
+    <SimplePageContentLoader :loader="foodData">
+      <FlexRow wrap justify="space-between">
+        <Box2LineLargeImageUserShadow
+          v-for="(item, i) in foodData.content.value"
+          width="calc(50% - 10rpx)"
+          titleColor="title-text"
+          fixSize
+          :key="i"
+          :title="item.title"
+          :image="item.thumbnail || item.image"
+          @click="goFoodDetail(item.id)"
+        />
+      </FlexRow>
     </SimplePageContentLoader>
 
-    <!-- 文化旅游路线 -->
-    <HomeTitle title="文化旅游路线" showMore @clickMore="goRouteList" />
-    <SimplePageContentLoader :loader="routeData">
+    <!-- 闽南文化景区 -->
+    <HomeTitle title="闽南文化景区" showMore @clickMore="navTo('/pages/travel/scenic-spot/list')" />
+    <SimplePageContentLoader :loader="spotData">
       <scroll-view scroll-x>
-        <view class="pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
-          <Box2LineLargeImageUserShadow
-            v-for="(item, i) in routeData.content.value"
-            classNames="width-2-3 mr-2"
+        <FlexCol>
+          <Box2LineImageRightShadow
+            v-for="(item, i) in spotData.content.value"
             titleColor="title-text"
             fixSize
             :key="i"
             :title="item.title"
             :desc="item.desc"
-            :image="item.thumbnail || item.image"
-            @click="goRouteDetail(item.id)"
+            :image="item.image"
+            :tags="item.bottomTags"
+            @click="navTo('/pages/inhert/intangible/details', { id: item.id })"
           />
-        </view>
+        </FlexCol>
       </scroll-view>
     </SimplePageContentLoader>
 
-    <!-- 文化产品 -->
-    <HomeTitle title="文化产品" showMore @clickMore="goCreativeList" />
-    <SimplePageContentLoader :loader="creativeData">
+    <!-- 文化旅游路线 -->
+    <HomeTitle title="文化旅游路线" showMore @clickMore="goRouteList" />
+    <SimplePageContentLoader :loader="routeData">
       <scroll-view scroll-x>
         <view class="pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
           <Box2LineLargeImageUserShadow
-            v-for="(item, i) in creativeData.content.value"
+            v-for="(item, i) in routeData.content.value"
             classNames="width-2-3 mr-2"
             titleColor="title-text"
             fixSize
             :key="i"
             :title="item.title"
+            :desc="item.desc"
             :image="item.thumbnail || item.image"
-            @click="goCreativeDetail(item.id)"
+            @click="goRouteDetail(item.id)"
           />
         </view>
       </scroll-view>
     </SimplePageContentLoader>
 
-    <!-- 闽南语在线课程-->
-    <HomeTitle title="闽南语在线课程" :showMore="false" @clickMore="goCourseList" />
-    <SimplePageContentLoader :loader="corseData" >
+    <!-- 闽南好物 -->
+    <HomeTitle title="闽南好物" showMore @clickMore="goCreativeList" />
+    <SimplePageContentLoader :loader="creativeData">
       <scroll-view scroll-x>
         <view class="pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
           <Box2LineLargeImageUserShadow
-            v-for="(item, i) in corseData.content.value"
+            v-for="(item, i) in creativeData.content.value"
             classNames="width-2-3 mr-2"
             titleColor="title-text"
             fixSize
             :key="i"
             :title="item.title"
-            :desc="item.desc"
             :image="item.thumbnail || item.image"
-            @click="goCourseDetail(item.id)"
+            @click="goCreativeDetail(item.id)"
           />
         </view>
       </scroll-view>
@@ -194,4 +211,16 @@ const {
   itemType: 'article-common',
   detailsPage: '/pages/article/details',
 });
+
+const {
+  loader: foodData,
+  goList: goFoodList,
+  goDetail: goFoodDetail,
+} = useHomePageMiniCommonListGoMoreAndGoDetail({
+  title: '闽南美食',
+  mainBodyColumnId: 253,
+  modelId: 3,
+  itemType: 'article-common',
+  detailsPage: '/pages/article/details',
+});
 </script>

+ 3 - 1
src/pages/parts/HomeTitle.vue

@@ -6,7 +6,9 @@
       inWing ? 'wing-l in-wing' : '',
     ]"
   >
-    <text>{{ title }}</text>
+    <slot>
+      <text>{{ title }}</text>
+    </slot>
     <text v-if="showMore" class="more" @click="$emit('clickMore')">
       {{moreText}}
       <text class="iconfont icon-arrow-right ml-2" />

+ 1 - 1
src/pages/travel/index.vue

@@ -4,7 +4,7 @@
     <NavBar leftButton="custom" backgroundColor="background.page">
       <template #left>
         <Image
-          src="https://mncdn.wenlvti.net/app_static/minnan/images/travel/Title.png"
+          src="https://mn.wenlvti.net/app_static/minnan/images/travel/TitleTravel.png"
           mode="widthFix"
           :width="110"
           :innerStyle="{ marginLeft: '30rpx', marginTop: '30rpx' }"