123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188 |
- <template>
- <view class="travel-detail">
- <!-- 顶部封面区域 -->
- <view class="cover-section">
- <image class="cover-image" :src="getTripCoverImage()" mode="aspectFill"></image>
- <view class="cover-mask"></view>
- <view class="cover-content">
- <view class="back-btn" @tap="goBack">
- <text class="back-icon">←</text>
- </view>
- <view class="trip-title">{{tripData.name || '保定精彩之旅'}}</view>
- <view class="trip-subtitle">{{tripData.days || '3'}}天{{(tripData.days - 1) || '2'}}晚 · {{formatDate(tripData.startDate)}} 出发</view>
- </view>
- </view>
-
- <!-- 行程信息 -->
- <view class="trip-info">
- <view class="info-title">行程信息</view>
- <view class="info-content">
- <view class="info-item">
- <text class="info-label">行程天数</text>
- <text class="info-value">{{tripData.days || '3'}}天{{(tripData.days - 1) || '2'}}晚</text>
- </view>
- <view class="info-item">
- <text class="info-label">出发时间</text>
- <text class="info-value">{{formatDate(tripData.startDate)}}</text>
- </view>
- <view class="info-item" v-if="tripData.budget">
- <text class="info-label">预算金额</text>
- <text class="info-value">¥{{tripData.budget}}</text>
- </view>
- <view class="info-item">
- <text class="info-label">出行人数</text>
- <text class="info-value">{{tripData.peopleCount || 1}}人</text>
- </view>
- </view>
- </view>
-
- <!-- 景点列表 -->
- <view class="spots-section" v-if="tripData.spots && tripData.spots.length > 0">
- <view class="section-title">景点行程安排</view>
- <view class="spots-list">
- <block v-for="(spot, index) in tripData.spots" :key="index">
- <!-- 景点项 -->
- <view class="spot-item">
- <view class="spot-index">{{index + 1}}</view>
- <view class="spot-info">
- <text class="spot-name">{{spot.name}}</text>
- <text class="spot-address" v-if="spot.address">{{spot.address}}</text>
- </view>
- </view>
-
- <!-- 距离显示(与下一个景点的距离) -->
- <view class="distance-item" v-if="index < tripData.spots.length - 1">
- <view class="distance-line"></view>
- <view class="distance-value">
- <text class="distance-icon">↓</text>
- <text class="distance-text">{{getDistanceBetween(spot, tripData.spots[index + 1])}}公里</text>
- </view>
- </view>
- </block>
- </view>
- </view>
-
- <!-- 按钮区域 -->
- <view class="action-buttons">
- <button class="edit-btn" @tap="editTrip">修改行程</button>
- <button class="back-home-btn" @tap="goToHome">返回规划页面</button>
- </view>
-
- <!-- 分享二维码按钮 -->
- <view class="share-section">
- <button class="share-btn" @tap="shareTrip">
- <text class="share-icon">🔗</text>
- <text class="share-text">分享行程二维码</text>
- </button>
- </view>
-
- <!-- 删除行程按钮 -->
- <view class="delete-section">
- <button class="delete-btn" @tap="showDeleteConfirm">
- <text class="delete-icon">🗑️</text>
- <text class="delete-text">删除行程</text>
- </button>
- </view>
-
- <!-- 二维码弹窗 -->
- <view class="qrcode-popup" v-if="showQrCode" @tap.stop="handlePopupBackdrop">
- <view class="qrcode-container" @tap.stop>
- <view class="qrcode-header">
- <view class="qrcode-title">分享行程</view>
- <view class="qrcode-close" @tap.stop="closeQrCode">×</view>
- </view>
- <view class="qrcode-content">
- <view class="qrcode-image-wrap">
- <image class="qrcode-image" :src="qrCodeUrl" mode="aspectFit" />
- </view>
- <view class="qrcode-desc">扫描二维码查看行程</view>
- <view class="qrcode-tips">
- <text>行程:{{tripData.name}}</text>
- <text>天数:{{tripData.days}}天</text>
- <text>预算:{{tripData.budget}}元</text>
- </view>
- </view>
- <view class="qrcode-footer">
- <button class="qrcode-save-btn" @tap.stop="saveQrCode">保存到相册</button>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import { API } from '@/util/api.js';
- export default {
- data() {
- return {
- isLoading: false,
- tripId: null,
- tripData: {},
- options: null,
- defaultImages: [
- '/static/baoding.jpg',
- '/static/custom_plan_icon.png',
- '/static/beijing.jpg',
- '/static/chengdu.jpg'
- ],
- showQrCode: false,
- qrCodeUrl: '',
- qrCodeExpireTime: 0
- }
- },
-
- onLoad(options) {
- console.log('行程详情页面加载,参数:', options);
- this.options = options;
-
- // 获取行程ID
- if (options && options.planId) {
- console.log('接收到行程ID:', options.planId);
- this.tripId = options.planId;
- this.loadTripData();
- } else {
- console.log('没有接收到行程ID,使用默认数据');
- // 如果没有ID,创建一个默认行程
- this.createDefaultTrip();
- }
- },
-
- // 监听app全局事件
- onShow() {
- // 监听加载指定行程的事件
- uni.$on('loadTripDetail', this.handleLoadTripDetail);
- },
-
- onHide() {
- // 取消监听事件
- uni.$off('loadTripDetail', this.handleLoadTripDetail);
- },
-
- methods: {
- // 处理通过事件加载行程
- handleLoadTripDetail(data) {
- if (data && data.tripId) {
- console.log('通过事件加载行程:', data.tripId);
- this.tripId = data.tripId;
- this.loadTripData();
- }
- },
-
- // 创建默认行程
- createDefaultTrip() {
- // 创建一个默认行程
- this.tripData = {
- id: 'default_trip_' + Date.now(),
- name: '保定精彩三日游',
- days: 3,
- nights: 2,
- startDate: this.formatDate(new Date()),
- budget: 1580
- };
-
- uni.showToast({
- title: '默认行程已生成',
- icon: 'success'
- });
- },
-
- // 加载行程数据
- loadTripData() {
- this.isLoading = true;
-
- // 首先尝试通过API加载
- if (this.tripId && !this.tripId.startsWith('trip_')) {
- // 如果ID不是本地临时ID(不以trip_开头),则使用API
- API.trip.detail(this.tripId)
- .then(res => {
- if (res.data) {
- this.tripData = res.data;
- uni.showToast({
- title: '行程加载成功',
- icon: 'success'
- });
- } else {
- console.log('API返回空数据,尝试从本地加载');
- this.loadFromLocalStorage();
- }
- })
- .catch(err => {
- console.error('通过API加载行程失败:', err);
- this.loadFromLocalStorage();
- })
- .finally(() => {
- this.isLoading = false;
- });
- } else {
- // 本地临时ID,从本地存储加载
- this.loadFromLocalStorage();
- }
- },
-
- // 从本地存储加载行程
- loadFromLocalStorage() {
- try {
- // 获取所有已保存的行程
- const savedTrips = uni.getStorageSync('savedTrips') || [];
- console.log('已保存行程:', savedTrips);
-
- // 查找当前行程ID对应的行程
- const tripData = savedTrips.find(trip => trip.id === this.tripId);
-
- if (tripData) {
- console.log('找到行程数据:', tripData);
- this.tripData = tripData;
-
- uni.showToast({
- title: '行程加载成功',
- icon: 'success'
- });
- } else {
- console.log('未找到行程数据,使用默认数据');
- // 使用默认数据
- this.createDefaultTrip();
- }
- } catch (e) {
- console.error('加载行程数据失败:', e);
- // 加载失败时使用默认数据
- this.createDefaultTrip();
- } finally {
- this.isLoading = false;
- }
- },
-
- // 修改行程
- editTrip() {
- if (!this.tripData || !this.tripData.id) {
- uni.showToast({
- title: '无法修改默认行程',
- icon: 'none'
- });
- return;
- }
-
- // 保存当前行程数据到本地存储中的临时数据
- try {
- // 如果有景点数据,保存到selectedLocations中
- if (this.tripData.spots && this.tripData.spots.length > 0) {
- uni.setStorageSync('selectedLocations', JSON.stringify(this.tripData.spots));
-
- // 跳转到行程编辑页面
- uni.navigateTo({
- url: `/pages/custom-trip/plan-detail?tripId=${this.tripData.id}`,
- success: () => {
- console.log('成功跳转到行程编辑页面,行程ID:', this.tripData.id);
- },
- fail: (err) => {
- console.error('跳转到行程编辑页面失败:', err);
- uni.showToast({
- title: '跳转失败',
- icon: 'none'
- });
- }
- });
- } else {
- uni.showToast({
- title: '行程没有景点数据',
- icon: 'none'
- });
- }
- } catch (e) {
- console.error('保存临时数据失败:', e);
- uni.showToast({
- title: '准备编辑数据失败',
- icon: 'none'
- });
- }
- },
-
- // 获取行程封面图片
- getTripCoverImage() {
- // 如果行程有spots并且第一个spot有图片,则使用该图片
- if (this.tripData.spots && this.tripData.spots.length > 0) {
- if (this.tripData.spots[0].coverImage) {
- return this.tripData.spots[0].coverImage;
- }
- }
-
- // 根据行程名称选择默认图片
- if (this.tripData.name && this.tripData.name.includes('保定')) {
- return '/static/baoding.jpg';
- } else if (this.tripData.name && this.tripData.name.includes('西安')) {
- return '/static/xian.jpg';
- } else if (this.tripData.name && this.tripData.name.includes('北京')) {
- return '/static/beijing.jpg';
- } else if (this.tripData.name && this.tripData.name.includes('上海')) {
- return '/static/shanghai.jpg';
- }
-
- // 根据行程ID生成一个固定的索引,确保每次显示相同的图片
- const hash = this.tripData.id ? this.tripData.id.split('_')[1] : Date.now();
- const index = hash % this.defaultImages.length;
-
- return this.defaultImages[index];
- },
-
- // 格式化日期
- formatDate(date) {
- if (!date) {
- const now = new Date();
- const year = now.getFullYear();
- const month = now.getMonth() + 1;
- const day = now.getDate();
- return `${year}.${month}.${day}`;
- }
-
- // 如果有日期对象,进行格式化
- if (date instanceof Date) {
- const year = date.getFullYear();
- const month = date.getMonth() + 1;
- const day = date.getDate();
- return `${year}.${month}.${day}`;
- }
-
- // 如果是字符串,直接返回
- return date;
- },
-
- // 返回上一页
- goBack() {
- uni.navigateBack({
- fail: () => {
- // 如果无法返回上一页,则回到首页
- this.goToHome();
- }
- });
- },
-
- // 回到首页
- goToHome() {
- uni.switchTab({
- url: '/pages/planning/index'
- });
- },
-
- // 计算两个景点之间的距离
- calculateDistance(spot1, spot2) {
- if (!spot1 || !spot2 || !spot1.latitude || !spot1.longitude || !spot2.latitude || !spot2.longitude) {
- return '未知';
- }
-
- // 将经纬度转换为数字类型
- const lat1 = Number(spot1.latitude);
- const lng1 = Number(spot1.longitude);
- const lat2 = Number(spot2.latitude);
- const lng2 = Number(spot2.longitude);
-
- // 检查经纬度是否有效
- if (isNaN(lat1) || isNaN(lng1) || isNaN(lat2) || isNaN(lng2)) {
- return '未知';
- }
-
- // 使用半正矢公式计算球面距离
- const R = 6371; // 地球半径,单位公里
- const dLat = this.toRadians(lat2 - lat1);
- const dLng = this.toRadians(lng2 - lng1);
-
- const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
- Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) *
- Math.sin(dLng/2) * Math.sin(dLng/2);
-
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
- const distance = R * c; // 距离,单位公里
-
- // 格式化距离,保留一位小数
- return distance.toFixed(1);
- },
-
- // 角度转弧度
- toRadians(degrees) {
- return degrees * Math.PI / 180;
- },
-
- // 获取两个景点之间的距离
- getDistanceBetween(spot1, spot2) {
- // 如果第二个景点有预先计算的距离信息,直接使用
- if (spot2.distanceFromPrevious !== undefined && spot2.distanceFromPrevious !== null) {
- return spot2.distanceFromPrevious;
- }
-
- // 否则实时计算距离
- return this.calculateDistance(spot1, spot2);
- },
-
- // 显示删除确认对话框
- showDeleteConfirm() {
- if (!this.tripData || !this.tripData.id) {
- uni.showToast({
- title: '无法删除默认行程',
- icon: 'none'
- });
- return;
- }
-
- uni.showModal({
- title: '确认删除',
- content: '确定要删除此行程吗?此操作不可恢复。',
- confirmColor: '#ff4d4f',
- success: (res) => {
- if (res.confirm) {
- this.deleteTrip();
- }
- }
- });
- },
-
- // 删除行程
- deleteTrip() {
- uni.showLoading({
- title: '正在删除...',
- mask: true
- });
-
- // 首先尝试通过API删除
- if (this.tripId && !this.tripId.startsWith('trip_')) {
- // 如果ID不是本地临时ID(不以trip_开头),则使用API
- API.trip.delete(this.tripId)
- .then(res => {
- console.log('API删除行程成功:', res);
- // 同时从本地存储中删除
- this.deleteFromLocalStorage();
-
- uni.showToast({
- title: '行程已删除',
- icon: 'success'
- });
-
- // 返回规划页面
- setTimeout(() => {
- this.goToHome();
- }, 1000);
- })
- .catch(err => {
- console.error('通过API删除行程失败:', err);
- // 尝试从本地存储中删除
- this.deleteFromLocalStorage();
- })
- .finally(() => {
- uni.hideLoading();
- });
- } else {
- // 本地临时ID,从本地存储删除
- this.deleteFromLocalStorage();
- uni.hideLoading();
- }
- },
-
- // 从本地存储中删除行程
- deleteFromLocalStorage() {
- try {
- // 获取所有已保存的行程
- const savedTrips = uni.getStorageSync('savedTrips') || [];
-
- // 过滤掉要删除的行程
- const updatedTrips = savedTrips.filter(trip => trip.id !== this.tripId);
-
- // 保存回本地存储
- uni.setStorageSync('savedTrips', updatedTrips);
-
- uni.showToast({
- title: '行程已删除',
- icon: 'success'
- });
-
- // 通知规划页面刷新数据
- uni.$emit('refreshTrips');
-
- // 返回规划页面
- setTimeout(() => {
- this.goToHome();
- }, 1000);
- } catch (e) {
- console.error('从本地存储删除行程失败:', e);
- uni.showToast({
- title: '删除失败',
- icon: 'none'
- });
- }
- },
-
- // 处理弹窗背景点击
- handlePopupBackdrop(e) {
- // 点击背景关闭弹窗
- this.closeQrCode();
- },
-
- // 分享行程方法
- shareTrip() {
- console.log("点击分享按钮");
- // 直接生成二维码分享
- this.generateQrCode();
-
- // 显示加载提示
- uni.showToast({
- title: '正在生成二维码',
- icon: 'loading',
- duration: 1000
- });
- },
-
- // 生成行程二维码
- generateQrCode() {
- console.log("点击生成二维码按钮");
- if (!this.tripData || !this.tripData.id) {
- uni.showToast({
- title: '无法生成默认行程的二维码',
- icon: 'none'
- });
- return;
- }
-
- // 如果已经生成过且未过期,直接显示
- if (this.qrCodeUrl && this.qrCodeExpireTime > Date.now()) {
- console.log('使用缓存的二维码');
- this.showQrCode = true;
- return;
- }
-
- // 生成一个简单的临时二维码以便稍后替换
- this.generateLocalQrCode();
-
- // 创建一个简化版的行程数据,只包含必要字段,减少传输数据量
- const simpleTripData = {
- id: this.tripData.id,
- name: this.tripData.name,
- days: this.tripData.days,
- budget: this.tripData.budget
- };
-
- // 打印发送到后端的数据
- console.log('发送到后端的数据:', JSON.stringify(simpleTripData));
-
- // 调用后端API生成二维码
- API.trip.generateQrCode(simpleTripData)
- .then(res => {
- // 打印后端返回的数据
- console.log('后端返回的二维码数据:', res);
-
- if (res.qrCodeUrl || res.data?.qrCodeUrl) {
- // 兼容不同的返回格式
- this.qrCodeUrl = res.qrCodeUrl || res.data?.qrCodeUrl;
- this.qrCodeExpireTime = res.expireTime || res.data?.expireTime || (Date.now() + 3600000);
-
- // 打印完整二维码URL和原始内容
- console.log('二维码URL:', this.qrCodeUrl);
- console.log('二维码内容:', res.qrContent || '未提供');
-
- // 更新二维码图片
- this.$nextTick(() => {
- // 图片已更新
- console.log('二维码图片已更新');
-
- // 显示成功提示
- uni.showToast({
- title: '二维码生成成功',
- icon: 'success',
- duration: 1500
- });
- });
- } else {
- console.error('生成二维码失败: 返回数据中无qrCodeUrl', res);
- // 保持显示本地生成的二维码
- uni.showToast({
- title: '使用本地二维码',
- icon: 'none'
- });
- }
- })
- .catch(err => {
- console.error('生成二维码失败:', err);
- // 保持显示本地生成的二维码
- uni.showToast({
- title: '使用本地二维码',
- icon: 'none',
- duration: 1500
- });
- });
- },
-
- // 生成本地二维码(不依赖后端)
- generateLocalQrCode() {
- try {
- // 显示弹窗
- this.showQrCode = true;
-
- // 设置为加载中的占位图,使用完整路径格式
- const qrContent = `pages/travel-detail/index?planId=${this.tripData.id}`;
- const loadingQrCode = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrContent)}`;
- this.qrCodeUrl = loadingQrCode;
- console.log('生成临时二维码:', loadingQrCode);
- console.log('二维码内容:', qrContent);
-
- // 这里可以进一步改进,使用本地QR码生成库
- } catch (e) {
- console.error('生成本地二维码失败:', e);
- }
- },
-
- // 关闭二维码弹窗
- closeQrCode() {
- this.showQrCode = false;
- },
-
- // 保存二维码到相册
- saveQrCode() {
- if (!this.qrCodeUrl) {
- uni.showToast({
- title: '二维码不存在',
- icon: 'none'
- });
- return;
- }
-
- // 检查是否有保存到相册的权限
- uni.getSetting({
- success: (res) => {
- if (!res.authSetting['scope.writePhotosAlbum']) {
- uni.authorize({
- scope: 'scope.writePhotosAlbum',
- success: () => {
- this.downloadQrCode();
- },
- fail: () => {
- uni.showModal({
- title: '提示',
- content: '请授权保存图片到相册的权限',
- confirmText: '去设置',
- success: (res) => {
- if (res.confirm) {
- uni.openSetting();
- }
- }
- });
- }
- });
- } else {
- this.downloadQrCode();
- }
- }
- });
- },
-
- // 下载二维码到本地
- downloadQrCode() {
- uni.showLoading({
- title: '保存中...'
- });
-
- // 检查qrCodeUrl是否是Base64格式
- if (this.qrCodeUrl && this.qrCodeUrl.indexOf('data:image/png;base64,') === 0) {
- console.log('检测到Base64格式图片,直接保存');
- const base64Data = this.qrCodeUrl.split(',')[1];
-
- // 小程序环境
- try {
- const fs = wx.getFileSystemManager();
- const filePath = `${wx.env.USER_DATA_PATH}/trip_qrcode_${Date.now()}.png`;
-
- fs.writeFile({
- filePath: filePath,
- data: base64Data,
- encoding: 'base64',
- success: () => {
- // 保存到相册
- wx.saveImageToPhotosAlbum({
- filePath: filePath,
- success: () => {
- uni.hideLoading();
- uni.showToast({
- title: '保存成功',
- icon: 'success'
- });
- },
- fail: (err) => {
- console.error('保存到相册失败:', err);
- uni.hideLoading();
- uni.showToast({
- title: '保存失败',
- icon: 'none'
- });
- }
- });
- },
- fail: (err) => {
- console.error('写入文件失败:', err);
- uni.hideLoading();
- uni.showToast({
- title: '保存失败',
- icon: 'none'
- });
- }
- });
- } catch (err) {
- console.error('保存Base64图片失败:', err);
- uni.hideLoading();
- uni.showToast({
- title: '当前平台不支持保存',
- icon: 'none'
- });
- }
- } else {
- // 如果是网络图片URL,使用downloadFile方法
- uni.downloadFile({
- url: this.qrCodeUrl,
- success: (res) => {
- if (res.statusCode === 200) {
- // 保存到相册
- uni.saveImageToPhotosAlbum({
- filePath: res.tempFilePath,
- success: () => {
- uni.showToast({
- title: '保存成功',
- icon: 'success'
- });
- },
- fail: (err) => {
- console.error('保存到相册失败:', err);
- uni.showToast({
- title: '保存失败',
- icon: 'none'
- });
- }
- });
- }
- },
- fail: (err) => {
- console.error('下载二维码失败:', err);
- uni.showToast({
- title: '保存失败',
- icon: 'none'
- });
- },
- complete: () => {
- uni.hideLoading();
- }
- });
- }
- },
- }
- }
- </script>
- <style>
- .travel-detail {
- padding-bottom: 40rpx;
- background-color: #f5f7fa;
- }
- /* 顶部封面区域 */
- .cover-section {
- position: relative;
- height: 400rpx;
- overflow: hidden;
- }
- .cover-image {
- width: 100%;
- height: 100%;
- }
- .cover-mask {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.6));
- }
- .cover-content {
- position: absolute;
- bottom: 40rpx;
- left: 0;
- width: 100%;
- padding: 0 40rpx;
- box-sizing: border-box;
- }
- .back-btn {
- position: absolute;
- top: -280rpx;
- left: 0;
- width: 80rpx;
- height: 80rpx;
- background-color: rgba(255,255,255,0.2);
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .back-icon {
- font-size: 48rpx;
- color: #ffffff;
- }
- .trip-title {
- font-size: 48rpx;
- font-weight: bold;
- color: #ffffff;
- margin-bottom: 16rpx;
- text-shadow: 0 2rpx 8rpx rgba(0,0,0,0.3);
- }
- .trip-subtitle {
- font-size: 28rpx;
- color: rgba(255,255,255,0.9);
- }
- /* 行程信息 */
- .trip-info {
- margin: 30rpx;
- padding: 30rpx;
- background-color: #ffffff;
- border-radius: 20rpx;
- box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.05);
- }
- .info-title {
- font-size: 32rpx;
- font-weight: bold;
- margin-bottom: 20rpx;
- color: #333;
- }
- .info-content {
- display: flex;
- flex-direction: column;
- }
- .info-item {
- display: flex;
- justify-content: space-between;
- padding: 16rpx 0;
- border-bottom: 1px solid #f0f0f0;
- }
- .info-item:last-child {
- border-bottom: none;
- }
- .info-label {
- color: #666;
- font-size: 28rpx;
- }
- .info-value {
- color: #333;
- font-size: 28rpx;
- font-weight: 500;
- }
- /* 景点列表 */
- .spots-section {
- margin: 30rpx;
- padding: 30rpx;
- background-color: #ffffff;
- border-radius: 20rpx;
- box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.05);
- }
- .section-title {
- font-size: 32rpx;
- font-weight: bold;
- margin-bottom: 20rpx;
- color: #333;
- }
- .spots-list {
- display: flex;
- flex-direction: column;
- }
- .spot-item {
- display: flex;
- align-items: center;
- padding: 20rpx 0;
- }
- .spot-index {
- width: 50rpx;
- height: 50rpx;
- background-color: #3e98ff;
- color: white;
- border-radius: 50%;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 26rpx;
- margin-right: 20rpx;
- }
- .spot-info {
- flex: 1;
- }
- .spot-name {
- font-size: 30rpx;
- color: #333;
- font-weight: 500;
- margin-bottom: 6rpx;
- }
- .spot-address {
- font-size: 24rpx;
- color: #999;
- }
- /* 距离项样式 */
- .distance-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 10rpx 0;
- position: relative;
- }
- .distance-line {
- width: 2rpx;
- height: 40rpx;
- background-color: #ddd;
- }
- .distance-value {
- display: flex;
- align-items: center;
- background-color: #f5f7fa;
- padding: 6rpx 16rpx;
- border-radius: 100rpx;
- margin: 5rpx 0;
- }
- .distance-icon {
- color: #3e98ff;
- font-size: 24rpx;
- margin-right: 8rpx;
- }
- .distance-text {
- font-size: 24rpx;
- color: #666;
- }
- /* 按钮区域 */
- .action-buttons {
- padding: 30rpx 30rpx 0;
- display: flex;
- gap: 20rpx;
- justify-content: space-between;
- }
- .edit-btn {
- background-color: #3e98ff;
- color: #ffffff;
- border-radius: 50rpx;
- font-size: 32rpx;
- padding: 20rpx 0;
- flex: 1;
- }
- .back-home-btn {
- background-color: #f0f0f0;
- color: #333;
- border-radius: 50rpx;
- font-size: 32rpx;
- padding: 20rpx 0;
- flex: 1;
- }
- /* 分享二维码按钮样式 */
- .share-section {
- padding: 0 30rpx;
- margin-top: 20rpx;
- }
- .share-btn {
- background-color: #4caf50;
- color: #ffffff;
- border-radius: 50rpx;
- font-size: 32rpx;
- padding: 16rpx 0;
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- box-shadow: 0 4rpx 10rpx rgba(76, 175, 80, 0.2);
- transition: all 0.3s ease;
- }
- .share-btn:active {
- transform: translateY(2rpx);
- }
- .share-icon {
- margin-right: 10rpx;
- font-size: 32rpx;
- }
- .share-text {
- font-size: 28rpx;
- }
- /* 删除行程按钮样式 */
- .delete-section {
- padding: 20rpx 30rpx 30rpx;
- }
- .delete-btn {
- background-color: #ffffff;
- color: #ff4d4f;
- border: 1px solid #ff4d4f;
- border-radius: 50rpx;
- font-size: 32rpx;
- padding: 16rpx 0;
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-top: 20rpx;
- box-shadow: 0 4rpx 10rpx rgba(255, 77, 79, 0.1);
- transition: all 0.3s ease;
- }
- .delete-btn:active {
- background-color: #fff1f0;
- transform: translateY(2rpx);
- }
- .delete-icon {
- margin-right: 10rpx;
- font-size: 32rpx;
- }
- .delete-text {
- font-size: 28rpx;
- }
- /* 二维码弹窗样式 */
- .qrcode-popup {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.6);
- z-index: 9999;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .qrcode-container {
- width: 600rpx;
- background-color: #ffffff;
- border-radius: 20rpx;
- overflow: hidden;
- box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.2);
- transform: scale(1);
- }
- .qrcode-header {
- padding: 30rpx;
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-bottom: 1rpx solid #f0f0f0;
- }
- .qrcode-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- }
- .qrcode-close {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 60rpx;
- height: 60rpx;
- font-size: 48rpx;
- color: #999;
- line-height: 1;
- border-radius: 50%;
- }
- .qrcode-close:active {
- background-color: #f5f5f5;
- }
- .qrcode-content {
- padding: 40rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .qrcode-image-wrap {
- width: 400rpx;
- height: 400rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- margin-bottom: 20rpx;
- padding: 20rpx;
- border: 1px dashed #eee;
- border-radius: 8rpx;
- background-color: #fff;
- }
- .qrcode-image {
- width: 100%;
- height: 100%;
- }
- .qrcode-desc {
- font-size: 28rpx;
- color: #666;
- margin-top: 20rpx;
- }
- .qrcode-tips {
- font-size: 24rpx;
- color: #666;
- margin-top: 20rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .qrcode-tips text {
- margin: 4rpx 0;
- }
- .qrcode-footer {
- padding: 30rpx;
- border-top: 1rpx solid #f0f0f0;
- }
- .qrcode-save-btn {
- background-color: #3e98ff;
- color: #ffffff;
- border-radius: 50rpx;
- font-size: 32rpx;
- padding: 16rpx 0;
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .qrcode-save-btn:active {
- opacity: 0.9;
- transform: translateY(2rpx);
- }
- </style>
|