Commit 017c7251 authored by 罗超's avatar 罗超

修改

parent a183c1a7
...@@ -28,18 +28,15 @@ ...@@ -28,18 +28,15 @@
<div class="mb-md">{{ x.week }}</div> --> <div class="mb-md">{{ x.week }}</div> -->
<div v-for="(y, index) in x.cities" :key="index"> <div v-for="(y, index) in x.cities" :key="index">
<div class="mt-md"> <div class="mt-md">
<span v-if="(i==0 && index==0)||(i==trip.days.length-1 && index==x.cities.length-1)" class="iconfont icon-qizhi mr-xs"></span> <span v-if="(i == 0 && index == 0) || (i == trip.days.length - 1 && index == x.cities.length - 1)"
class="iconfont icon-qizhi mr-xs"></span>
<span class="pdf-mid">{{ y }}</span> <span class="pdf-mid">{{ y }}</span>
</div> </div>
<!-- <div class="info-text pdf-small">{{ y.enName }}</div> --> <!-- <div class="info-text pdf-small">{{ y.enName }}</div> -->
</div> </div>
</td> </td>
<td> <td>
<div <div class="flex-row bold mb-sm" v-for="(y, index) in x.attractions" :key="index">
class="flex-row bold mb-sm"
v-for="(y, index) in x.attractions"
:key="index"
>
<div>{{ index + 1 }}.</div> <div>{{ index + 1 }}.</div>
<div class="ml-sm flex-1">{{ y.name }}</div> <div class="ml-sm flex-1">{{ y.name }}</div>
</div> </div>
...@@ -47,8 +44,8 @@ ...@@ -47,8 +44,8 @@
<td> <td>
<div class="flex-row mb-md" v-if="x.hotels && x.hotels.length > 0"> <div class="flex-row mb-md" v-if="x.hotels && x.hotels.length > 0">
<span class="iconfont icon-shuijue primary-text"></span> <span class="iconfont icon-shuijue primary-text"></span>
<div class="flex-1 ml-sm" v-if="i<trip.days.length-1"> <div class="flex-1 ml-sm" v-if="i < trip.days.length - 1">
<div v-for="(y, index) in x.hotels" :key="index" :class="{'mb-sm': index < x.hotels.length - 1}"> <div v-for="(y, index) in x.hotels" :key="index" :class="{ 'mb-sm': index < x.hotels.length - 1 }">
<div class="bold"> <div class="bold">
<span>{{ y.name }}</span> <span>{{ y.name }}</span>
<span v-if="index < x.hotels.length - 1"></span> <span v-if="index < x.hotels.length - 1"></span>
...@@ -72,9 +69,11 @@ ...@@ -72,9 +69,11 @@
</div> </div>
</td> </td>
<td> <td>
<!-- <div <div
class="flex-row" class="flex-row"
v-if="(i == 0 && trip.flights.length > 0) || (i == items.length - 1 && trip.flights.length > 1)" v-for="(traffic, tIndex) in x.traffics"
:key="tIndex"
v-if="traffic.type === '航班'"
> >
<div class="column align-center py-sm relative"> <div class="column align-center py-sm relative">
<div class="accent-bar-h"></div> <div class="accent-bar-h"></div>
...@@ -86,34 +85,36 @@ ...@@ -86,34 +85,36 @@
</div> </div>
<div class="flex-1 ml-sm"> <div class="flex-1 ml-sm">
<div class="bold"> <div class="bold">
{{ trip.flights[i > 0 ? 1 : 0].startCityName }} {{ traffic.departure }}
</div> </div>
<div class="pdf-small"> <div class="pdf-small">
Airport Code {{ trip.flights[i > 0 ? 1 : 0].startCityCode }} {{ traffic.departureAirport }} ({{ traffic.departureAirportCode }})
</div> </div>
<div class="my-md primary-text bold"> <div class="my-md primary-text bold">
<div> <div>
{{ trip.flights[i > 0 ? 1 : 0].items[0].flightNo }} {{ traffic.airline }} {{ traffic.flightNumber }}
<span v-if="trip.flights[i > 0 ? 1 : 0].items.length > 1">
{{ trip.flights[i > 0 ? 1 : 0].items.length }}个航班
</span>
</div> </div>
<div class="pdf-small alifont"> <div class="pdf-small alifont">
{{ trip.flights[i > 0 ? 1 : 0].items[0].startTime }} - {{ traffic.departureTime }} - {{ traffic.arrivalTime }}
{{ trip.flights[i > 0 ? 1 : 0].items[trip.flights[i > 0 ? 1 : 0].items.length - 1].endTime }}
<span v-if="trip.flights[i > 0 ? 1 : 0].items[0].startDate != trip.flights[i > 0 ? 1 : 0].items[trip.flights[i > 0 ? 1 : 0].items.length - 1].endDate">
(+1天)
</span>
</div> </div>
</div> </div>
<div class="bold"> <div class="bold">
{{ trip.flights[i > 0 ? 1 : 0].endCityName }} {{ traffic.destination }}
</div> </div>
<div class="pdf-small"> <div class="pdf-small">
Airport Code {{ trip.flights[i > 0 ? 1 : 0].endCityCode }} {{ traffic.arrivalAirport }} ({{ traffic.arrivalAirportCode }})
</div> </div>
</div> </div>
</div> --> </div>
<div
class="flex-row"
v-for="(traffic, tIndex) in x.traffics"
:key="tIndex"
v-if="traffic.type != '航班'"
>
<div class="bold">{{ traffic.type }}</div>
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -240,7 +241,7 @@ ...@@ -240,7 +241,7 @@
</template> </template>
<script> <script>
import {itineraryService} from '@/services/itinerary'; import { itineraryService } from '@/services/itinerary';
export default { export default {
name: 'ItineraryDetail', name: 'ItineraryDetail',
...@@ -295,11 +296,11 @@ export default { ...@@ -295,11 +296,11 @@ export default {
x.cities = []; x.cities = [];
const departures = x.traffics.map(y => y.departure) const departures = x.traffics.map(y => y.departure)
const destinations = x.traffics.map(y => y.destination) const destinations = x.traffics.map(y => y.destination)
const attractionsCities = x.attractions.map(y=>y.city) const attractionsCities = x.attractions.map(y => y.city)
const cateringsCities = x.caterings.map(y=>y.city) const cateringsCities = x.caterings.map(y => y.city)
const hotelsCities = x.hotels.map(y=>y.city) const hotelsCities = x.hotels.map(y => y.city)
let temp = [...new Set([...departures,...destinations, ...attractionsCities, ...cateringsCities, ...hotelsCities])] let temp = [...new Set([...departures, ...destinations, ...attractionsCities, ...cateringsCities, ...hotelsCities])]
temp = temp.filter(y => y !== null && y !== undefined && y !== '' && !y.includes('实际')&& !y.includes('周边')&& !y.includes('或')) temp = temp.filter(y => y !== null && y !== undefined && y !== '' && !y.includes('实际') && !y.includes('周边') && !y.includes('或'))
temp = temp.map(y => { temp = temp.map(y => {
y = y.replace('省', '').replace('市', '').replace('区', '').replace('县', '') y = y.replace('省', '').replace('市', '').replace('区', '').replace('县', '')
return y return y
...@@ -319,7 +320,7 @@ export default { ...@@ -319,7 +320,7 @@ export default {
const currentDate = new Date(travelDate.getTime() + i * 24 * 60 * 60 * 1000); const currentDate = new Date(travelDate.getTime() + i * 24 * 60 * 60 * 1000);
temp.num = 'D' + (i + 1); temp.num = 'D' + (i + 1);
temp.date = `${(currentDate.getMonth() + 1).toString().padStart(2, '0')}-${currentDate.getDate().toString().padStart(2, '0')}`; temp.date = `${(currentDate.getMonth() + 1).toString().padStart(2, '0')}-${currentDate.getDate().toString().padStart(2, '0')}`;
temp.week = ['周日','周一','周二','周三','周四','周五','周六'][currentDate.getDay()]; temp.week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][currentDate.getDay()];
temp.cities = []; temp.cities = [];
if (i === 0) { if (i === 0) {
if (this.trip.flights.length > 0) temp.price += parseFloat(this.trip.flights[0].displayPrice); if (this.trip.flights.length > 0) temp.price += parseFloat(this.trip.flights[0].displayPrice);
...@@ -363,6 +364,7 @@ export default { ...@@ -363,6 +364,7 @@ export default {
this.typePrices.flight += parseFloat(x.displayPrice); this.typePrices.flight += parseFloat(x.displayPrice);
}); });
}, },
printPDF() { printPDF() {
window.print(); window.print();
}, },
...@@ -372,12 +374,14 @@ export default { ...@@ -372,12 +374,14 @@ export default {
<style scoped> <style scoped>
@import url('//at.alicdn.com/t/c/font_4020685_jbpfa13faji.css'); @import url('//at.alicdn.com/t/c/font_4020685_jbpfa13faji.css');
@font-face { @font-face {
font-family: 'alifont'; font-family: 'alifont';
src: url('//at.alicdn.com/wf/webfont/MQHUV6e56ce5/FZ2wHD6g3frR.woff2') format('woff2'), src: url('//at.alicdn.com/wf/webfont/MQHUV6e56ce5/FZ2wHD6g3frR.woff2') format('woff2'),
url('//at.alicdn.com/wf/webfont/MQHUV6e56ce5/wXT52gRya21s.woff') format('woff'); url('//at.alicdn.com/wf/webfont/MQHUV6e56ce5/wXT52gRya21s.woff') format('woff');
font-display: swap; font-display: swap;
} }
.full-box { .full-box {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
...@@ -386,47 +390,208 @@ export default { ...@@ -386,47 +390,208 @@ export default {
box-sizing: border-box; box-sizing: border-box;
overflow: auto; overflow: auto;
} }
.alifont { font-family: 'alifont', 等线 !important; }
.pdf-content { width: 21cm; margin: 0 auto; font-family: 等线 !important; } .alifont {
.pdf-table { background: #eef0f2; width: 100%; } font-family: 'alifont', 等线 !important;
.pdf-table th, .pdf-table td { padding-left: 16px; padding-right: 16px; text-align: left; } }
.pdf-table td { background: #fff; padding-top: 12px; padding-bottom: 12px; font-size: 12px; vertical-align: top; page-break-inside: avoid; }
.pdf-table th { font-weight: bolder; font-size: 16px; padding-top: 8px; padding-bottom: 8px; } .pdf-content {
.pdf-small { font-weight: 400; font-size: 9px; } width: 21cm;
.pdf-mid { font-size: 14px; font-weight: 800; } margin: 0 auto;
.title-main { font-size: 30px; color: #409EFF; font-weight: bold; margin-bottom: 12px; } font-family: 等线 !important;
.city-list { color: #666; margin-bottom: 12px; } }
.primary-bar { width: 80px; height: 4px; background: #409EFF; margin-bottom: 16px; }
.flex-row { display: flex; flex-direction: row; } .pdf-table {
.align-center { align-items: center; } background: #eef0f2;
.column { display: flex; flex-direction: column; } width: 100%;
.bold { font-weight: bold; } }
.primary-text { color: #409EFF; }
.info-text { color: #999; } .pdf-table th,
.negative-text { color: #e53935; } .pdf-table td {
.h6 { font-size: 18px; } padding-left: 16px;
.subtitle2 { font-size: 16px; } padding-right: 16px;
.text-right { text-align: right; } text-align: left;
.text-center { text-align: center; } }
.flex-1 { flex: 1; }
.mt-md { margin-top: 16px; } .pdf-table td {
.mb-md { margin-bottom: 16px; } background: #fff;
.mt-lg { margin-top: 32px; } padding-top: 12px;
.mb-lg { margin-bottom: 32px; } padding-bottom: 12px;
.mt-xl { margin-top: 48px; } font-size: 12px;
.my-md { margin-top: 16px; margin-bottom: 16px; } vertical-align: top;
.mb-sm { margin-bottom: 8px; } page-break-inside: avoid;
.mt-md { margin-top: 16px; } }
.ml-sm { margin-left: 8px; }
.mr-xs { margin-right: 4px; } .pdf-table th {
.pa-md { padding: 16px; } font-weight: bolder;
.pa-sm { padding: 8px; } font-size: 16px;
.py-sm { padding-top: 8px; padding-bottom: 8px; } padding-top: 8px;
.primary-bar { background: #409EFF; } padding-bottom: 8px;
.accent-bar-h { height: 2px; width: 14px; background: #409EFF; } }
.accent-bar-v { width: 2px; flex: 1; background: #409EFF; }
.icon-feiji-box { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(180deg); background: #fff; border-radius: 100%; padding: 2px; } .pdf-small {
.relative { position: relative; } font-weight: 400;
font-size: 9px;
}
.pdf-mid {
font-size: 14px;
font-weight: 800;
}
.title-main {
font-size: 30px;
color: #409EFF;
font-weight: bold;
margin-bottom: 12px;
}
.city-list {
color: #666;
margin-bottom: 12px;
}
.primary-bar {
width: 80px;
height: 4px;
background: #409EFF;
margin-bottom: 16px;
}
.flex-row {
display: flex;
flex-direction: row;
}
.align-center {
align-items: center;
}
.column {
display: flex;
flex-direction: column;
}
.bold {
font-weight: bold;
}
.primary-text {
color: #409EFF;
}
.info-text {
color: #999;
}
.negative-text {
color: #e53935;
}
.h6 {
font-size: 18px;
}
.subtitle2 {
font-size: 16px;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
.flex-1 {
flex: 1;
}
.mt-md {
margin-top: 16px;
}
.mb-md {
margin-bottom: 16px;
}
.mt-lg {
margin-top: 32px;
}
.mb-lg {
margin-bottom: 32px;
}
.mt-xl {
margin-top: 48px;
}
.my-md {
margin-top: 16px;
margin-bottom: 16px;
}
.mb-sm {
margin-bottom: 8px;
}
.mt-md {
margin-top: 16px;
}
.ml-sm {
margin-left: 8px;
}
.mr-xs {
margin-right: 4px;
}
.pa-md {
padding: 16px;
}
.pa-sm {
padding: 8px;
}
.py-sm {
padding-top: 8px;
padding-bottom: 8px;
}
.primary-bar {
background: #409EFF;
}
.accent-bar-h {
height: 2px;
width: 14px;
background: #409EFF;
}
.accent-bar-v {
width: 2px;
flex: 1;
background: #409EFF;
}
.icon-feiji-box {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(180deg);
background: #fff;
border-radius: 100%;
padding: 2px;
}
.relative {
position: relative;
}
.pdf-float-btn { .pdf-float-btn {
position: fixed; position: fixed;
right: 32px; right: 32px;
...@@ -437,12 +602,13 @@ export default { ...@@ -437,12 +602,13 @@ export default {
color: #fff; color: #fff;
padding: 14px 28px; padding: 14px 28px;
border-radius: 28px; border-radius: 28px;
box-shadow: 0 2px 8px rgba(64,158,255,0.15); box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
transition: background 0.2s; transition: background 0.2s;
} }
.pdf-float-btn:hover { .pdf-float-btn:hover {
background: #337ecc; background: #337ecc;
} }
...@@ -451,12 +617,16 @@ export default { ...@@ -451,12 +617,16 @@ export default {
@page { @page {
size: A4; size: A4;
} }
@media print { @media print {
@page { @page {
size: A4 portrait; size: A4 portrait;
margin: 0; margin: 0;
} }
html, body, .pdf-content {
html,
body,
.pdf-content {
width: 100% !important; width: 100% !important;
min-width: 0 !important; min-width: 0 !important;
max-width: 100% !important; max-width: 100% !important;
...@@ -464,26 +634,33 @@ export default { ...@@ -464,26 +634,33 @@ export default {
padding: 0 !important; padding: 0 !important;
background: unset !important; background: unset !important;
} }
.pdf-table { .pdf-table {
width: 100% !important; width: 100% !important;
} }
.pdf-float-btn { .pdf-float-btn {
display: none !important; display: none !important;
} }
.full-box { .full-box {
overflow: visible !important; overflow: visible !important;
height: auto !important; height: auto !important;
max-height: none !important; max-height: none !important;
} }
.pdf-content { .pdf-content {
width: 21cm !important; width: 21cm !important;
margin: 0 auto !important; margin: 0 auto !important;
} }
.pdf-table tr { .pdf-table tr {
page-break-inside: avoid !important; page-break-inside: avoid !important;
break-inside: avoid !important; break-inside: avoid !important;
} }
.customerServiceButton {
display: none;
}
} }
</style> </style>
...@@ -50,25 +50,7 @@ ...@@ -50,25 +50,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" size="small" @click="handleEdit(scope.row)">修改</el-button> <el-button type="text" size="small" @click="handleEdit(scope.row)">修改</el-button>
<el-button type="text" size="small" style="color:#f56c6c;margin-right: 10px;" @click="handleDelete(scope.row)">删除</el-button> <el-button type="text" size="small" style="color:#f56c6c;margin-right: 10px;" @click="handleDelete(scope.row)">删除</el-button>
<el-dropdown trigger="click" @command="(command) => handleCommand(command, scope.row)"> <el-button type="text" size="small" @click="openPublishDialog(scope.row)">发布行程</el-button>
<el-button type="text" size="small">
更多<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="wechatH5" divided>
<i class="el-icon-document"></i> 微信H5行程书
</el-dropdown-item>
<el-dropdown-item command="pdfItinerary">
<i class="el-icon-document"></i> PDF行程书
</el-dropdown-item>
<el-dropdown-item command="webSchedule" divided>
<i class="el-icon-tickets"></i> Web行程单
</el-dropdown-item>
<el-dropdown-item command="pdfSchedule">
<i class="el-icon-tickets"></i> PDF行程单
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -95,6 +77,45 @@ ...@@ -95,6 +77,45 @@
</el-tabs> </el-tabs>
</div> </div>
</div> </div>
<el-dialog
title="发布行程"
:visible.sync="publishDialogVisible"
width="400px"
@close="resetPublishDialog"
append-to-body
>
<div class="publish-options-grid">
<div
v-for="item in publishOptions"
:key="item.command"
class="publish-option-card"
:class="{ active: currentPublishOption === item.command }"
@click="handlePublishOption(item.command)"
>
<!-- <i :class="['el-icon', item.icon]" style="font-size: 28px; margin-bottom: 8px; color: #409EFF;" /> -->
<div class="option-label">{{ item.label }}</div>
</div>
</div>
<div class="qrcode-area" style="margin: 24px 0; text-align: center;" v-loading="createQrcode">
<div style="height: 100px; width: 100px; background: #f5f5f5; display: inline-block; border-radius: 8px; line-height: 100px;">
<!-- 这里放二维码图片 -->
<img :src="qrcodeUrl" style="width: 100%; height: 100%;" />
</div>
<div style="margin-top: 8px; color: #888; font-size: 12px;">扫码查看行程</div>
</div>
<el-input
v-model="publishShareLink"
readonly
placeholder="这里是分享链接"
style="width: 100%;"
v-if="currentPublishOption!='wechatH5'"
>
<template #append>
<el-button @click="copyPublishLink">复制</el-button>
</template>
</el-input>
<div style="height: 30px;"></div>
</el-dialog>
</el-drawer> </el-drawer>
</template> </template>
...@@ -102,6 +123,7 @@ ...@@ -102,6 +123,7 @@
import { requirementService } from '@/services/requirement'; import { requirementService } from '@/services/requirement';
import { itineraryService } from '@/services/itinerary'; import { itineraryService } from '@/services/itinerary';
import InfoCard from './InfoCard.vue'; import InfoCard from './InfoCard.vue';
import QRCode from 'qrcode'
export default { export default {
name: 'RequirementDetail', name: 'RequirementDetail',
...@@ -124,7 +146,19 @@ export default { ...@@ -124,7 +146,19 @@ export default {
activeTab: 'basic', activeTab: 'basic',
loading: false, loading: false,
detail: this.getInitialDetailState(), detail: this.getInitialDetailState(),
baseHref:'http://'+location.host+'/#' baseHref:'http://'+location.host+'/#',
publishDialogVisible: false,
publishRow: null,
publishShareLink: '',
publishOptions: [
{ command: 'wechatH5', label: '小程序行程书', icon: 'el-icon-document' },
{ command: 'pdfItinerary', label: 'TD行程书', icon: 'el-icon-document' },
{ command: 'webSchedule', label: 'Web行程单', icon: 'el-icon-tickets' },
{ command: 'pdfSchedule', label: 'PDF行程单', icon: 'el-icon-tickets' }
],
currentPublishOption: 'wechatH5',
qrcodeUrl: '',
createQrcode: false
} }
}, },
computed: { computed: {
...@@ -207,6 +241,15 @@ export default { ...@@ -207,6 +241,15 @@ export default {
handleEdit(row) { handleEdit(row) {
window.open(`${this.baseHref}/itinerary/edit/${row.id}`, '_blank'); window.open(`${this.baseHref}/itinerary/edit/${row.id}`, '_blank');
}, },
async handleTravelPdf(id) {
try {
const response = await itineraryService.getPdfItinerary(id);
return response;
} catch (error) {
this.$message.error('获取行程PDF失败');
return null;
}
},
handleDelete(row) { handleDelete(row) {
this.$confirm(`是否确认删除【${row.title}】?`, '提示', { this.$confirm(`是否确认删除【${row.title}】?`, '提示', {
type: 'warning' type: 'warning'
...@@ -220,26 +263,64 @@ export default { ...@@ -220,26 +263,64 @@ export default {
} }
}).catch(() => {}); }).catch(() => {});
}, },
handleCommand(command, row) { openPublishDialog(row) {
this.publishRow = row;
this.publishDialogVisible = true;
// 默认分享链接,可根据实际需求生成
this.publishShareLink = '';
this.qrcodeUrl = '';
this.createQrcode = false;
this.currentPublishOption = 'wechatH5';
this.handlePublishOption(this.currentPublishOption);
},
resetPublishDialog() {
this.publishDialogVisible = false;
this.publishRow = null;
this.publishShareLink = '';
},
handlePublishOption(command) {
const row = this.publishRow;
switch (command) { switch (command) {
case 'wechatH5': case 'wechatH5':
this.handleWechatH5(row); this.handleWechatH5(row);
this.currentPublishOption = 'wechatH5';
break; break;
case 'pdfItinerary': case 'pdfItinerary':
this.handlePDFItinerary(row); this.handlePDFItinerary(row);
this.currentPublishOption = 'pdfItinerary';
break; break;
case 'webSchedule': case 'webSchedule':
this.handleWebSchedule(row); this.handleWebSchedule(row);
this.currentPublishOption = 'webSchedule';
break; break;
case 'pdfSchedule': case 'pdfSchedule':
this.handlePDFSchedule(row); this.handlePDFSchedule(row);
this.currentPublishOption = 'pdfSchedule';
break; break;
} }
}, },
copyPublishLink() {
if (navigator.clipboard) {
navigator.clipboard.writeText(this.publishShareLink).then(() => {
this.$message.success('复制成功');
});
} else {
const input = document.createElement('input');
input.value = this.publishShareLink;
document.body.appendChild(input);
input.select();
document.execCommand('copy');
document.body.removeChild(input);
this.$message.success('复制成功');
}
},
handleWechatH5(row) { handleWechatH5(row) {
// 生成微信H5链接并打开 // 生成微信H5链接并打开
const url = `${this.baseHref}/itinerary/h5/${row.id}`; // const url = `${this.baseHref}/itinerary/h5/${row.id}`;
window.open(url, '_blank'); // window.open(url, '_blank');
this.qrcodeUrl='';
this.createQrcode = true;
this.getMiniProgramQrcode(row.autoId);
}, },
handlePDFItinerary(row) { handlePDFItinerary(row) {
// 下载PDF行程书 // 下载PDF行程书
...@@ -247,11 +328,61 @@ export default { ...@@ -247,11 +328,61 @@ export default {
}, },
handleWebSchedule(row) { handleWebSchedule(row) {
// 打开Web行程单页面 // 打开Web行程单页面
window.open(`${this.baseHref}/itinerary/detail/${row.id}`, '_blank'); // window.open(`${this.baseHref}/itinerary/detail/${row.id}`, '_blank');
this.createQrcode = true;
this.canvasQrCode(`${this.baseHref}/itinerary/detail/${row.id}`)
this.publishShareLink = `${this.baseHref}/itinerary/detail/${row.id}`;
}, },
handlePDFSchedule(row) { async handlePDFSchedule(row) {
// 下载PDF行程单 // 下载PDF行程单
window.open(`${this.baseHref}/api/itinerary/pdf/schedule/${row.id}`, '_blank'); //window.open(`${this.baseHref}/api/itinerary/pdf/schedule/${row.id}`, '_blank');
this.createQrcode = true;
let pdfName = await this.handleTravelPdf(row.id);
this.qrcodeUrl = '';
this.publishShareLink = '';
if (pdfName) {
pdfName = pdfName.replace('"', '');
const url = `https://imgfile.oytour.com/aipdf/${pdfName}`;
console.log(url);
this.canvasQrCode(url)
this.publishShareLink = url;
}
},
getMiniProgramQrcode(id) {
let urlObj = this.domainManager();
this.$http({
headers: {
'Content-Type': 'application/json'
},
method: 'post',
url: urlObj.DomainUrl + '/api/file/GetAiTravelInfo',
data: {
"msg": {
"id": id
}
}
}).then(res => {
if (res.data.resultCode === 1) {
this.qrcodeUrl = "data:image/png;base64,"+res.data.data
this.createQrcode = false;
}
}).catch(err => {
this.createQrcode = false;
this.$message.error('获取小程序二维码失败');
})
},
canvasQrCode(text) {
let that = this
QRCode.toDataURL(text, {
color: {
dark: "000",
light: "#fff"
}
}, function (err, url) {
that.qrcodeUrl = url
that.createQrcode = false;
})
}, },
getTimelineItemType(state) { getTimelineItemType(state) {
const typeMap = { const typeMap = {
...@@ -316,4 +447,37 @@ export default { ...@@ -316,4 +447,37 @@ export default {
color: #606266; color: #606266;
font-size: 13px; font-size: 13px;
} }
.publish-options-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 18px 24px;
justify-items: center;
margin-bottom: 24px;
margin-top: 8px;
}
.publish-option-card {
width: 140px;
height: 60px;
background: #f7fafd;
border-radius: 12px;
box-shadow: 0 1px 4px rgba(64,158,255,0.06);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: box-shadow 0.2s, background 0.2s;
border: 1px solid #e6f0fa;
}
.publish-option-card:hover,
.publish-option-card.active {
background: #e6f7ff;
box-shadow: 0 4px 16px rgba(64,158,255,0.12);
}
.option-label {
font-size: 14px;
color: #333;
font-weight: 500;
}
</style> </style>
...@@ -122,7 +122,7 @@ export default { ...@@ -122,7 +122,7 @@ export default {
let locationName = window.location.hostname; let locationName = window.location.hostname;
let isOnline = 0; //0-本地测试,1-线上 let isOnline = 0; //0-本地测试,1-线上
let ocrUrl = "http://192.168.5.46:8888"; let ocrUrl = "http://192.168.5.46:8888";
domainUrl = "http://192.168.5.46"; domainUrl = "http://reborn.oytour.com";
let crmLocalFileStreamDownLoadUrl = ""; let crmLocalFileStreamDownLoadUrl = "";
crmLocalFileStreamDownLoadUrl = locationName.indexOf('oytour') !== -1 ? "http://crm.oytour.com" : "http://testcrm.oytour.com"; crmLocalFileStreamDownLoadUrl = locationName.indexOf('oytour') !== -1 ? "http://crm.oytour.com" : "http://testcrm.oytour.com";
let javaUrldo = ""; let javaUrldo = "";
......
...@@ -4,7 +4,7 @@ import axios from 'axios'; ...@@ -4,7 +4,7 @@ import axios from 'axios';
// 创建 axios 实例 // 创建 axios 实例
const service = axios.create({ const service = axios.create({
baseURL: process.env.NODE_ENV === 'production'?'http://rw.oytour.com/api/app':'http://rw.oytour.com/api/app',//'http://localhost:19001/api/app', // 通用前缀 baseURL: process.env.NODE_ENV === 'production'?'http://rw.oytour.com/api/app':'http://rw.oytour.com/api/app',//'http://localhost:19001/api/app', // 通用前缀
timeout: 10000 timeout: 1000 * 60
}); });
// 请求拦截器:自动加 token // 请求拦截器:自动加 token
......
...@@ -28,6 +28,15 @@ export const itineraryService = { ...@@ -28,6 +28,15 @@ export const itineraryService = {
return rwRequest.delete('/travel/'+id); return rwRequest.delete('/travel/'+id);
}, },
/**
* 获取行程PDF
* @param {string} id - 行程ID
* @returns {Promise} - API 响应
*/
getPdfItinerary: (id) => {
return rwRequest.get('/travel/'+id+"/pdf");
},
/** /**
* 更新行程 * 更新行程
* @param {Object} data - 行程数据 * @param {Object} data - 行程数据
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment