fix:修复bug
This commit is contained in:
+124
-6
@@ -6,9 +6,18 @@
|
||||
<map id="map" class="native-map" :longitude="mapCenter.longitude" :latitude="mapCenter.latitude"
|
||||
:markers="mapMarkers" :scale="mapZoom" :show-location="false" @regionchange="onMapRegionChange"
|
||||
@markertap="onMapMarkerTap" @callouttap="onCalloutTap" @updated="onMapUpdated" @error="onMapError">
|
||||
<!-- 覆盖在地图上的可点击控件(使用 cover-view 以兼容小程序原生组件层级) -->
|
||||
<cover-view class="index-swiper" v-if="!props.hideControls && !props.hideMapOverlays" @tap="handleJoinTap">
|
||||
<cover-image src="/static/index_swiper.png" class="index-swiper-img" mode="aspectFit"></cover-image>
|
||||
<!-- 覆盖在地图上的广告轮播(使用 cover-view 以兼容小程序原生组件层级) -->
|
||||
<cover-view class="index-swiper" v-if="!props.hideControls && !props.hideMapOverlays && currentBannerImage">
|
||||
<cover-image :src="currentBannerImage" class="index-swiper-img" mode="aspectFill" @tap="handleBannerTap"></cover-image>
|
||||
<!-- 轮播指示器 -->
|
||||
<cover-view class="banner-indicators" v-if="props.bannerImages.length > 1">
|
||||
<cover-view
|
||||
v-for="(img, idx) in props.bannerImages"
|
||||
:key="idx"
|
||||
class="indicator-dot"
|
||||
:class="{ active: idx === currentBannerIndex }">
|
||||
</cover-view>
|
||||
</cover-view>
|
||||
</cover-view>
|
||||
|
||||
<!-- 地图中心固定定位图标 -->
|
||||
@@ -105,8 +114,12 @@
|
||||
hideMapOverlays: {
|
||||
type: Boolean,
|
||||
default: false // 是否隐藏地图上的覆盖层元素(如中心定位图标、轮播图等)
|
||||
},
|
||||
bannerImages: {
|
||||
type: Array,
|
||||
default: () => [] // 广告图片列表
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits([
|
||||
@@ -114,7 +127,8 @@
|
||||
'scan',
|
||||
'showList',
|
||||
'markerTap',
|
||||
'mapCenterChange'
|
||||
'mapCenterChange',
|
||||
'bannerClick'
|
||||
])
|
||||
|
||||
// 响应式数据
|
||||
@@ -126,6 +140,17 @@
|
||||
const mapZoom = ref(17)
|
||||
const mapMarkers = ref([]) // 用于地图组件的markers
|
||||
const mapContext = ref(null) // 地图上下文
|
||||
const currentBannerIndex = ref(0) // 当前显示的广告索引
|
||||
let bannerTimer = null // 广告轮播定时器
|
||||
|
||||
// 计算当前显示的广告图片
|
||||
const currentBannerImage = computed(() => {
|
||||
if (props.bannerImages && props.bannerImages.length > 0) {
|
||||
return props.bannerImages[currentBannerIndex.value]
|
||||
}
|
||||
// 降级:如果没有广告,显示默认图片
|
||||
return '/static/index_swiper.png'
|
||||
})
|
||||
|
||||
// 验证坐标有效性
|
||||
const isValidCoordinate = (lat, lng) => {
|
||||
@@ -220,6 +245,26 @@
|
||||
deep: true
|
||||
})
|
||||
|
||||
// 监听广告图片变化,启动或停止轮播
|
||||
watch(() => props.bannerImages, (newImages, oldImages) => {
|
||||
console.log('广告图片变化:', newImages?.length, '张')
|
||||
// 先停止旧的轮播
|
||||
stopBannerRotation()
|
||||
currentBannerIndex.value = 0
|
||||
|
||||
// 如果有多张图片,启动新的轮播
|
||||
if (newImages && newImages.length > 1) {
|
||||
console.log('启动广告轮播,共', newImages.length, '张图片')
|
||||
// 使用 nextTick 确保 DOM 已更新
|
||||
nextTick(() => {
|
||||
startBannerRotation()
|
||||
})
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
deep: true
|
||||
})
|
||||
|
||||
// 地图加载完成事件
|
||||
const onMapUpdated = () => {
|
||||
isLoading.value = false
|
||||
@@ -337,6 +382,44 @@ const handleSearch = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 处理广告点击
|
||||
const handleBannerTap = () => {
|
||||
console.log('点击地图广告:', currentBannerIndex.value, currentBannerImage.value)
|
||||
// 触发父组件处理点击事件
|
||||
emit('bannerClick', currentBannerIndex.value)
|
||||
// 默认跳转到合作加盟页面
|
||||
handleJoinTap()
|
||||
}
|
||||
|
||||
// 启动广告轮播
|
||||
const startBannerRotation = () => {
|
||||
// 如果只有一张或没有图片,不需要轮播
|
||||
if (!props.bannerImages || props.bannerImages.length <= 1) {
|
||||
console.log('图片数量不足,不启动轮播')
|
||||
return
|
||||
}
|
||||
|
||||
// 清除旧的定时器
|
||||
stopBannerRotation()
|
||||
|
||||
console.log('开始广告轮播定时器')
|
||||
// 每3秒切换一次
|
||||
bannerTimer = setInterval(() => {
|
||||
const nextIndex = (currentBannerIndex.value + 1) % props.bannerImages.length
|
||||
console.log('轮播切换:', currentBannerIndex.value, '->', nextIndex)
|
||||
currentBannerIndex.value = nextIndex
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
// 停止广告轮播
|
||||
const stopBannerRotation = () => {
|
||||
if (bannerTimer) {
|
||||
console.log('停止广告轮播')
|
||||
clearInterval(bannerTimer)
|
||||
bannerTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
const handleScan = () => {
|
||||
emit('scan')
|
||||
}
|
||||
@@ -364,6 +447,12 @@ const handleSearch = () => {
|
||||
if (collapseRef.value) {
|
||||
collapseRef.value.init()
|
||||
}
|
||||
|
||||
// 初始化广告轮播
|
||||
if (props.bannerImages && props.bannerImages.length > 1) {
|
||||
console.log('onMounted: 初始化广告轮播')
|
||||
startBannerRotation()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -373,6 +462,8 @@ const handleSearch = () => {
|
||||
clearTimeout(regionChangeTimer)
|
||||
regionChangeTimer = null
|
||||
}
|
||||
// 停止广告轮播
|
||||
stopBannerRotation()
|
||||
mapContext.value = null
|
||||
})
|
||||
|
||||
@@ -554,15 +645,42 @@ const handleSearch = () => {
|
||||
border-radius: 20rpx;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
// top: 10rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
|
||||
&-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.banner-indicators {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
z-index: 2;
|
||||
|
||||
.indicator-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
width: 24rpx;
|
||||
border-radius: 6rpx;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
// export const URL = "https://my.gxfs123.com/api" //正式服务器-弃用
|
||||
export const URL = "https://manager.fdzpower.com/api" //正式服务器
|
||||
// export const URL = "https://fansdev.gxfs123.com/api" //测试服务器
|
||||
// export const URL = "https://manager.fdzpower.com/api" //正式服务器
|
||||
export const URL = "https://fansdev.gxfs123.com/api" //测试服务器
|
||||
// export const URL = "http://192.168.5.30:8080" //本地调试
|
||||
// export const URL = "http://127.0.0.1:8080" //本地调试
|
||||
|
||||
export const appid = "wx2165f0be356ae7a9" //小程序appid
|
||||
export const appid = "wx2165f0be356ae7a9" //微信小程序appid
|
||||
export const ZFBappid = "2021006117693332" //支付宝小程序appid
|
||||
+11
-2
@@ -233,7 +233,13 @@ export default {
|
||||
cancelFailedContactService: 'Cancel failed, please contact customer service',
|
||||
getOrderStatusFailed: 'Failed to get order status',
|
||||
syncSuccess: 'Status synced successfully',
|
||||
syncFailed: 'Sync failed'
|
||||
syncFailed: 'Sync failed',
|
||||
freeRentTime: 'Free Time',
|
||||
pricingRule: 'Pricing Rule',
|
||||
paymentMethod: 'Payment Method',
|
||||
perHour: 'per hour',
|
||||
perMinute: 'per minute',
|
||||
perHalfHour: 'per half hour'
|
||||
},
|
||||
|
||||
user: {
|
||||
@@ -556,7 +562,10 @@ export default {
|
||||
daysAgo: 'days ago',
|
||||
yesterday: 'Yesterday',
|
||||
today: 'Today',
|
||||
tomorrow: 'Tomorrow'
|
||||
tomorrow: 'Tomorrow',
|
||||
hours: 'hour(s)',
|
||||
minutes: 'minute(s)',
|
||||
halfHours: 'half hour(s)'
|
||||
},
|
||||
|
||||
unit: {
|
||||
|
||||
+11
-2
@@ -233,7 +233,13 @@ export default {
|
||||
cancelFailedContactService: '取消订单失败,请联系客服',
|
||||
getOrderStatusFailed: '订单状态查询失败',
|
||||
syncSuccess: '状态同步成功',
|
||||
syncFailed: '同步状态失败'
|
||||
syncFailed: '同步状态失败',
|
||||
freeRentTime: '免费时长',
|
||||
pricingRule: '计费规则',
|
||||
paymentMethod: '支付方式',
|
||||
perHour: '每小时',
|
||||
perMinute: '每分钟',
|
||||
perHalfHour: '每半小时'
|
||||
},
|
||||
|
||||
user: {
|
||||
@@ -556,7 +562,10 @@ export default {
|
||||
daysAgo: '天前',
|
||||
yesterday: '昨天',
|
||||
today: '今天',
|
||||
tomorrow: '明天'
|
||||
tomorrow: '明天',
|
||||
hours: '小时',
|
||||
minutes: '分钟',
|
||||
halfHours: '半小时'
|
||||
},
|
||||
|
||||
unit: {
|
||||
|
||||
+5
-1
@@ -69,7 +69,11 @@
|
||||
"requiredPrivateInfos" : [ "getLocation", "chooseLocation" ]
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
"usingComponents" : true,
|
||||
"appid" : "2021006117693332",
|
||||
"unipush" : {
|
||||
"enable" : true
|
||||
}
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
|
||||
+103
-13
@@ -21,9 +21,10 @@
|
||||
<!-- 全屏地图组件 -->
|
||||
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||
:enableMarkers="true" :hideMapOverlays="showGuidePopup || showNoticePopup || showActivityPopup"
|
||||
:enableMarkers="true" :bannerImages="bannerImages"
|
||||
:hideMapOverlays="showGuidePopup || showNoticePopup || showActivityPopup"
|
||||
@relocate="handleRelocate" @scan="handleScan" @showList="showLocationList" @markerTap="selectPosition"
|
||||
@mapCenterChange="onMapCenterChange" />
|
||||
@mapCenterChange="onMapCenterChange" @bannerClick="handleBannerClick" />
|
||||
|
||||
<!-- 地图加载状态 -->
|
||||
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
||||
@@ -200,7 +201,6 @@
|
||||
getPotionsDetail
|
||||
} from '../../config/api/order.js'
|
||||
import {
|
||||
getNoticeTextData,
|
||||
getActiveActivity
|
||||
} from '../../config/api/system.js'
|
||||
// 导入地图工具函数
|
||||
@@ -291,25 +291,110 @@
|
||||
}
|
||||
|
||||
const noticeText = ref('')
|
||||
const getNoticeText = async () => {
|
||||
const parasm = {
|
||||
'title': '用户端公告'
|
||||
const bannerImages = ref([]) // 首页广告图片列表
|
||||
|
||||
// 将语言代码转换为后端接受的格式
|
||||
const convertLanguageCode = (lang) => {
|
||||
// zh-CN -> zh_CN (转换下划线)
|
||||
// en-US -> en_US (转换下划线)
|
||||
return lang.replace(/-/g, '_')
|
||||
}
|
||||
const res = await getNoticeTextData(parasm);
|
||||
noticeText.value = res.data.noticeContent;
|
||||
|
||||
// 获取公告内容(支持多语言)
|
||||
const getNoticeText = async () => {
|
||||
try {
|
||||
// 获取当前语言设置
|
||||
const currentLang = uni.getStorageSync('language') || 'zh-CN'
|
||||
const languageCode = convertLanguageCode(currentLang)
|
||||
|
||||
console.log('加载公告,语言:', currentLang, '转换后:', languageCode)
|
||||
|
||||
// 调用接口获取公告内容
|
||||
const res = await uni.request({
|
||||
url: `${URL}/device/announcementConfig/current`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Content-Language': languageCode
|
||||
},
|
||||
data: {
|
||||
type: 'wx_user_type' // 微信小程序用户端
|
||||
}
|
||||
})
|
||||
|
||||
console.log('公告响应:', res)
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200 && res.data.data) {
|
||||
// 使用后端自动解析的 announcement 字段
|
||||
const announcement = res.data.data.announcement || ''
|
||||
noticeText.value = announcement
|
||||
|
||||
// 设置通知栏高度
|
||||
if (res.data.noticeContent) {
|
||||
if (announcement) {
|
||||
noticeHeight.value = 50 // 通知栏高度约50px
|
||||
}
|
||||
|
||||
// 将通知内容存储到本地缓存
|
||||
try {
|
||||
uni.setStorageSync('noticeContent', res.data.noticeContent);
|
||||
console.log('通知内容已缓存:', res.data.noticeContent);
|
||||
uni.setStorageSync('noticeContent', announcement)
|
||||
console.log('通知内容已缓存:', announcement)
|
||||
} catch (e) {
|
||||
console.warn('缓存通知内容失败:', e);
|
||||
console.warn('缓存通知内容失败:', e)
|
||||
}
|
||||
} else {
|
||||
console.warn('获取公告失败:', res.data?.msg || '未知错误')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取公告失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取首页广告图片(支持多语言)
|
||||
const getBannerImages = async () => {
|
||||
try {
|
||||
// 获取当前语言设置
|
||||
const currentLang = uni.getStorageSync('language') || 'zh-CN'
|
||||
const languageCode = convertLanguageCode(currentLang)
|
||||
|
||||
console.log('加载首页广告,语言:', currentLang, '转换后:', languageCode)
|
||||
|
||||
// 调用接口获取广告内容
|
||||
const res = await uni.request({
|
||||
url: `${URL}/device/advertisementConfig/current`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Content-Language': languageCode
|
||||
},
|
||||
data: {
|
||||
appPlatform: 'wechat', // 微信平台
|
||||
appType: 'user' // 用户端
|
||||
}
|
||||
})
|
||||
|
||||
console.log('首页广告响应:', res)
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200 && res.data.data) {
|
||||
// 使用 files 字段(图片列表)
|
||||
const files = res.data.data.files || []
|
||||
if (files.length > 0) {
|
||||
bannerImages.value = files
|
||||
console.log('首页广告加载成功,图片数量:', files.length)
|
||||
} else {
|
||||
console.warn('未获取到广告图片')
|
||||
}
|
||||
} else {
|
||||
console.warn('获取首页广告失败:', res.data?.msg || '未知错误')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取首页广告失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理首页广告点击
|
||||
const handleBannerClick = (index) => {
|
||||
console.log('点击首页广告:', index, bannerImages.value[index])
|
||||
// 可以根据需要添加跳转逻辑
|
||||
// 例如跳转到合作加盟页面
|
||||
uni.navigateTo({ url: '/pages/join/index' })
|
||||
}
|
||||
|
||||
// 查询最近的活动
|
||||
@@ -442,7 +527,12 @@
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
testDistanceCalculation()
|
||||
}
|
||||
await getNoticeText();
|
||||
|
||||
// 并行加载公告和广告(不依赖定位)
|
||||
await Promise.all([
|
||||
getNoticeText(),
|
||||
getBannerImages()
|
||||
])
|
||||
|
||||
// 1. 先获取用户位置
|
||||
await getUserLocationAndAddress()
|
||||
|
||||
+134
-27
@@ -1,40 +1,118 @@
|
||||
<template>
|
||||
<view class="loading-page">
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="loading" class="loading-page">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>{{ $t('common.loading') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<view v-else-if="error" class="error-page">
|
||||
<view class="error-content">
|
||||
<text class="error-icon">⚠️</text>
|
||||
<text class="error-message">{{ errorMessage }}</text>
|
||||
<button class="retry-btn" @click="loadAgreement">{{ $t('common.retry') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容显示 -->
|
||||
<view v-else class="legal-page">
|
||||
<view class="header">
|
||||
<text class="title">{{ agreementData.title || $t('legal.agreement') }}</text>
|
||||
<text v-if="agreementData.remark" class="subtitle">{{ agreementData.remark }}</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="content" scroll-y>
|
||||
<rich-text :nodes="agreementData.content"></rich-text>
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">
|
||||
<text>{{ $t('legal.footerNotice') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
import { URL } from '@/config/url.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
// 响应式数据
|
||||
const loading = ref(true)
|
||||
const error = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const agreementData = ref({
|
||||
title: '',
|
||||
content: '',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
// 将语言代码转换为后端接受的格式
|
||||
const convertLanguageCode = (lang) => {
|
||||
// zh-CN -> zh-CN (保持不变)
|
||||
// en-US -> en_US (转换下划线)
|
||||
return lang.replace(/-/g, '_')
|
||||
}
|
||||
|
||||
// 加载协议内容
|
||||
const loadAgreement = async () => {
|
||||
loading.value = true
|
||||
error.value = false
|
||||
errorMessage.value = ''
|
||||
|
||||
try {
|
||||
// 获取当前语言设置
|
||||
const currentLang = uni.getStorageSync('language') || 'zh-CN'
|
||||
const languageCode = convertLanguageCode(currentLang)
|
||||
|
||||
// 根据语言跳转到对应页面
|
||||
const targetPage = currentLang === 'en-US'
|
||||
? '/pages/legal/agreement-en'
|
||||
: '/pages/legal/agreement-zh'
|
||||
console.log('加载用户协议,语言:', currentLang, '转换后:', languageCode)
|
||||
|
||||
console.log('当前语言:', currentLang, '跳转到:', targetPage)
|
||||
|
||||
// 使用 redirectTo 替换当前页面
|
||||
uni.redirectTo({
|
||||
url: targetPage,
|
||||
fail: (err) => {
|
||||
console.error('跳转失败:', err)
|
||||
// 如果跳转失败,默认跳转到中文版
|
||||
uni.redirectTo({
|
||||
url: '/pages/legal/agreement-zh'
|
||||
})
|
||||
// 调用接口获取协议内容
|
||||
const res = await uni.request({
|
||||
url: `${URL}/device/agreementConfig/current`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Content-Language': languageCode,
|
||||
'Authorization': 'Bearer ' + uni.getStorageSync('token'),
|
||||
'Clientid': uni.getStorageSync('client_id')
|
||||
},
|
||||
data: {
|
||||
agreementCode: 'USER_AGREEMENT',
|
||||
appPlatform: 'wechat',
|
||||
appType: 'user'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('用户协议响应:', res)
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200 && res.data.data) {
|
||||
agreementData.value = {
|
||||
title: res.data.data.title || $t('legal.agreement'),
|
||||
content: res.data.data.content || '',
|
||||
remark: res.data.data.remark || ''
|
||||
}
|
||||
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: agreementData.value.title
|
||||
})
|
||||
} else {
|
||||
throw new Error(res.data.msg || $t('common.loadFailed'))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载用户协议失败:', err)
|
||||
error.value = true
|
||||
errorMessage.value = err.message || $t('common.loadFailed')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadAgreement()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -68,9 +146,40 @@
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
text {
|
||||
.error-page {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
|
||||
.error-icon {
|
||||
font-size: 80rpx;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 60rpx;
|
||||
background: #07c160;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.legal-page {
|
||||
@@ -83,33 +192,31 @@
|
||||
|
||||
.header {
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin-bottom: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
// width: 100%;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
padding: 20rpx;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.04);
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.h1 { font-size: 30rpx; font-weight: 600; color: #222; margin: 18rpx 0 12rpx; }
|
||||
.p { font-size: 26rpx; color: #444; line-height: 1.8; margin-bottom: 10rpx; }
|
||||
.bold { font-weight: 600; color: #222; }
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 16rpx;
|
||||
|
||||
+131
-51
@@ -1,40 +1,118 @@
|
||||
<template>
|
||||
<view class="loading-page">
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="loading" class="loading-page">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>{{ $t('common.loading') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<view v-else-if="error" class="error-page">
|
||||
<view class="error-content">
|
||||
<text class="error-icon">⚠️</text>
|
||||
<text class="error-message">{{ errorMessage }}</text>
|
||||
<button class="retry-btn" @click="loadAgreement">{{ $t('common.retry') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容显示 -->
|
||||
<view v-else class="legal-page">
|
||||
<view class="header">
|
||||
<text class="title">{{ agreementData.title || $t('legal.privacy') }}</text>
|
||||
<text v-if="agreementData.remark" class="subtitle">{{ agreementData.remark }}</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="content" scroll-y>
|
||||
<rich-text :nodes="agreementData.content"></rich-text>
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">
|
||||
<text>{{ $t('legal.footerNoticePolicy') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
import { URL } from '@/config/url.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
// 响应式数据
|
||||
const loading = ref(true)
|
||||
const error = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const agreementData = ref({
|
||||
title: '',
|
||||
content: '',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
// 将语言代码转换为后端接受的格式
|
||||
const convertLanguageCode = (lang) => {
|
||||
// zh-CN -> zh-CN (保持不变)
|
||||
// en-US -> en_US (转换下划线)
|
||||
return lang.replace(/-/g, '_')
|
||||
}
|
||||
|
||||
// 加载协议内容
|
||||
const loadAgreement = async () => {
|
||||
loading.value = true
|
||||
error.value = false
|
||||
errorMessage.value = ''
|
||||
|
||||
try {
|
||||
// 获取当前语言设置
|
||||
const currentLang = uni.getStorageSync('language') || 'zh-CN'
|
||||
const languageCode = convertLanguageCode(currentLang)
|
||||
|
||||
// 根据语言跳转到对应页面
|
||||
const targetPage = currentLang === 'en-US'
|
||||
? '/pages/legal/privacy-en'
|
||||
: '/pages/legal/privacy-zh'
|
||||
console.log('加载隐私政策,语言:', currentLang, '转换后:', languageCode)
|
||||
|
||||
console.log('当前语言:', currentLang, '跳转到:', targetPage)
|
||||
|
||||
// 使用 redirectTo 替换当前页面
|
||||
uni.redirectTo({
|
||||
url: targetPage,
|
||||
fail: (err) => {
|
||||
console.error('跳转失败:', err)
|
||||
// 如果跳转失败,默认跳转到中文版
|
||||
uni.redirectTo({
|
||||
url: '/pages/legal/privacy-zh'
|
||||
})
|
||||
// 调用接口获取协议内容
|
||||
const res = await uni.request({
|
||||
url: `${URL}/device/agreementConfig/current`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Content-Language': languageCode,
|
||||
'Authorization': 'Bearer ' + uni.getStorageSync('token'),
|
||||
'Clientid': uni.getStorageSync('client_id')
|
||||
},
|
||||
data: {
|
||||
agreementCode: 'PRIVACY_POLICY',
|
||||
appPlatform: 'wechat',
|
||||
appType: 'user'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('隐私政策响应:', res)
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200 && res.data.data) {
|
||||
agreementData.value = {
|
||||
title: res.data.data.title || $t('legal.privacy'),
|
||||
content: res.data.data.content || '',
|
||||
remark: res.data.data.remark || ''
|
||||
}
|
||||
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: agreementData.value.title
|
||||
})
|
||||
} else {
|
||||
throw new Error(res.data.msg || $t('common.loadFailed'))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载隐私政策失败:', err)
|
||||
error.value = true
|
||||
errorMessage.value = err.message || $t('common.loadFailed')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadAgreement()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -68,9 +146,40 @@
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
text {
|
||||
.error-page {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
|
||||
.error-icon {
|
||||
font-size: 80rpx;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 60rpx;
|
||||
background: #07c160;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.legal-page {
|
||||
@@ -83,60 +192,31 @@
|
||||
|
||||
.header {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin-bottom: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.notice {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
padding: 20rpx;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.h1 {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin: 18rpx 0 12rpx;
|
||||
}
|
||||
|
||||
.p {
|
||||
font-size: 26rpx;
|
||||
color: #444;
|
||||
line-height: 1.8;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 16rpx;
|
||||
|
||||
+73
-1
@@ -24,7 +24,18 @@
|
||||
</view> -->
|
||||
|
||||
<view class="section">
|
||||
<view class="banner-card" @click="navigateTo('/pages/join/index')">
|
||||
<!-- 广告轮播 -->
|
||||
<view class="banner-card" v-if="bannerImages.length > 0">
|
||||
<swiper class="banner-swiper" :indicator-dots="bannerImages.length > 1"
|
||||
:autoplay="bannerImages.length > 1" :circular="true" :interval="3000">
|
||||
<swiper-item v-for="(image, index) in bannerImages" :key="index">
|
||||
<image class="banner-image" :src="image" mode="aspectFill"
|
||||
@click="handleBannerClick(index)"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<!-- 默认图片(当没有广告时显示) -->
|
||||
<view class="banner-card" v-else @click="navigateTo('/pages/join/index')">
|
||||
<image class="banner-image" src="/static/userCenter_swiper.png" mode="aspectFill"></image>
|
||||
</view>
|
||||
<!-- <view class="section-title">常用服务</view> -->
|
||||
@@ -147,6 +158,60 @@ import {
|
||||
const appVersion = ref('1.0.0');
|
||||
|
||||
const showMenuItem = ref(false)
|
||||
const bannerImages = ref([]) // 广告图片列表
|
||||
|
||||
// 将语言代码转换为后端接受的格式
|
||||
const convertLanguageCode = (lang) => {
|
||||
// zh-CN -> zh_CN (转换下划线)
|
||||
// en-US -> en_US (转换下划线)
|
||||
return lang.replace(/-/g, '_')
|
||||
}
|
||||
|
||||
// 获取广告图片
|
||||
const getBannerImages = async () => {
|
||||
try {
|
||||
// 获取当前语言设置
|
||||
const currentLang = uni.getStorageSync('language') || 'zh-CN'
|
||||
const languageCode = convertLanguageCode(currentLang)
|
||||
|
||||
console.log('加载个人中心广告,语言:', currentLang, '转换后:', languageCode)
|
||||
|
||||
// 调用接口获取广告内容
|
||||
const res = await uni.request({
|
||||
url: `${URL}/device/advertisementConfig/current`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Content-Language': languageCode
|
||||
},
|
||||
data: {
|
||||
appPlatform: 'wechat', // 微信平台
|
||||
appType: 'user' // 用户端
|
||||
}
|
||||
})
|
||||
|
||||
console.log('个人中心广告响应:', res)
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200 && res.data.data) {
|
||||
// 使用 files 字段(图片列表)
|
||||
const files = res.data.data.files || []
|
||||
if (files.length > 0) {
|
||||
bannerImages.value = files
|
||||
console.log('个人中心广告加载成功,图片数量:', files.length)
|
||||
}
|
||||
} else {
|
||||
console.warn('获取个人中心广告失败:', res.data?.msg || '未知错误')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取个人中心广告失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理广告点击
|
||||
const handleBannerClick = (index) => {
|
||||
console.log('点击广告:', index)
|
||||
// 可以根据需要添加跳转逻辑
|
||||
// 例如:navigateTo('/pages/join/index')
|
||||
}
|
||||
|
||||
// 页面加载时初始化
|
||||
onMounted(() => {
|
||||
@@ -155,11 +220,13 @@ import {
|
||||
})
|
||||
getInfo();
|
||||
initVersion();
|
||||
getBannerImages(); // 加载广告
|
||||
});
|
||||
|
||||
// 页面显示时刷新用户信息
|
||||
onShow(() => {
|
||||
getInfo();
|
||||
getBannerImages(); // 刷新广告
|
||||
});
|
||||
|
||||
// 获取用户信息
|
||||
@@ -571,6 +638,11 @@ import {
|
||||
border: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.banner-swiper {
|
||||
width: 100%;
|
||||
height: 260rpx;
|
||||
}
|
||||
|
||||
.banner-image {
|
||||
width: 100%;
|
||||
height: 260rpx;
|
||||
|
||||
+481
-492
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user