ソースを参照

📦 文物列表页和详情页

imengyu 2 週間 前
コミット
cadae6df8c

+ 1 - 1
src/common/components/SimpleDropDownPicker.vue

@@ -58,7 +58,7 @@ function confirm(e: { value: SimpleDropDownPickerItem[] }) {
 .simple-dropdown-box {
   position: relative;
   padding: 16rpx 18rpx;
-  border-radius: 20rpx;
+  border-radius: 30rpx;
   background: #FFFFFF;
 }
 </style>

+ 13 - 1
src/pages.json

@@ -33,6 +33,18 @@
       }
     },
     {
+      "path": "pages/inhert/artifact/list",
+      "style": {
+        "navigationBarTitleText": "文物"
+      }
+    },
+    {
+      "path": "pages/inhert/artifact/details",
+      "style": {
+        "navigationBarTitleText": "文物"
+      }
+    },
+    {
       "path": "pages/article/details",
       "style": {
         "navigationBarTitleText": "新闻详情"
@@ -110,7 +122,7 @@
       },
       {
         "pagePath": "pages/travel",
-        "text": "旅"
+        "text": "旅"
       },
       {
         "pagePath": "pages/user/index",

+ 5 - 1
src/pages/inhert.vue

@@ -8,7 +8,7 @@
     <view class="content d-flex flex-col ">
       
       <!-- 文物 -->
-      <HomeTitle title="文物" showMore inWing />
+      <HomeTitle title="文物" showMore inWing @clickMore="navTo('inhert/artifact/list')" />
       <SimplePageContentLoader :loader="artifactData">
         <scroll-view scroll-x>
           <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
@@ -21,6 +21,7 @@
               :image="item.image"
               :likes="item.likes"
               :comment="item.comment"
+              @click="navTo('inhert/artifact/details', { id: item.id })"
             />
           </view>
         </scroll-view>
@@ -157,12 +158,14 @@ import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
 import { GetContentListParams } from '@/api/CommonContent';
 import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
 import ProjectsContent from '@/api/inheritor/ProjectsContent';
+import { navTo } from '@/common/utils/PageAction';
 
 const artifactData = useSimpleDataLoader(async () => 
   (await UnmoveableContent.getContentList(new GetContentListParams().setSelfValues({
     type: GetContentListParams.TYPE_ARTICLE,
     flag: 'recommend',
   }), 1, 4)).list.map(p => ({
+    id: p.id,
     title: p.title, 
     desc: '', 
     image: p.image,
@@ -175,6 +178,7 @@ const intangibleData = useSimpleDataLoader(async () =>
     type: GetContentListParams.TYPE_ARTICLE,
     flag: 'recommend',
   }), 1, 4)).list.map(p => ({
+    id: p.id,
     title: p.title, 
     desc: p.desc, 
     image: p.image,

+ 284 - 0
src/pages/inhert/artifact/details.vue

@@ -0,0 +1,284 @@
+<template>
+  <view class="d-flex flex-col h-100vh">
+    <SimplePageContentLoader :loader="loader">
+      <template v-if="loader.content.value">
+        <view class="banner">
+          <swiper class="swiper" circular :indicator-dots="true" :autoplay="true" :interval="2000" :duration="1000">
+            <swiper-item v-for="(item, key) in loader.content.value.images" :key="key">
+              <view class="item">
+                <ImageWrapper :src="item" mode="aspectFill" width="750rpx" />
+              </view>
+            </swiper-item>
+          </swiper>
+        </view>
+        <view class="d-flex flex-col p-3">
+          <view class="intro-block artifact-info">
+            <HomeTitle :title="loader.content.value.title" />
+            <view class="desc no-indent">
+              <view class="navigation">
+                <view class="address">
+                  <text class="iconfont icon-navigation"></text>
+                  <text>{{ loader.content.value.address }}</text>
+                </view>
+                <view class="link">
+                  去这里 <text class="iconfont icon-go"></text>
+                </view>
+              </view>
+              <view class="entry">
+                <view class="label">开放时间:</view>
+                <view class="value">{{ loader.content.value.openStatusText }}</view>
+              </view>
+              <view class="entry">
+                <view class="label">年代:</view>
+                <view class="value">{{ loader.content.value.age }} 年)</view>
+              </view>
+              <view class="entry">
+                <view class="label">文物类型:</view>
+                <view class="value">{{ loader.content.value.crTypeText }}</view>
+              </view>
+              <view class="entry">
+                <view class="label">所属区域:</view>
+                <view class="value">{{ loader.content.value.regionText }}</view>
+              </view>
+              <view class="entry">
+                <view class="label">级别:</view>
+                <view class="value">{{ loader.content.value.levelText }}</view>
+              </view>
+              <view class="entry">
+                <view class="label">保护范围:</view>
+                <view class="value">
+                </view>
+              </view>
+              <u-parse :content="loader.content.value.protectedArea" :tagStyle="commonParserStyle"></u-parse>
+            </view>
+          </view>
+          <view class="intro-block">
+            <view class="title">
+              <view class="line"></view>
+              <text class="sm">简介</text>
+            </view>
+            <view class="desc">
+              <u-parse :content="loader.content.value.intro" :tagStyle="commonParserStyle"></u-parse>
+            </view>
+            <view class="sub-title">详情</view>
+            <view class="desc">
+              <u-parse :content="loader.content.value.value" :tagStyle="commonParserStyle"></u-parse>
+            </view>
+          </view>
+          <HomeTitle title="更多人气好去处" showMore />
+          <view class="rec-list">
+            <swiper class="swiper" :autoplay="false" :circular="false" :duration="500"
+                    :next-margin="'145rpx'">
+              <swiper-item v-for="item in loader.content.value.associationMeList" :key="item.id" @click="goDetails(item)">
+                <view class="item">
+                  <image :src="item.image" mode="aspectFill"></image>
+                  <view class="name">
+                    <text>{{ item.title }}</text>
+                  </view>
+                </view>
+              </swiper-item>
+            </swiper>
+          </view>
+          <HomeTitle title="本地吃透透" showMore />
+          <view class="food-list">
+            <view class="item" v-for="item in foodList" :key="item.id">
+              <image :src="item.image" mode="aspectFill"></image>
+              <view class="info">
+                <view class="name">{{ item.name }}</view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </template>
+    </SimplePageContentLoader>
+  </view>
+</template>
+<script setup lang="ts">
+import type { GetContentDetailItem } from "@/api/CommonContent";
+import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
+import { onLoad } from "@dcloudio/uni-app";
+import { navTo } from "@/common/utils/PageAction";
+import UnmoveableContent from "@/api/inheritor/UnmoveableContent";
+import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
+import ImageWrapper from "@/common/components/ImageWrapper.vue";
+import HomeTitle from "@/pages/parts/HomeTitle.vue";
+import commonParserStyle from "@/common/style/commonParserStyle";
+
+const loader = useSimplePageContentLoader<
+  GetContentDetailItem, 
+  { id: number }
+>(async (params) => {
+  if (!params)
+    throw new Error("!params");
+  return await UnmoveableContent.getContentDetail(params.id);
+});
+
+onLoad((options) => {
+  loader.loadData({
+    id: Number(options?.id),
+  })
+});
+
+function goDetails(item: any) {
+  navTo('inherit_artifact_details', { id: item.id })
+}
+
+const foodList = [
+  {
+    id: 1,
+    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food1.png',
+    name: '沙茶面',
+  },
+  {
+    id: 2,
+    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food2.png',
+    name: '碗糕',
+  },
+  {
+    id: 3,
+    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food1.png',
+    name: '姜母鸭',
+  },
+  {
+    id: 4,
+    image: 'https://lucheng.app4lh.cn/static/tmp/static/tmp/food2.png',
+    name: '炸枣',
+  }
+];
+</script>
+
+<style lang="scss" scoped>
+page {
+  background: #FFF3E1;
+}
+
+.food-list {
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
+
+  .item {
+    width: calc(50% - 15rpx);
+    margin-bottom: 53rpx;
+
+    image {
+      width: 100%;
+      height: 360rpx;
+      display: block;
+    }
+
+    .info {
+      text-align: center;
+      padding-top: 20rpx;
+      font-weight: bold;
+      font-size: 30rpx;
+      color: #312520;
+    }
+  }
+}
+
+.rec-list {
+  swiper {
+    height: 300rpx;
+  }
+
+  .item {
+    width: 514rpx;
+    height: 300rpx;
+    position: relative;
+    border-radius: 20rpx;
+    overflow: hidden;
+    background-color: #eaeaea;
+
+    image {
+      width: 100%;
+      height: 100%;
+    }
+
+    .name {
+      position: absolute;
+      bottom: 34rpx;
+      right: 22rpx;
+      color: #fff;
+      font-weight: 600;
+      font-size: 28rpx;
+    }
+  }
+}
+
+.intro-block {
+  margin-bottom: 38rpx;
+  .title{
+    .sm{
+      font-size: 30rpx;
+    }
+  }
+  &.artifact-info{
+    .desc{
+      line-height: inherit;
+      padding-bottom: 10rpx;
+    }
+  }
+  .entry {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    margin-bottom: 10rpx;
+
+    .label {
+      color: #666666;
+      font-weight: 400;
+      font-size: 28rpx;
+    }
+    .value {
+      font-size: 28rpx;
+      color: #312520;
+      font-weight: 400;
+    }
+  }
+  .sub-title{
+    margin-left: 20rpx;
+    margin-top: 10rpx;
+    font-size: 30rpx;
+    font-weight: 600;
+  }
+  .desc{
+    padding:30rpx;
+  }
+  .navigation{
+    display: flex;
+    align-items: center;
+    margin-bottom: 28rpx;
+    .address{
+      flex:1;
+      height: auto;
+      background: #F9F6EB;
+      border-radius: 28rpx;
+      font-weight: 400;
+      font-size: 24rpx;
+      color: #000000;
+      line-height: 48rpx;
+      padding-left: 30rpx;
+      display: flex;
+      align-items: center;
+      text.iconfont{
+        display: inline-block;
+        font-size: 36rpx;
+        margin-right: 8rpx;
+      }
+    }
+    .link{
+      margin-left: 20rpx;
+      color:#FF8719;
+    }
+  }
+}
+.banner {
+  margin-top: 0;
+  .swiper {
+    border-radius: 0;
+    height: 504rpx;
+  }
+}
+
+</style>

+ 116 - 0
src/pages/inhert/artifact/list.vue

@@ -0,0 +1,116 @@
+<template>
+  <view class="d-flex flex-column bg-base">
+    <u-tabs 
+      :list="tabs" 
+      lineWidth="30"
+      lineColor="#d9492e"
+      :activeStyle="{
+        color: '#000',
+        fontWeight: 'bold',
+        transform: 'scale(1.05)'
+      }"
+      :inactiveStyle="{
+        color: '#606266',
+        transform: 'scale(1)'
+      }"
+      :scrollable="false"
+      class="top-tab"
+      @click="(e: any) => tab = e.index"
+    />
+
+    <view class="d-flex flex-col p-2">
+      <uni-search-bar 
+        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 class="width-1-4" :columns="categoryData" />
+      <SimpleDropDownPicker class="width-1-4" :columns="categoryData" />
+      <SimpleDropDownPicker class="width-1-4" :columns="categoryData" />
+    </view>
+    <view class="d-flex flex-row flex-wrap justify-between p-2">
+      <view
+        v-for="item in listLoader.list.value"
+        :key="item.id"
+        class="width-1-2"
+      >
+        <Box2LineLargeImageUserShadow 
+          classNames="ml-2 mb-3"
+          titleColor="title-text"
+          :image="item.image"
+          :title="item.name"
+          @click="goDetails(item.id)"
+        />
+      </view>
+    </view>
+    <SimplePageListLoader :loader="listLoader" />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, watch } from 'vue';
+import { GetContentListParams } from '@/api/CommonContent';
+import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
+import { navTo } from '@/common/utils/PageAction';
+import MoveableContent from '@/api/inheritor/MoveableContent';
+import UnmoveableContent from '@/api/inheritor/UnmoveableContent';
+import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
+import Box2LineLargeImageUserShadow from '@/pages/parts/Box2LineLargeImageUserShadow.vue';
+import SimpleDropDownPicker from '@/common/components/SimpleDropDownPicker.vue';
+
+const categoryData =  [
+    { id: 290, name: '全部' },
+    { id: 291, name: '闽南音乐' },
+    { id: 187, name: '讲古' },
+    { id: 292, name: '方言' },
+    { id: 293, name: '民俗习俗' },
+  ]
+const searchValue = ref('');
+const tab = ref(0)
+const tabs = [
+  {
+    name: '不可移动文物'
+  },
+  {
+    name: '可移动文物'
+  },
+];
+const listLoader = useSimplePageListLoader<{
+  id: number,
+  image: string,
+  name: string
+}>(8, async (page, pageSize) => {
+  let api;
+  switch (tab.value) {
+    default:
+    case 0: api = UnmoveableContent; break; 
+    case 1: api = MoveableContent; break; 
+  }
+  const res = await api.getContentList(new GetContentListParams().setSelfValues({
+    //keywords: searchValue.value,
+  }), page, pageSize);
+  return res.list.map((item) => {
+    return {
+      id: item.id,
+      image: item.image,
+      name: item.title,
+    }
+  })
+});
+
+watch(tab, () => {
+  listLoader.loadData(undefined, true);
+}, { immediate: true });
+
+function doSearch() {
+  
+}
+function goDetails(id: number) {
+  navTo('details', { id })
+}
+</script>

+ 4 - 1
src/pages/parts/Box1AudioPlay.vue

@@ -1,5 +1,8 @@
 <template>
-    <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base p-25">
+    <view 
+      class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base p-25"
+      @click="$emit('click')"
+    >
     <image class="width-150 height-150 radius-base" :src="image" mode="aspectFill" />
     <view class="d-flex flex-col ml-25 flex-one">
       <text class="color-second-text">{{ title }}</text>

+ 4 - 1
src/pages/parts/Box2LineImageRightShadow.vue

@@ -1,5 +1,8 @@
 <template>
-  <view class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2 pt-3 pb-3">
+  <view 
+    class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2 pt-3 pb-3"
+    @click="$emit('click')"
+  >
     <view class="d-flex flex-row">
       <image class="width-100 height-100 radius-base" :src="image" mode="aspectFill" />
       <view class="d-flex flex-col ml-3 flex-one">

+ 4 - 1
src/pages/parts/Box2LineLargeImageUserShadow.vue

@@ -1,5 +1,8 @@
 <template>
-  <view :class="'position-relative grid4-item d-flex flex-col shadow radius-l bg-base p-2 mb-2 ' + classNames">
+  <view 
+    :class="'position-relative grid4-item d-flex flex-col shadow-l radius-l bg-base p-2 mb-2 ' + classNames"
+    @click="$emit('click')"
+  >
     <image class="w-100 height-300 radius-base" :src="image" mode="aspectFill" />
     <image 
       v-if="videoMark" 

+ 4 - 1
src/pages/parts/Box2LinePlayRightArrow.vue

@@ -1,5 +1,8 @@
 <template>
-  <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-2 p-2">
+  <view 
+    class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-2 p-2"
+    @click="$emit('click')"
+  >
     <image class="width-100 height-100 radius-base" src="/static/images/discover/PlayButtonLarge.png" mode="aspectFill" />
     <view class="d-flex flex-col ml-3 flex-one">
       <text class="color-primary">{{ title }}</text>

+ 5 - 2
src/pages/parts/Box2LineRightShadow.vue

@@ -1,6 +1,9 @@
 <template>
-  <view class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2">
-   <view class="d-flex flex-row">
+  <view 
+    class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2"
+    @click="$emit('click')"
+  >
+    <view class="d-flex flex-row">
       <slot name="left" />
       <view class="d-flex flex-col ml-3 flex-one">
         <text class="color-primary">{{ title }}</text>

+ 4 - 1
src/pages/parts/Box2LineRightSlot.vue

@@ -1,5 +1,8 @@
 <template>
-  <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-2 p-2 pb-3 pt-3">
+  <view 
+    class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-2 p-2 pb-3 pt-3"
+    @click="$emit('click')"
+  >
     <view class="d-flex flex-col ml-3 flex-one">
       <text class="color-primary">{{ title }}</text>
       <text class="color-primary-second-text">{{ desc }}</text>