From a403393c1190994b473e679e1751794d9a1b9502 Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期二, 01 七月 2025 10:36:07 +0800
Subject: [PATCH] add: 分享+景点管理
---
components/card/localtion-card.vue | 95 +++++++
pages/home/home.vue | 2
static/common/parking.png | 0
static/common/wechat.png | 0
components/title/section-title.vue | 1
pages/home/home-main.vue | 65 ++++
pages.json | 26 +
static/common/visit.png | 0
sub-pages/hot-spot/index.vue | 100 +++++++
components/share-popup.vue | 46 +++
types/index.ts | 51 +++
sub-pages/film-list/film-detail.vue | 10
sub-pages/film-list/film-list.vue | 1
static/common/link.png | 0
sub-pages/hot-spot/spot-detail.vue | 366 ++++++++++++++++++++++++++++
sub-pages/utils/api.ts | 15 +
static/common/wechat-moments.png | 0
17 files changed, 755 insertions(+), 23 deletions(-)
diff --git a/components/card/localtion-card.vue b/components/card/localtion-card.vue
new file mode 100644
index 0000000..32a9584
--- /dev/null
+++ b/components/card/localtion-card.vue
@@ -0,0 +1,95 @@
+<template>
+ <view class="card" @click="handleClick(item)">
+ <view class="image-wrapper">
+ <image :src="item.locationUrl" mode="widthFix" class="card-image" />
+ </view>
+ <view class="card-title">
+ <up-text :lines="2" size="14px" :text="item.locationName" bold></up-text>
+ </view>
+ <view class="card-footer">
+ <view class="user-info">
+ <view class="user-text">
+ <text class="nickname">{{ item.address }}</text>
+ </view>
+ </view>
+ <view class="opera-info">
+ <up-icon name="heart" size="30rpx" color="#999" />
+ <text>{{ item.locationWeight }}</text>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script setup lang="ts">
+defineProps<{
+ item: any
+}>()
+
+const emit = defineEmits(['click'])
+const handleClick = (item: any) => {
+ emit('click', item)
+}
+</script>
+
+<style scoped lang="scss">
+.card {
+ border-radius: 10rpx;
+ background-color: #ffffff;
+ font-size: 14px;
+ line-height: 20px;
+ color: rgb(51, 51, 51);
+ margin: 10rpx;
+
+ .image-wrapper {
+ width: 100%;
+ position: relative;
+ display: inline-block;
+
+ .card-image {
+ width: 100%;
+ border-radius: inherit;
+ }
+
+ }
+
+
+ .card-title {
+ padding: 10rpx;
+ font-weight: 500;
+ }
+
+ .card-footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10rpx;
+ }
+
+ .user-info {
+ display: flex;
+ align-items: center;
+
+ .user-text {
+ font-size: 18rpx;
+ line-height: 14px;
+ margin-left: 10rpx;
+
+ .nickname {
+ font-weight: bold;
+ display: block;
+ color: #646464;
+ }
+ }
+ }
+
+ .opera-info {
+ display: flex;
+ align-items: center;
+
+ text {
+ margin-left: 10rpx;
+ font-size: 12px;
+ }
+ }
+}
+</style>
\ No newline at end of file
diff --git a/components/share-popup.vue b/components/share-popup.vue
index 9cd2ef9..f316f4d 100644
--- a/components/share-popup.vue
+++ b/components/share-popup.vue
@@ -4,14 +4,16 @@
<view class="share-content">
<view class="share-title">分享到</view>
<view class="share-options">
- <button class="share-item" open-type="share" @click="handleShare('wechat')">
+ <!-- 分享给好友 -->
+ <button class="share-item" open-type="share">
<image src="/static/common/wechat.png" class="share-icon" />
<text>微信好友</text>
</button>
- <button class="share-item" open-type="share" @click="handleShare('moments')">
+ <!-- 分享到朋友圈 -->
+ <view class="share-item" @click="handleShareTimeline">
<image src="/static/common/wechat-moments.png" class="share-icon" />
<text>朋友圈</text>
- </button>
+ </view>
<view class="share-item" @click="handleCopyLink">
<image src="/static/common/link.png" class="share-icon" />
<text>复制链接</text>
@@ -48,10 +50,40 @@
emit('update:show', false)
}
-// 处理分享
-const handleShare = (type: 'wechat' | 'moments') => {
- // 小程序分享通过页面配置和按钮的 open-type="share" 实现
- // 分享内容在页面的 onShareAppMessage 中配置
+// 处理分享到朋友圈
+const handleShareTimeline = () => {
+ // #ifdef MP-WEIXIN
+ // 使用微信原生朋友圈分享
+ wx.openChannelsActivity({
+ finderUserName: '', // 视频号用户名,可选
+ success: (res) => {
+ console.log('打开朋友圈成功', res)
+ uni.showToast({
+ title: '已打开朋友圈',
+ icon: 'success'
+ })
+ },
+ fail: (err) => {
+ console.error('打开朋友圈失败', err)
+ // 如果打开失败,尝试使用小程序分享
+ uni.showModal({
+ title: '提示',
+ content: '无法直接打开朋友圈,请点击右上角分享到朋友圈',
+ showCancel: false
+ })
+ }
+ })
+ // #endif
+
+ // #ifndef MP-WEIXIN
+ // 非微信小程序环境
+ uni.showToast({
+ title: '请点击右上角分享到朋友圈',
+ icon: 'none',
+ duration: 2000
+ })
+ // #endif
+
closePopup()
}
diff --git a/components/title/section-title.vue b/components/title/section-title.vue
index d3fbf41..8e101ac 100644
--- a/components/title/section-title.vue
+++ b/components/title/section-title.vue
@@ -53,6 +53,7 @@
})
function go(url: string) {
+ console.log("url",url)
if (url) {
uni.navigateTo({
url
diff --git a/pages.json b/pages.json
index 1ebaad6..6a19d6c 100644
--- a/pages.json
+++ b/pages.json
@@ -52,7 +52,9 @@
"path": "film-detail",
"style": {
"navigationBarTitleText": "",
- "enablePullDownRefresh": true
+ "enablePullDownRefresh": true,
+ "enableShareTimeline": true,
+ "enableShareAppMessage": true
}
}
,{
@@ -122,6 +124,28 @@
}
]
}
+ ,{
+ "root": "sub-pages/hot-spot",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "场景博物馆",
+ "enablePullDownRefresh": true
+ }
+ }
+ ,{
+ "path": "spot-detail",
+ "style": {
+ "navigationBarTitleText": "",
+ "enablePullDownRefresh": true,
+ "enableShareTimeline": true,
+ "enableShareAppMessage": true
+ }
+ }
+ ]
+ }
+
],
"globalStyle": {
"navigationBarTextStyle": "black",
diff --git a/pages/home/home-main.vue b/pages/home/home-main.vue
index 3e545c6..e809a9b 100644
--- a/pages/home/home-main.vue
+++ b/pages/home/home-main.vue
@@ -2,23 +2,26 @@
<view>
<!-- <view class="card" v-if="!showVideo"> -->
<view class="card">
- <view class="main-title">每一帧画面,都藏着一个等待探索的世界</view>
+ <view class="main-title">{{ config.mainTitle }}</view>
<view class="sub-title">
- 从经典场景到幕后故事,开启你的专属影视朝圣之旅
+ {{ config.subTitle }}
</view>
<view class="btn-group">
<view class="custom-btn explore-btn" @click="startExplore">
- <text class="btn-text">开始探索</text>
- <up-icon name="play-right-fill" size="34rpx" color="black" class="btn-icon" />
+ <text class="btn-text">{{ config.btnText1 }}</text>
+ <up-icon
+ :name="config.btnIcon1"
+ :color="config.iconColor1"
+ size="34rpx" class="btn-icon" />
</view>
<view class="custom-btn route-btn" @click="hotRoute">
- <text class="btn-text">热门路线</text>
+ <text class="btn-text">{{ config.btnText2 }}</text>
<up-icon
- name="/static/common/road-map-fill.png"
+ :name="config.btnIcon2"
+ :color="config.iconColor2"
size="34rpx"
- color="white"
class="btn-icon"
/>
</view>
@@ -54,7 +57,9 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
-
+ import { onLoad } from '@dcloudio/uni-app'
+ import { useGlobal } from '@/composables/useGlobal'
+ const { $http, $message, $store } = useGlobal()
const showVideo = ref(false)
const currentIndex = ref(0)
@@ -70,7 +75,17 @@
]
const currentVideo = computed(() => videoList[currentIndex.value])
-
+ // 添加配置响应式对象
+ const config = ref({
+ mainTitle: '每一帧画面,都藏着一个等待探索的世界',
+ subTitle: '从经典场景到幕后故事,开启你的专属影视朝圣之旅',
+ btnText1: '开始探索',
+ btnText2: '热门路线',
+ btnIcon1: 'play-right-fill',
+ btnIcon2: '/static/common/road-map-fill.png',
+ iconColor1: 'black',
+ iconColor2: 'white'
+ })
function startExplore() {
// 跳转到具体页面
uni.navigateTo({
@@ -89,6 +104,38 @@
icon: 'none',
})
}
+
+ onLoad((options: any) => {
+ getHomeConfig()
+ })
+
+ // 获取首页配置信息
+ const getHomeConfig = async () => {
+ try {
+ const { code, data } = await $http.request(
+ 'get',
+ '/api/home/homeConfig/info',
+ {}
+ )
+ if (code == 0) {
+ console.log("接口返回数据:", data);
+ // 只更新接口返回的有效字段
+ Object.keys(config.value).forEach(key => {
+ const newValue = data[key];
+ console.log(`字段 ${key}: 接口值=${newValue}, 本地值=${config.value[key]}`);
+ if (newValue !== undefined && newValue !== null && newValue !== '') {
+ config.value[key] = newValue;
+ }
+ });
+ console.log("首页配置加载成功", config.value)
+ } else {
+ }
+ } catch (error) {
+ console.error('配置请求失败', error)
+ }
+ }
+
+
</script>
<style scoped>
.card {
diff --git a/pages/home/home.vue b/pages/home/home.vue
index a1f260e..7095440 100644
--- a/pages/home/home.vue
+++ b/pages/home/home.vue
@@ -35,7 +35,7 @@
<SectionTitle title="全球影视地标" optitle="查看全部" goUrl="/pages/home/home-more" />
<GlobalGeo />
- <SectionTitle title="场景博物馆" optitle="查看全部" goUrl="/pages/home/home-more" />
+ <SectionTitle title="场景博物馆" optitle="查看全部" goUrl="/sub-pages/hot-spot/index" />
<SceneMuseumCard v-for="(item, index) in cardList" :key="index" :image="item.image" :title="item.title"
:subtitle="item.subtitle" :readTime="item.readTime" />
diff --git a/static/common/link.png b/static/common/link.png
new file mode 100644
index 0000000..a08c7a1
--- /dev/null
+++ b/static/common/link.png
Binary files differ
diff --git a/static/common/parking.png b/static/common/parking.png
new file mode 100644
index 0000000..1425c94
--- /dev/null
+++ b/static/common/parking.png
Binary files differ
diff --git a/static/common/visit.png b/static/common/visit.png
new file mode 100644
index 0000000..614b53b
--- /dev/null
+++ b/static/common/visit.png
Binary files differ
diff --git a/static/common/wechat-moments.png b/static/common/wechat-moments.png
new file mode 100644
index 0000000..cb131fb
--- /dev/null
+++ b/static/common/wechat-moments.png
Binary files differ
diff --git a/static/common/wechat.png b/static/common/wechat.png
new file mode 100644
index 0000000..68bbedb
--- /dev/null
+++ b/static/common/wechat.png
Binary files differ
diff --git a/sub-pages/film-list/film-detail.vue b/sub-pages/film-list/film-detail.vue
index 3d89490..2d73253 100644
--- a/sub-pages/film-list/film-detail.vue
+++ b/sub-pages/film-list/film-detail.vue
@@ -183,7 +183,8 @@
title: filmInfo.value?.coverTitle || '分享内容',
desc: filmInfo.value?.filmContent?.substring(0, 50) || '',
image: filmPictureList.value[0] || '',
- url: `https://您的域名/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`
+ // url: `http://您的域名/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`
+ url: `/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`
}
showSharePopup.value = true
}
@@ -193,7 +194,9 @@
const copyLink = () => {
sharePopupShow.value = false
uni.setClipboardData({
- data: `https://你的域名/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`,
+ // data: `http://14.103.144.28/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`,
+ // 此处应该是一个小程序的外链
+ data: `http://14.103.144.28/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`,
success: () => $message.showToast('链接已复制')
})
}
@@ -426,7 +429,8 @@
return {
title: filmInfo.value?.coverTitle || '分享内容',
query: `id=${filmInfo.value?.id}`,
- imageUrl: filmPictureList.value[0] || ''
+ imageUrl: filmPictureList.value[0] || '',
+ desc: filmInfo.value?.filmContent?.substring(0, 50) || ''
}
}
})
diff --git a/sub-pages/film-list/film-list.vue b/sub-pages/film-list/film-list.vue
index 3987c0d..3257cd1 100644
--- a/sub-pages/film-list/film-list.vue
+++ b/sub-pages/film-list/film-list.vue
@@ -119,6 +119,7 @@
type: '',
current: filmPage.value,
size: filmSize,
+ status: 'published',
keywords: keywords.value // 关键修改
};
const records = await getFilmWorksBase(query)
diff --git a/sub-pages/hot-spot/index.vue b/sub-pages/hot-spot/index.vue
new file mode 100644
index 0000000..b6ac4cf
--- /dev/null
+++ b/sub-pages/hot-spot/index.vue
@@ -0,0 +1,100 @@
+<template>
+ <view :class="['app', theme]">
+ <view style="padding-top: 10rpx;">
+ <up-search height="70rpx" placeholder="搜索" search-icon-size="40rpx" margin="0rpx 30rpx" v-model="search"
+ :show-action="true" @search="onSearch" />
+ </view>
+ <view class="list-view">
+ <up-waterfall v-model="films">
+ <template #left="{ leftList }">
+ <LocaltionCard v-for="(item, index) in leftList" :key="index" :item="item" @click="handleDetailClick(item)" />
+ </template>
+ <template #right="{ rightList }">
+ <LocaltionCard v-for="(item, index) in rightList" :key="index" :item="item" @click="handleDetailClick(item)" />
+ </template>
+ </up-waterfall>
+ <up-loadmore :status="filmStatus" :line="true" />
+ </view>
+ </view>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { onLoad, onShow, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
+import { FilmLocationVO, FilmLocationQueryDTO } from '@/types/index'
+import { useGlobal } from '@/composables/useGlobal'
+const { $http, $message } = useGlobal()
+import { useNavigator } from '@/composables/useNavigator'
+const { navigateTo } = useNavigator()
+import { getFilmLocationBase } from '@/sub-pages/utils/api'
+import LocaltionCard from "../../components/card/localtion-card.vue";
+
+const theme = ref('light')
+const search = ref('')
+const films = ref<FilmLocationVO[]>([])
+const filmPage = ref(1)
+const filmSize = 10
+const filmStatus = ref('loading')
+
+const onSearch = () => {
+ filmPage.value = 1
+ films.value = []
+ filmStatus.value = 'loadmore'
+ getFilmLocation(search.value)
+}
+
+const handleDetailClick = (item: FilmLocationVO) => {
+ const url = `/sub-pages/hot-spot/spot-detail?id=${item.id}`
+ navigateTo(url)
+}
+
+onLoad(() => {
+ const storedTheme = uni.getStorageSync('theme') || 'light'
+ theme.value = storedTheme
+})
+
+onShow(() => {
+ getFilmLocation()
+})
+
+onPullDownRefresh(async () => {
+ filmPage.value = 1
+ getFilmLocation()
+ uni.stopPullDownRefresh()
+})
+
+onReachBottom(() => {
+ getFilmLocation()
+})
+
+const getFilmLocation = async (keyword = '') => {
+ if (filmStatus.value === 'nomore') return
+ filmStatus.value = 'loading'
+
+ try {
+ const query: FilmLocationQueryDTO = {
+ locationName: keyword,
+ current: filmPage.value,
+ size: filmSize,
+ isEnabled: 1
+ }
+ const records = await getFilmLocationBase(query)
+ if (records && records.length > 0) {
+ const existingIds = new Set(films.value.map(item => item.id))
+ const uniqueRecords = records.filter(item => !existingIds.has(item.id))
+ films.value = [...films.value, ...uniqueRecords]
+ if (records.length < filmSize) {
+ filmStatus.value = 'noMore'
+ }
+ filmPage.value++
+ } else {
+ filmStatus.value = 'noMore'
+ }
+ } catch (e) {
+ filmStatus.value = 'loadmore' // 重置状态允许重试
+ $message.error('加载失败,请重试')
+ }
+}
+</script>
+
+<style lang="scss" scoped></style>
\ No newline at end of file
diff --git a/sub-pages/hot-spot/spot-detail.vue b/sub-pages/hot-spot/spot-detail.vue
new file mode 100644
index 0000000..ff20930
--- /dev/null
+++ b/sub-pages/hot-spot/spot-detail.vue
@@ -0,0 +1,366 @@
+<template>
+ <view class="spot-detail-page">
+ <!-- 顶部信息 -->
+ <view class="header">
+ <view class="header-info">
+ <view class="geo-row">
+ <view class="geo-path">{{ geoPath }}</view>
+ <image src="/static/common/earth.png" class="earth-icon" />
+ </view>
+ <view class="title-row">
+ <view class="title">{{ location?.locationName || '景点详情' }}</view>
+ <up-icon name="heart" size="40rpx" :color="collected ? '#FF4D4F' : '#ccc'" @click="toggleCollect" />
+ </view>
+ </view>
+ </view>
+
+ <!-- 主图 -->
+ <view class="main-image">
+ <image :src="mainImage" mode="aspectFill" class="main-img" />
+ </view>
+
+ <!-- 地址、类型、电话、身份准入等 -->
+ <view class="info-list">
+ <view class="info-item">{{ location?.address }}</view>
+ <view class="info-item"><up-icon name="/static/common/marker.png" size="32rpx" /> {{ location?.sceneType || '类型未知' }}</view>
+ <view class="info-item"><up-icon name="/static/common/parking.png" size="32rpx" /> {{ location?.parkingInfo || '无电话' }}</view>
+ <view class="info-item"><up-icon name="/static/common/visit.png" size="32rpx" /> {{ location?.isOpenVisitStr === '是' ? '允许参观' : '不允许参观' }}</view>
+ </view>
+
+ <!-- 介绍描述 -->
+ <view class="divider-line"></view>
+ <view class="desc-block">
+ <text>{{ location?.landmarkDesc || location?.visitInfo || '暂无介绍' }}</text>
+ </view>
+
+ <!-- 地图 -->
+ <view class="map-block" v-if="showMap">
+ <!-- 腾讯地图小程序组件(uni-app中需配置腾讯地图key) -->
+ <map
+ :latitude="location?.gpsLat"
+ :longitude="location?.gpsLng"
+ :markers="mapMarkers"
+ style="width: 100%; height: 300rpx;"
+ v-if="location?.gpsLat && location?.gpsLng"
+ />
+ <image v-else src="/static/common/geo-earth.png" class="map-placeholder" />
+ </view>
+
+ <!-- 实景图 -->
+ <view class="scene-block" v-if="sceneImages.length">
+ <view class="scene-title">实景图 <text class="scene-count">{{ sceneImages.length }}</text></view>
+ <view class="scene-list">
+ <image
+ v-for="(img, idx) in sceneImages"
+ :key="idx"
+ :src="img"
+ mode="aspectFill"
+ class="scene-image"
+ @tap="previewScene(idx)"
+ />
+ </view>
+ </view>
+
+ <!-- 关联影视作品 -->
+ <view class="film-block" v-if="relatedFilms.length">
+ <view class="film-title">关联影视作品</view>
+ <view class="film-list">
+ <view class="film-item" v-for="film in relatedFilms" :key="film.id">
+ <image :src="film.coverUrl" class="film-cover" />
+ <view class="film-info">
+ <view class="film-name">{{ film.nameCn }}</view>
+ <view class="film-en">{{ film.nameEn }}</view>
+ <view class="film-meta">
+ <text>{{ film.typeStr }}</text>
+ <text v-if="film.country"> / {{ film.country }}</text>
+ <text v-if="film.releaseYear"> / {{ film.releaseYear }}</text>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import { useGlobal } from '@/composables/useGlobal'
+const { $http, $message } = useGlobal()
+import { FilmLocationVO, FilmWorks } from '@/types/index'
+
+const location = ref<FilmLocationVO>()
+const collected = ref(false)
+const geoPath = ref('亚洲-中国-海南省-海口市')
+const mainImage = ref('')
+const sceneImages = ref<string[]>([])
+const relatedFilms = ref<FilmWorks[]>([])
+const showMap = ref(true)
+
+
+onLoad(async (options: any) => {
+ const id = options.id
+ if (id) {
+ await getLocationDetail(id)
+ await getRelatedFilms(id)
+ }
+})
+
+const getLocationDetail = async (id: string) => {
+ const { code, data } = await $http.request('get', '/api/filmLocation/list/view', {
+ params: { id }
+ })
+ if (code === 0) {
+ location.value = data
+ // 主图优先locationUrl,其次visitorPhotos
+ if (data.locationUrl) {
+ mainImage.value = data.locationUrl
+ console.log(data.locationUrl)
+ console.log( mainImage.value)
+ } else if (data.visitorPhotos) {
+ try {
+ const arr = JSON.parse(data.visitorPhotos)
+ mainImage.value = arr[0]?.url || ''
+ } catch {
+ mainImage.value = ''
+ }
+ }
+ // 实景图
+ if (data.visitorPhotos) {
+ try {
+ const arr = JSON.parse(data.visitorPhotos)
+ sceneImages.value = arr.map((item: any) => item.url)
+ } catch {
+ sceneImages.value = []
+ }
+ } else {
+ sceneImages.value = []
+ }
+ // 拼接地理层级
+ geoPath.value = [
+ '亚洲',
+ '中国',
+ data.province,
+ data.city
+ ].filter(Boolean).join('-')
+ } else {
+ $message.showToast('获取景点信息失败')
+ }
+}
+
+// 地图标记
+const mapMarkers = ref([
+ {
+ id: 1,
+ latitude: location.value?.gpsLat,
+ longitude: location.value?.gpsLng,
+ iconPath: '/static/common/marker.png',
+ width: 40,
+ height: 40
+ }
+])
+
+const previewScene = (idx: number) => {
+ uni.previewImage({
+ current: sceneImages.value[idx],
+ urls: sceneImages.value
+ })
+}
+
+// 影视作品接口示例
+const getRelatedFilms = async (locationId: string) => {
+ // 假设接口 /api/filmWorks/related?locationId=xxx
+ const { code, data } = await $http.request('get', '/api/filmLocation/related', {
+ params: { locationId }
+ })
+ if (code === 0 && Array.isArray(data)) {
+ relatedFilms.value = data
+ } else {
+ relatedFilms.value = []
+ }
+}
+
+const toggleCollect = () => {
+ collected.value = !collected.value
+ $message.showToast(collected.value ? '已收藏' : '已取消收藏')
+}
+</script>
+
+<style scoped>
+.spot-detail-page {
+ background: #fff;
+ min-height: 100vh;
+}
+.header {
+ display: flex;
+ align-items: flex-start;
+ padding: 30rpx 20rpx 10rpx 20rpx;
+}
+.header-info {
+ flex: 1;
+ margin-left: 20rpx;
+}
+.geo-path {
+ color: #6c8fc5;
+ font-size: 22rpx;
+ margin-bottom: 10rpx;
+}
+.title-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 30rpx; /* 增加名称与上方的间距 */
+}
+.title {
+ font-size: 36rpx;
+ font-weight: bold;
+ margin-right: 16rpx;
+}
+.earth-icon {
+ width: 144rpx; /* 放大三倍 */
+ height: 144rpx;
+}
+.main-image {
+ width: 100%;
+ height: 320rpx;
+ margin-top: 40rpx; /* 增加名称和图片之间的间隔 */
+ margin-bottom: 40rpx;
+}
+.main-img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 10rpx;
+}
+/*.info-list {*/
+/* padding: 0 20rpx;*/
+/* margin-bottom: 20rpx;*/
+/*}*/
+/*.info-item {*/
+/* font-size: 28rpx;*/
+/* color: #333;*/
+/* margin-bottom: 16rpx;*/
+/* display: flex;*/
+/* align-items: center;*/
+/*}*/
+/*.desc-block {*/
+/* padding: 0 20rpx 30rpx 20rpx;*/
+/* color: #666;*/
+/* font-size: 26rpx;*/
+/*}*/
+.info-list {
+ padding: 20rpx; /* 增加内边距 */
+ margin: 20rpx 0; /* 调整上下外边距 */
+ background-color: #f9f9f9;
+ border-radius: 12rpx;
+}
+
+.info-item {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 20rpx; /* 调整间距 */
+ display: flex;
+ align-items: center;
+ line-height: 1.6;
+}
+
+.info-item:last-child {
+ margin-bottom: 0;
+}
+
+/* 添加分割线样式 */
+.divider-line {
+ height: 1px;
+ background-color: #eee;
+ margin: 30rpx 20rpx 20rpx 20rpx;
+}
+
+/* 调整描述区块的间距 */
+.desc-block {
+ padding: 0 20rpx 30rpx 20rpx;
+ color: #666;
+ font-size: 26rpx;
+ line-height: 1.8;
+ margin-top: 20rpx;
+}
+.map-block {
+ margin: 20rpx 0;
+}
+.map-placeholder {
+ width: 100%;
+ height: 300rpx;
+ object-fit: cover;
+ border-radius: 10rpx;
+}
+.scene-block {
+ padding: 0 20rpx 30rpx 20rpx;
+}
+.scene-title {
+ font-size: 28rpx;
+ font-weight: bold;
+ margin-bottom: 10rpx;
+}
+.scene-count {
+ color: #888;
+ font-size: 22rpx;
+ margin-left: 10rpx;
+}
+.scene-list {
+ display: flex;
+ gap: 20rpx;
+ flex-wrap: wrap;
+}
+.scene-image {
+ width: 45vw;
+ height: 140rpx;
+ object-fit: cover;
+ border-radius: 8rpx;
+ margin-bottom: 10rpx;
+}
+.film-block {
+ padding: 0 20rpx 30rpx 20rpx;
+}
+.film-title {
+ font-size: 28rpx;
+ font-weight: bold;
+ margin-bottom: 10rpx;
+}
+.film-list {
+ display: flex;
+ flex-direction: column;
+ gap: 20rpx;
+}
+.film-item {
+ display: flex;
+ align-items: flex-start;
+ gap: 20rpx;
+}
+.film-cover {
+ width: 120rpx;
+ height: 160rpx;
+ object-fit: cover;
+ border-radius: 8rpx;
+}
+.film-info {
+ flex: 1;
+}
+.film-name {
+ font-size: 28rpx;
+ font-weight: bold;
+}
+.film-en {
+ font-size: 22rpx;
+ color: #888;
+ margin-bottom: 6rpx;
+}
+.film-meta {
+ font-size: 22rpx;
+ color: #888;
+}
+.geo-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 15rpx;
+}
+</style>
\ No newline at end of file
diff --git a/sub-pages/utils/api.ts b/sub-pages/utils/api.ts
index 4dcc8a9..0316dea 100644
--- a/sub-pages/utils/api.ts
+++ b/sub-pages/utils/api.ts
@@ -83,4 +83,17 @@
message.showToast('系统异常,无法获取数据');
return null;
}
- }
\ No newline at end of file
+ }
+
+export const getFilmLocationBase = async (query: FilmWorksQueryDTO) => {
+ const { code, data } = await http.request('get', '/api/filmLocation/list', {
+ params: query
+ });
+
+ if (code === 0) {
+ return data.records;
+ } else {
+ message.showToast('系统异常,无法获取数据');
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/types/index.ts b/types/index.ts
index f214c6d..7ba6aaa 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -304,4 +304,53 @@
size: number;
url: string;
status: string;
- }
\ No newline at end of file
+ }
+
+
+export interface FilmLocationVO {
+ address?: string,
+ arEntry?: string,
+ checkinCount?: number,
+ city?: string,
+ classicScene?: string,
+ endDate?: string,
+ filmId?: number,
+ gpsLat?: number,
+ gpsLng?: number,
+ id?: number,
+ isEnabled?: boolean,
+ isOpenVisit?: string,
+ isOpenVisitStr?: string,
+ landmarkDesc?: string,
+ locationName?: string,
+ locationUrl?: string,
+ locationWeight?: number,
+ operationWeight?: number,
+ parkingInfo?: string,
+ province?: string,
+ region?: string,
+ sceneType?: string,
+ startDate?: string,
+ surroundingFacilities?: string,
+ transportGuide?: string,
+ visitInfo?: string,
+ visitorPhotos?: string
+}
+
+export interface FilmWorksQueryDTO extends PaginationQuery {
+
+ /** 拍摄地点名称 */
+ locationName?: string;
+
+ /** 所在省 */
+ province?: string;
+
+ /** 所在市 */
+ city?: string;
+
+ /** 所在区 */
+ region?: string;
+
+ /** 启用/禁用(USER_ENABLED_OR_DISABLED) */
+ isEnabled?: boolean;
+}
--
Gitblit v1.9.3