26 changed files with 11907 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||||
|
NODE_ENV='development' |
||||
|
# 请求域名前缀 |
||||
|
VUE_APP_URL='https://tongli.sz-trip.com' |
||||
|
# 打包后输出目录 |
||||
|
VUE_APP_OUTPUTDIR='dist_dev' |
@ -0,0 +1,5 @@ |
|||||
|
NODE_ENV='production' |
||||
|
# 请求域名前缀 |
||||
|
VUE_APP_URL='https://tongli.sz-trip.com' |
||||
|
# 打包后输出目录 |
||||
|
VUE_APP_OUTPUTDIR='dist' |
@ -0,0 +1,5 @@ |
|||||
|
NODE_ENV='production' |
||||
|
# 请求域名前缀 |
||||
|
VUE_APP_URL='https://tongli.sz-trip.com' |
||||
|
# 打包后输出目录 |
||||
|
VUE_APP_OUTPUTDIR='dist_test' |
@ -0,0 +1,23 @@ |
|||||
|
.DS_Store |
||||
|
node_modules |
||||
|
/dist |
||||
|
|
||||
|
|
||||
|
# local env files |
||||
|
.env.local |
||||
|
.env.*.local |
||||
|
|
||||
|
# Log files |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
pnpm-debug.log* |
||||
|
|
||||
|
# Editor directories and files |
||||
|
.idea |
||||
|
.vscode |
||||
|
*.suo |
||||
|
*.ntvs* |
||||
|
*.njsproj |
||||
|
*.sln |
||||
|
*.sw? |
@ -0,0 +1,5 @@ |
|||||
|
module.exports = { |
||||
|
presets: [ |
||||
|
'@vue/cli-plugin-babel/preset' |
||||
|
] |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
{ |
||||
|
"compilerOptions": { |
||||
|
"target": "es5", |
||||
|
"module": "esnext", |
||||
|
"baseUrl": "./", |
||||
|
"moduleResolution": "node", |
||||
|
"paths": { |
||||
|
"@/*": [ |
||||
|
"src/*" |
||||
|
] |
||||
|
}, |
||||
|
"lib": [ |
||||
|
"esnext", |
||||
|
"dom", |
||||
|
"dom.iterable", |
||||
|
"scripthost" |
||||
|
] |
||||
|
} |
||||
|
} |
File diff suppressed because it is too large
@ -0,0 +1,63 @@ |
|||||
|
{ |
||||
|
"name": "taihulake", |
||||
|
"version": "0.1.0", |
||||
|
"private": true, |
||||
|
"scripts": { |
||||
|
"serve": "vue-cli-service serve --open", |
||||
|
"build": "vue-cli-service build", |
||||
|
"test": "vue-cli-service build --mode test", |
||||
|
"lint": "vue-cli-service lint" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"amfe-flexible": "^2.2.1", |
||||
|
"axios": "^1.3.2", |
||||
|
"core-js": "^3.8.3", |
||||
|
"html-webpack-plugin": "^5.5.1", |
||||
|
"moment": "^2.30.1", |
||||
|
"postcss-px2rem-exclude": "0.0.6", |
||||
|
"postcss-pxtorem": "^6.1.0", |
||||
|
"qs": "^6.11.0", |
||||
|
"vant": "^2.12.53", |
||||
|
"vue": "^2.6.14", |
||||
|
"vue-router": "^3.5.3", |
||||
|
"vuex": "^3.6.2", |
||||
|
"webpack-bundle-analyzer": "^4.8.0" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@babel/core": "^7.12.16", |
||||
|
"@babel/eslint-parser": "^7.12.16", |
||||
|
"@vue/cli-plugin-babel": "~5.0.0", |
||||
|
"@vue/cli-plugin-eslint": "~5.0.0", |
||||
|
"@vue/cli-service": "~5.0.0", |
||||
|
"babel-plugin-import": "^1.13.6", |
||||
|
"eslint": "^7.32.0", |
||||
|
"eslint-plugin-vue": "^8.0.3", |
||||
|
"node-sass": "^4.14.1", |
||||
|
"postcss": "^8.4.45", |
||||
|
"postcss-loader": "^3.0.0", |
||||
|
"px2rem-loader": "^0.1.9", |
||||
|
"sass-loader": "^7.3.1", |
||||
|
"vue-template-compiler": "^2.6.14" |
||||
|
}, |
||||
|
"eslintConfig": { |
||||
|
"root": true, |
||||
|
"env": { |
||||
|
"node": true |
||||
|
}, |
||||
|
"extends": [ |
||||
|
"plugin:vue/essential", |
||||
|
"eslint:recommended" |
||||
|
], |
||||
|
"parserOptions": { |
||||
|
"parser": "@babel/eslint-parser" |
||||
|
}, |
||||
|
"rules": { |
||||
|
"no-mixed-spaces-and-tabs": 0 |
||||
|
} |
||||
|
}, |
||||
|
"browserslist": [ |
||||
|
"> 1%", |
||||
|
"last 2 versions", |
||||
|
"not dead" |
||||
|
] |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
const autoprefixer = require('autoprefixer'); |
||||
|
const px2rem = require('postcss-pxtorem'); |
||||
|
|
||||
|
module.exports = { |
||||
|
plugins: [ |
||||
|
autoprefixer(), |
||||
|
px2rem({ |
||||
|
rootValue(res) { |
||||
|
return res.file.indexOf('vant') !== -1 ? 37.5 : 75 //换算基数,1rem相当于75px
|
||||
|
}, |
||||
|
unitPrecision: 5, //保留rem小数点多少位
|
||||
|
propList: ['*'], |
||||
|
minPixelValue: 12 //px小于12的不会被转换
|
||||
|
}) |
||||
|
] |
||||
|
} |
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,24 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang=""> |
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0"> |
||||
|
<link rel="icon" href="<%= htmlWebpackPlugin.options.url %>favicon.ico"> |
||||
|
<title>地图</title> |
||||
|
<!-- 腾讯地图 --> |
||||
|
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=YVOBZ-MWJ3Z-34IXK-7J2GL-O33US-QLF5X"> |
||||
|
</script> |
||||
|
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> |
||||
|
<!-- 引入uniSDK --> |
||||
|
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script> |
||||
|
</head> |
||||
|
<body> |
||||
|
<noscript> |
||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript |
||||
|
enabled. Please enable it to continue.</strong> |
||||
|
</noscript> |
||||
|
<div id="app"></div> |
||||
|
<!-- built files will be auto injected --> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,59 @@ |
|||||
|
<template> |
||||
|
<div id="app"> |
||||
|
<keep-alive> |
||||
|
<router-view v-if="$route.meta.keepAlive"></router-view> |
||||
|
</keep-alive> |
||||
|
<router-view v-if="!$route.meta.keepAlive"></router-view> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'App', |
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
div { |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.flex-between { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.flex-around { |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.flex-center { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
/*单行隐藏*/ |
||||
|
.text-overflow { |
||||
|
overflow-x: hidden; |
||||
|
overflow-y: inherit; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
/* 两行隐藏 */ |
||||
|
.text-overflowRows { |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
-webkit-line-clamp: 2; |
||||
|
word-break: break-all; |
||||
|
display: -webkit-box; |
||||
|
-webkit-box-orient: vertical; |
||||
|
} |
||||
|
</style> |
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,91 @@ |
|||||
|
import Vue from 'vue' |
||||
|
/**引入axios*/ |
||||
|
import axios from "axios"; |
||||
|
/**引入参数处理*/ |
||||
|
// import Qs from 'qs';
|
||||
|
import {Dialog, Toast} from "vant"; |
||||
|
import store from '@/store'; |
||||
|
const http = axios.create({ |
||||
|
baseURL: process.env.VUE_APP_URL, |
||||
|
timeout: 6000 // 请求超时时间 当请求时间超过`秒还未取得结果时 提示用户请求超时
|
||||
|
}) |
||||
|
|
||||
|
//添加请求拦截器
|
||||
|
http.interceptors.request.use((config) => { |
||||
|
const token = store.state.user.userInfo.token; |
||||
|
config.headers['token'] = token |
||||
|
config.headers['Content-Type'] = 'application/json;charset=UTF-8' |
||||
|
// if(config.loading === true){
|
||||
|
Toast.loading({ |
||||
|
message: '加载中...', |
||||
|
forbidClick: true, |
||||
|
duration: 0 |
||||
|
}); |
||||
|
// }
|
||||
|
return config; |
||||
|
}, (error) => { |
||||
|
return Promise.reject(error); |
||||
|
}); |
||||
|
|
||||
|
// 添加响应拦截器
|
||||
|
http.interceptors.response.use(response => { |
||||
|
Toast.clear() |
||||
|
if(response.status === 200 || response.status === 1){ |
||||
|
return response.data; |
||||
|
} |
||||
|
},error => { |
||||
|
if(error.response && error.response.status){ |
||||
|
switch(error.response.status){ |
||||
|
case 401: |
||||
|
Dialog.confirm({ |
||||
|
title: '提示', |
||||
|
message: '请登录后操作', |
||||
|
confirmButtonText: '去登录' |
||||
|
}).then(() => { |
||||
|
// 登录操作
|
||||
|
}); |
||||
|
break; |
||||
|
case 404: |
||||
|
Toast.fail({ |
||||
|
type: "fail", |
||||
|
message: '网络繁忙,请刷新再试', |
||||
|
forbidClick: true, |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
break; |
||||
|
default: |
||||
|
Toast.fail({ |
||||
|
type: "fail", |
||||
|
message: '网络繁忙,请刷新再试', |
||||
|
forbidClick: true, |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 请求
|
||||
|
Vue.prototype.get = (params, url, loading) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
http.get(url, params, loading) |
||||
|
.then(res => { |
||||
|
resolve(res); |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
reject(err); |
||||
|
}); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
Vue.prototype.post = (data, url, loading) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
http.post(url, data, loading) |
||||
|
.then(res => { |
||||
|
resolve(res); |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
reject(err); |
||||
|
}); |
||||
|
}) |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
import { |
||||
|
validatenull |
||||
|
} from '@/libs/tools'; |
||||
|
|
||||
|
const keyName = '' + '-'; //随便写个自己的标识
|
||||
|
|
||||
|
//存储sessionStorage
|
||||
|
export const setStore = (params = {}) => { |
||||
|
let { |
||||
|
name, |
||||
|
content, |
||||
|
type, |
||||
|
} = params; |
||||
|
name = keyName + name |
||||
|
let obj = { |
||||
|
dataType: typeof(content), |
||||
|
content: content, |
||||
|
type: type, |
||||
|
datetime: new Date().getTime() |
||||
|
} |
||||
|
if (type) window.sessionStorage.setItem(name, JSON.stringify(obj)); |
||||
|
else window.localStorage.setItem(name, JSON.stringify(obj)); |
||||
|
} |
||||
|
|
||||
|
//获取sessionStorage
|
||||
|
export const getStore = (params = {}) => { |
||||
|
let { |
||||
|
name, |
||||
|
debug |
||||
|
} = params; |
||||
|
name = keyName + name |
||||
|
let obj = {}, |
||||
|
content; |
||||
|
obj = window.sessionStorage.getItem(name); |
||||
|
if (validatenull(obj)) obj = window.localStorage.getItem(name); |
||||
|
if (validatenull(obj)) return; |
||||
|
try { |
||||
|
obj = JSON.parse(obj); |
||||
|
} catch { |
||||
|
return obj; |
||||
|
} |
||||
|
if (debug) { |
||||
|
return obj; |
||||
|
} |
||||
|
if (obj.dataType == 'string') { |
||||
|
content = obj.content; |
||||
|
} else if (obj.dataType == 'number') { |
||||
|
content = Number(obj.content); |
||||
|
} else if (obj.dataType == 'boolean') { |
||||
|
content = eval(obj.content); |
||||
|
} else if (obj.dataType == 'object') { |
||||
|
content = obj.content; |
||||
|
} |
||||
|
return content; |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
//判断是否为空
|
||||
|
export function validatenull(val) { |
||||
|
if (typeof val == 'boolean') { |
||||
|
return false; |
||||
|
} |
||||
|
if (typeof val == 'number') { |
||||
|
return false; |
||||
|
} |
||||
|
if (val instanceof Array) { |
||||
|
if (val.length == 0) return true; |
||||
|
} else if (val instanceof Object) { |
||||
|
if (JSON.stringify(val) === '{}') return true; |
||||
|
} else { |
||||
|
if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true; |
||||
|
return false; |
||||
|
} |
||||
|
return false; |
||||
|
} |
@ -0,0 +1,76 @@ |
|||||
|
export default { |
||||
|
install(Vue) { |
||||
|
Vue.prototype.util = { |
||||
|
// 格式化富文本
|
||||
|
formateRichText(str) { |
||||
|
if (!str) return ""; |
||||
|
var reg = new RegExp("<img", "g"); |
||||
|
str = str.replace(reg, "<img class='sz-xcx-fwb-img' width='100%'") |
||||
|
reg = new RegExp("<IMG", "g"); |
||||
|
str = str.replace(reg, "<img class='sz-xcx-fwb-img' width='100%'") |
||||
|
reg = new RegExp(" ", "g"); |
||||
|
str = str.replace(reg, '<span style="width: 8rpx;display: inline-block;"></span>') |
||||
|
reg = new RegExp("section", "g"); |
||||
|
str = str.replace(reg, 'div'); |
||||
|
reg = new RegExp("↵", "g"); |
||||
|
str = str.replace(reg, '<br />'); |
||||
|
str = str.replace(/<table/g, '<table border="1" cellspacing="0" style="border-collapse:collapse"') |
||||
|
return str; |
||||
|
}, |
||||
|
// 手机号验证规则
|
||||
|
mobileValid(val) { |
||||
|
return /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(val); |
||||
|
}, |
||||
|
// 身份证验证规则
|
||||
|
idNumberValid(val) { |
||||
|
return /^\d{17}(\d{1}|[X|x])$/.test(val); |
||||
|
}, |
||||
|
// 护照验证正则
|
||||
|
passportValid(val) { |
||||
|
return /^([a-zA-z]|[0-9]){5,17}$/.test(val); |
||||
|
}, |
||||
|
// 台胞证正则
|
||||
|
taiwanValid(val) { |
||||
|
return /^\d{8}|^[a-zA-Z0-9]{10}|^\d{18}$/.test(val); |
||||
|
}, |
||||
|
// 港澳通行证正则
|
||||
|
gangaoValid(val) { |
||||
|
return /^([A-Z]\d{6,10}(\(\w{1}\))?)$/.test(val); |
||||
|
}, |
||||
|
// 外国人永久居留证正则
|
||||
|
foreignerValid(val) { |
||||
|
return /(^[A-Za-z]{3})([0-9]{12}$)/.test(val); |
||||
|
}, |
||||
|
// 军官证正则
|
||||
|
officerValid(val) { |
||||
|
return /^[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)$/.test(val); |
||||
|
}, |
||||
|
// 邮箱验证正则
|
||||
|
emailValid(val) { |
||||
|
return /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(val) |
||||
|
}, |
||||
|
// 获取路径参数
|
||||
|
getUrlPara(url) { |
||||
|
let arrUrl = url.split("?"); |
||||
|
let para = arrUrl[1]; |
||||
|
return para ? para.split('&') : false; |
||||
|
}, |
||||
|
openMap(item) { |
||||
|
uni.openLocation({ |
||||
|
longitude: item.lon, // 经度
|
||||
|
latitude: item.lat, //纬度
|
||||
|
name: item.address || item.title || item.name, // 位置名称
|
||||
|
address: item.address, //详细地址
|
||||
|
}) |
||||
|
}, |
||||
|
showImg(img) { |
||||
|
if(!img) return; |
||||
|
if (img.indexOf('https://') != -1 || img.indexOf('http://') != -1) { |
||||
|
return img; |
||||
|
} else { |
||||
|
return 'https://tongli.sz-trip.com' + img; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
import Vue from 'vue' |
||||
|
import App from './App.vue' |
||||
|
import store from './store' |
||||
|
import '../src/libs/axios.js' // axios处理
|
||||
|
// 引入amfe-flexible做rem适配
|
||||
|
import "amfe-flexible" |
||||
|
import router from "./router" |
||||
|
|
||||
|
import utils from './libs/utils.js' |
||||
|
Vue.use(utils) |
||||
|
|
||||
|
import Vant from 'vant'; |
||||
|
import 'vant/lib/index.css'; |
||||
|
Vue.use(Vant); |
||||
|
|
||||
|
// Vue.prototype.ShowLoading = (title) => {
|
||||
|
// Vue.prototype.$toast.loading({
|
||||
|
// message: title ? title : '请求中',
|
||||
|
// forbidClick: true,
|
||||
|
// duration: 0
|
||||
|
// })
|
||||
|
// }
|
||||
|
|
||||
|
Vue.config.productionTip = false |
||||
|
|
||||
|
new Vue({ |
||||
|
store, |
||||
|
router, |
||||
|
render: h => h(App), |
||||
|
}).$mount('#app') |
@ -0,0 +1,27 @@ |
|||||
|
import Vue from "vue"; |
||||
|
import VueRouter from "vue-router"; |
||||
|
import Index from "../views/Index.vue"; |
||||
|
|
||||
|
Vue.use(VueRouter); |
||||
|
|
||||
|
const routes = [{ |
||||
|
path: "/", |
||||
|
name: "index", |
||||
|
meta: {title: "首页", keepAlive: true}, |
||||
|
component: Index, |
||||
|
}, |
||||
|
{ |
||||
|
path: "/lineList", |
||||
|
name: "lineList", |
||||
|
meta: {title: "", keepAlive: true}, |
||||
|
component: () =>import("../views/LineList.vue"), |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
const router = new VueRouter({ |
||||
|
mode: "history", |
||||
|
base: process.env.BASE_URL, |
||||
|
routes, |
||||
|
}); |
||||
|
|
||||
|
export default router; |
@ -0,0 +1,19 @@ |
|||||
|
import Vue from 'vue' |
||||
|
import Vuex from 'vuex' |
||||
|
import user from './modules/user' |
||||
|
|
||||
|
Vue.use(Vuex) |
||||
|
|
||||
|
export default new Vuex.Store({ |
||||
|
state: { |
||||
|
|
||||
|
}, |
||||
|
mutations: { |
||||
|
|
||||
|
}, |
||||
|
actions: {}, |
||||
|
modules: { |
||||
|
namespaced: true, // 为了解决不同模块命名冲突的问题
|
||||
|
user |
||||
|
} |
||||
|
}) |
@ -0,0 +1,19 @@ |
|||||
|
import { setStore, getStore } from '@/libs/storage' |
||||
|
export default { |
||||
|
state: { |
||||
|
userInfo: getStore({ name: 'userInfo' }) || '', // 保存用户登录信息
|
||||
|
}, |
||||
|
mutations: { |
||||
|
changeUserInfo(state, data) { |
||||
|
state.userInfo = data |
||||
|
setStore({ name: 'userInfo', content: state.userInfo, type: 'session' }) |
||||
|
if(data && data.token)localStorage.setItem('userInfo', JSON.stringify(data)) |
||||
|
}, |
||||
|
}, |
||||
|
getters: { |
||||
|
|
||||
|
}, |
||||
|
actions: { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,566 @@ |
|||||
|
<template> |
||||
|
<div> |
||||
|
<div id="mapContainer" class="mapContainer"></div> |
||||
|
|
||||
|
<!-- 点位分类 --> |
||||
|
<div class="type-box"> |
||||
|
<div :class="['type-item',{'type-active': index == typeIndex}]" v-for="(item,index) in mapType" |
||||
|
@click="getSpotsByCategory(index)">{{item.name}}</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="area-box"> |
||||
|
<!-- 区域分类 --> |
||||
|
<div> |
||||
|
<div class="area-item area-items" @click="areaMore = !areaMore"> |
||||
|
<img :src="'https://static.ticket.sz-trip.com/yandu/images/map/'+ (areaMore ? 'topIcon.png' : 'bottomIcon.png')" |
||||
|
alt="" /> |
||||
|
{{areaMore ? '收起' : '展开'}} |
||||
|
</div> |
||||
|
<div v-if="areaMore"> |
||||
|
<div v-for="(item,index) in areaList" :key="index" |
||||
|
:class="['area-item',{'area-active':index == areaIndex}]" @click="changeArea(index)"> |
||||
|
{{item.name}} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- 行程线路 --> |
||||
|
<div> |
||||
|
<div class="area-item area-items" @click="addLine"> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/addLine.png" alt="" /> |
||||
|
添加<br>行程 |
||||
|
</div> |
||||
|
<div class="area-item area-items" @click="gotoLine"> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/line.png" alt="" /> |
||||
|
线路<br>推荐 |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 详情弹框 --> |
||||
|
<van-popup v-model="detailShow" @close="audioPause" :overlay-style="{'background-color': 'rgba(0, 0, 0, 0)'}" |
||||
|
position="bottom" round> |
||||
|
<ProductDetail ref="detailRef" /> |
||||
|
</van-popup> |
||||
|
|
||||
|
<!-- 输入线路信息弹框 --> |
||||
|
<van-popup v-model="addLineShow" position="center" round> |
||||
|
<div class="addLine-box"> |
||||
|
添加行程 |
||||
|
<div class="addLine-item"> |
||||
|
线路名称: <input type="text" v-model="lineName" placeholder="请输入线路名称" /> |
||||
|
</div> |
||||
|
<div class="addLine-item"> |
||||
|
开始时间: <input type="text" v-model="lineDate" placeholder="请选择出发时间" readonly |
||||
|
@click="lineDateShow = true" /> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/dateRight.png" alt=""> |
||||
|
</div> |
||||
|
<div class="addLine-btn flex-around"> |
||||
|
<div @click="addLineShow = false">取消</div> |
||||
|
<div @click="lineClick">下一步</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</van-popup> |
||||
|
|
||||
|
<!-- 日期选择 --> |
||||
|
<van-popup v-model="lineDateShow" round position="bottom"> |
||||
|
<van-datetime-picker v-model="currentDate" type="date" title="选择年月日" @confirm="lineDateConfirm" /> |
||||
|
</van-popup> |
||||
|
|
||||
|
<!-- 添加线路行程弹框 --> |
||||
|
<van-popup v-model="lineRouteShow" round position="bottom"> |
||||
|
<LineRoute :id="lineId" :lineDate="lineDate" ref="lineRouteRef" /> |
||||
|
</van-popup> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import moment from 'moment' |
||||
|
import ProductDetail from './compoents/productDetail' |
||||
|
import LineRoute from './compoents/lineRoute' |
||||
|
export default { |
||||
|
components: { |
||||
|
ProductDetail, |
||||
|
LineRoute |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
mapObj: null, |
||||
|
mapMarker: null, |
||||
|
basics: {}, |
||||
|
mapType: [], |
||||
|
typeIndex: -1, |
||||
|
areaList: [], |
||||
|
areaIndex: 0, |
||||
|
areaMore: true, |
||||
|
detailShow: false, // 详情弹框 |
||||
|
addLineShow: false, // 输入线路名称和日期弹框 |
||||
|
lineName: '', |
||||
|
lineDate: '', |
||||
|
lineDateShow: false, // 选择日期弹框 |
||||
|
currentDate: new Date(), |
||||
|
lineRouteShow: false, // 添加线路行程弹框 |
||||
|
lineAddStatus: false, // 点击添加行程时为true,地图景点图标改变为加号 |
||||
|
lineId: '', |
||||
|
maps: [], //热点 |
||||
|
}; |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.getAreaList() |
||||
|
}, |
||||
|
methods: { |
||||
|
// 获取全部区域 |
||||
|
getAreaList() { |
||||
|
this.post({}, '/api/emap/get_map_list').then(res => { |
||||
|
this.areaList = res.data |
||||
|
if (res.data.length > 0) { |
||||
|
this.getAreaDetail() |
||||
|
this.getCategory() |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
// 更改地图区域 |
||||
|
changeArea(index) { |
||||
|
this.areaIndex = index |
||||
|
this.getAreaDetail() |
||||
|
}, |
||||
|
// 根据code获取当前区域信息 |
||||
|
getAreaDetail() { |
||||
|
this.post({ |
||||
|
code: this.areaList[this.areaIndex].code |
||||
|
}, '/api/emap/get_init').then(res => { |
||||
|
this.basics = res.data |
||||
|
this.basics.center_poi = JSON.parse(this.basics.center_poi) |
||||
|
this.basics.lb_poi = JSON.parse(this.basics.lb_poi) |
||||
|
this.basics.rt_poi = JSON.parse(this.basics.rt_poi) |
||||
|
this.$nextTick(() => { |
||||
|
this.initMap() |
||||
|
}) |
||||
|
}) |
||||
|
}, |
||||
|
// 根据code获取热点分类 |
||||
|
getCategory() { |
||||
|
this.post({ |
||||
|
code: this.areaList[this.areaIndex].code |
||||
|
}, '/api/emap/getByCategory').then(res => { |
||||
|
this.mapType = Array.from(res.data) |
||||
|
if(this.mapType.length > 0) this.getSpotsByCategory(0) |
||||
|
}) |
||||
|
}, |
||||
|
// 根据code、热点分类获取热点 |
||||
|
getSpotsByCategory(index) { |
||||
|
this.typeIndex = index |
||||
|
this.post({ |
||||
|
code: this.areaList[this.areaIndex].code, |
||||
|
category_id: this.mapType[this.typeIndex].id |
||||
|
},'/api/emap/getSpotsByCategory').then(res => { |
||||
|
console.log(res) |
||||
|
this.maps = res.data |
||||
|
// 移除原先点位 |
||||
|
this.clearMarkers() |
||||
|
if(this.maps.length > 0) this.setMarkers() |
||||
|
}) |
||||
|
}, |
||||
|
initMap() { |
||||
|
let centerLat = this.basics.center_poi[1] |
||||
|
let centerLon = this.basics.center_poi[0] |
||||
|
var center = new TMap.LatLng(this.basics.center_poi[1], this.basics.center_poi[0]) //设置中心点坐标 |
||||
|
var sw = new TMap.LatLng(this.basics.rt_poi[1], this.basics.rt_poi[0]); //东北角坐标, |
||||
|
var ne = new TMap.LatLng(this.basics.lb_poi[1], this.basics.lb_poi[0]); //西南角坐标, |
||||
|
var latlngBounds = new TMap.LatLngBounds(ne, sw); |
||||
|
// 初始化地图 |
||||
|
this.mapObj = new TMap.Map("mapContainer", { |
||||
|
center: center, |
||||
|
boundary: latlngBounds, |
||||
|
zoom: 12, // 地图默认缩放级别 |
||||
|
minZoom: 12, |
||||
|
maxZoom: 15, |
||||
|
showControl: true, // 是否显示地图上的控件 |
||||
|
// viewMode: '2D', // 地图视图模式,支持2D和3D,默认为3D。2D模式下俯仰角和旋转角度始终为0 |
||||
|
rotation: 0, //设置地图旋转角度 |
||||
|
}); |
||||
|
|
||||
|
this.mapObj.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM); // 移除缩放控件 |
||||
|
this.mapObj.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ROTATION); // 移除旋转控件 |
||||
|
|
||||
|
// 初始化瓦片 |
||||
|
// 瓦片图需要切好每个位置的图 |
||||
|
// x,y,z 为上图的坐标 |
||||
|
new TMap.ImageTileLayer({ |
||||
|
getTileUrl: function(x, y, z) { |
||||
|
console.log(x, y, z) |
||||
|
//拼接瓦片URL |
||||
|
let url = |
||||
|
`https://static.ticket.sz-trip.com/yandu/images/maps/` + |
||||
|
z + |
||||
|
"/" + |
||||
|
x + |
||||
|
"/" + |
||||
|
y + |
||||
|
".png"; |
||||
|
return url; |
||||
|
}, |
||||
|
tileSize: 256, //瓦片像素尺寸 |
||||
|
minZoom: 12, //显示自定义瓦片的最小级别 |
||||
|
maxZoom: 15, //显示自定义瓦片的最大级别 |
||||
|
visible: true, //是否可见 |
||||
|
zIndex: 5000, //层级高度(z轴) |
||||
|
opacity: 1, //图层透明度:1不透明,0为全透明 |
||||
|
map: this.mapObj, //设置图层显示到哪个地图实例中 |
||||
|
}); |
||||
|
|
||||
|
// 创建点聚合实例 |
||||
|
// this.markerCluster = new TMap.MarkerCluster({ |
||||
|
// id: "cluster", |
||||
|
// map: this.mapObj, |
||||
|
// enableDefaultStyle: true, // 是否启用默认样式 |
||||
|
// minimumClusterSize: 5, // 形成聚合簇的最小个数 |
||||
|
// geometries: [], // 点数组 |
||||
|
// zoomOnClick: true, |
||||
|
// gridSize: 60, |
||||
|
// averageCenter: true, |
||||
|
// }); |
||||
|
}, |
||||
|
// 地图打点 |
||||
|
setMarkers() { |
||||
|
// 聚合点点位 |
||||
|
// this.markerCluster.setGeometries([ |
||||
|
// { |
||||
|
// position: new TMap.LatLng(33.332682, 120.16451) |
||||
|
// }, |
||||
|
// { |
||||
|
// position: new TMap.LatLng(33.329281, 120.161117) |
||||
|
// } |
||||
|
// ]); |
||||
|
|
||||
|
let markers = [] |
||||
|
let labels = [] |
||||
|
this.maps.forEach(item => { |
||||
|
markers.push({ |
||||
|
"styleId": 'marker', |
||||
|
text: item.name, |
||||
|
position: new TMap.LatLng(item.poi_gcj02[1], item.poi_gcj02[0]) |
||||
|
}) |
||||
|
|
||||
|
labels.push({ |
||||
|
id: 'label', // 点图形数据的标志信息 |
||||
|
styleId: 'label', // 样式id |
||||
|
position: new TMap.LatLng(item.poi_gcj02[1], item.poi_gcj02[0]), // 标注点位置 |
||||
|
content: item.name, // 标注文本 |
||||
|
properties: { |
||||
|
// 标注点的属性数据 |
||||
|
title: 'label', |
||||
|
}, |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
// 添加marker点 |
||||
|
this.multiMarker = new TMap.MultiMarker({ |
||||
|
id: 'marker-layer', |
||||
|
map: this.mapObj, |
||||
|
styles: { |
||||
|
"marker": new TMap.MarkerStyle({ |
||||
|
"width": 24, |
||||
|
"height": 30, |
||||
|
"src": 'https://static.ticket.sz-trip.com/yandu/images/map/scenic.png', |
||||
|
"src": this.util.showImg(this.mapType.find(i => {return i.id == this.maps[0].category_id}).icon_image) |
||||
|
}) |
||||
|
}, |
||||
|
// 点数组 |
||||
|
geometries: markers, |
||||
|
}) |
||||
|
|
||||
|
// 标记点点击事件 |
||||
|
this.multiMarker.on("click", this.markerClick) |
||||
|
|
||||
|
// 文本标记 |
||||
|
this.multiLabel = new TMap.MultiLabel({ |
||||
|
id: 'label-layer', |
||||
|
map: this.mapObj, |
||||
|
collisionOptions: { |
||||
|
sameSource: true, |
||||
|
}, //开启图层内部的文本标注碰撞 |
||||
|
styles: { |
||||
|
label: new TMap.LabelStyle({ |
||||
|
color: '#FFF', // 颜色属性 |
||||
|
size: 13, // 文字大小属性 |
||||
|
offset: { |
||||
|
x: 0, |
||||
|
y: 15 |
||||
|
}, // 文字偏移属性单位为像素 |
||||
|
angle: 0, // 文字旋转属性 |
||||
|
alignment: 'center', // 文字水平对齐属性 |
||||
|
verticalAlignment: 'middle', // 文字垂直对齐属性 |
||||
|
backgroundColor: 'rgba(0, 0, 0, .5)', |
||||
|
borderRadius: 7, |
||||
|
padding: '2px 8px', |
||||
|
}), |
||||
|
}, |
||||
|
geometries: labels, |
||||
|
}) |
||||
|
|
||||
|
// 标记文本点击事件 |
||||
|
// this.multiLabel.on("click", this.markerClick) |
||||
|
}, |
||||
|
// 移除点位 |
||||
|
clearMarkers() { |
||||
|
if (this.multiMarker) { |
||||
|
this.multiMarker.setMap(null); |
||||
|
this.multiMarker = null; |
||||
|
} |
||||
|
|
||||
|
if(this.multiLabel) { |
||||
|
this.multiLabel.setMap(null); |
||||
|
this.multiLabel = null; |
||||
|
} |
||||
|
}, |
||||
|
// 改变地图中心 |
||||
|
changeMapCenter() { |
||||
|
this.mapObj.panTo(new TMap.LatLng(33.37307, 120.18467)); |
||||
|
}, |
||||
|
// 标记点点击事件 |
||||
|
markerClick(evt) { |
||||
|
console.log(evt, evt.geometry.text) |
||||
|
if (this.lineAddStatus) { |
||||
|
//添加行程时 |
||||
|
this.$dialog.confirm({ |
||||
|
title: '', |
||||
|
message: '是否将' + evt.geometry.text + '加入行程?' |
||||
|
}).then(() => { |
||||
|
this.lineId = 1 |
||||
|
this.$refs.lineRouteRef.addLineList() |
||||
|
}).catch(() => { |
||||
|
|
||||
|
}) |
||||
|
} else { |
||||
|
this.detailShow = true |
||||
|
} |
||||
|
}, |
||||
|
// 路线规划 |
||||
|
gotoLine() { |
||||
|
// this.MultiPolyline = new TMap.MultiPolyline({ |
||||
|
// id: 'polyline-layer', |
||||
|
// map: this.mapObj, |
||||
|
// styles: { |
||||
|
// "style_blue": new TMap.PolylineStyle({ |
||||
|
// "width": 4, |
||||
|
// 'color': '#3777FF', //线填充色 |
||||
|
// 'borderWidth': 2, //边线宽度 |
||||
|
// 'borderColor': '#FFF', //边线颜色 |
||||
|
// 'lineCap': 'butt' //线端头方式 |
||||
|
// }) |
||||
|
// }, |
||||
|
// // 折线数据定义 |
||||
|
// geometries: [{ |
||||
|
// "id": 'style_blue', |
||||
|
// "styleId": 'style_blue', |
||||
|
// "paths": [new TMap.LatLng(33.347305, 120.136504), new TMap.LatLng(33.323448, |
||||
|
// 120.157053), new TMap.LatLng(33.338249, 120.1832)] |
||||
|
// }] |
||||
|
// }) |
||||
|
|
||||
|
this.$router.push({ |
||||
|
path: '/lineList', |
||||
|
query: { |
||||
|
code: this.areaList[this.areaIndex].code |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
// 关闭弹框后暂停音频 |
||||
|
audioPause() { |
||||
|
this.$refs.detailRef.audioPlay(false) |
||||
|
}, |
||||
|
// 添加线路 |
||||
|
addLine() { |
||||
|
this.lineName = '' |
||||
|
this.lineDate = '' |
||||
|
this.addLineShow = true |
||||
|
}, |
||||
|
// 确认日期 |
||||
|
lineDateConfirm() { |
||||
|
this.lineDate = moment(this.currentDate).format('YYYY-MM-DD') |
||||
|
this.lineDateShow = false |
||||
|
}, |
||||
|
// 输入线路名称和时间,下一步 |
||||
|
lineClick() { |
||||
|
if (this.lineName.trim().length == 0 || this.lineDate.trim().length == 0) { |
||||
|
this.$toast('请输入行程信息') |
||||
|
} else { |
||||
|
this.addLineShow = false |
||||
|
this.lineRouteShow = true |
||||
|
} |
||||
|
}, |
||||
|
// 点击添加行程、关闭添加行程弹框,改变景点标识图标 |
||||
|
addlineRoute(status) { |
||||
|
this.lineRouteShow = false |
||||
|
|
||||
|
if (status) { |
||||
|
// 更换marker样式方法 |
||||
|
this.multiMarker.setStyles({ |
||||
|
"marker": new TMap.MarkerStyle({ |
||||
|
"width": 24, |
||||
|
"height": 30, |
||||
|
"src": 'https://static.ticket.sz-trip.com/yandu/images/map/add.png' |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
// 添加行程时为true |
||||
|
this.lineAddStatus = true |
||||
|
} else { |
||||
|
this.typeIndex = -1 |
||||
|
this.setMarkers(0) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
div { |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.mapContainer { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.type-box { |
||||
|
position: fixed; |
||||
|
z-index: 2000; |
||||
|
width: 723px; |
||||
|
height: 53px; |
||||
|
top: 22px; |
||||
|
left: 27px; |
||||
|
display: flex; |
||||
|
overflow-x: auto; |
||||
|
|
||||
|
.type-item { |
||||
|
padding: 0 26px; |
||||
|
line-height: 53px; |
||||
|
background: #FFFFFF; |
||||
|
border-radius: 13px; |
||||
|
font-weight: 500; |
||||
|
font-size: 27px; |
||||
|
color: #000000; |
||||
|
margin-right: 27px; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.type-active { |
||||
|
background: linear-gradient(130deg, #9EE4FE, #7FD491); |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.type-box::-webkit-scrollbar { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.area-box { |
||||
|
position: fixed; |
||||
|
z-index: 2000; |
||||
|
top: 153px; |
||||
|
right: 17px; |
||||
|
|
||||
|
&>div { |
||||
|
width: 87px; |
||||
|
height: auto; |
||||
|
background: #FFFFFF; |
||||
|
border-radius: 43px; |
||||
|
border: 2px solid #FFFFFF; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
&>div:last-child { |
||||
|
margin-top: 24px; |
||||
|
|
||||
|
.area-items { |
||||
|
height: 133px !important; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.area-item { |
||||
|
height: 93px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
text-align: center; |
||||
|
border-top: 1px solid #D8D8D8; |
||||
|
font-weight: 500; |
||||
|
font-size: 22px; |
||||
|
color: #666666; |
||||
|
} |
||||
|
|
||||
|
.area-items { |
||||
|
flex-direction: column; |
||||
|
justify-content: space-around; |
||||
|
height: 100px; |
||||
|
|
||||
|
img { |
||||
|
width: 38px; |
||||
|
height: 38px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.area-active { |
||||
|
background: linear-gradient(130deg, #9EE4FE, #7FD491); |
||||
|
color: #000000; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 线路弹框 |
||||
|
.addLine-box { |
||||
|
width: 673px; |
||||
|
height: 413px; |
||||
|
background: #FFFFFF; |
||||
|
border-radius: 27px; |
||||
|
padding: 32px 33px 0 37px; |
||||
|
font-weight: bold; |
||||
|
font-size: 40px; |
||||
|
color: #000000; |
||||
|
|
||||
|
.addLine-item { |
||||
|
font-weight: 400; |
||||
|
font-size: 29px; |
||||
|
margin-top: 40px; |
||||
|
|
||||
|
input { |
||||
|
outline: none; |
||||
|
border: none; |
||||
|
height: 27px; |
||||
|
width: 380px; |
||||
|
margin-left: 30px; |
||||
|
} |
||||
|
|
||||
|
input::placeholder { |
||||
|
color: #BEBEBE; |
||||
|
} |
||||
|
|
||||
|
img { |
||||
|
width: 20px; |
||||
|
height: 20px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.addLine-btn { |
||||
|
margin-top: 50px; |
||||
|
|
||||
|
div { |
||||
|
width: 233px; |
||||
|
line-height: 67px; |
||||
|
background: #EAEAEA; |
||||
|
border-radius: 13px; |
||||
|
text-align: center; |
||||
|
font-weight: 500; |
||||
|
font-size: 29px; |
||||
|
color: #000000; |
||||
|
} |
||||
|
|
||||
|
div:last-child { |
||||
|
background: #71B580; |
||||
|
color: #FFFFFF; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,100 @@ |
|||||
|
<template> |
||||
|
<div class="bg"> |
||||
|
<div class="item" v-for="(item,index) in list" :key="index"> |
||||
|
<img :src="util.showImg(item.image)" alt="" /> |
||||
|
|
||||
|
<div class="content"> |
||||
|
<div class="title">{{item.name}}</div> |
||||
|
<div class="subtitle">{{item.points.length}}个景点</div> |
||||
|
<div class="tags" v-if="item.goods_new_tag"> |
||||
|
<div class="tag" v-for="(tagItem,tagIndex) in item.goods_new_tag.split(',').slice(0,2)">{{tagItem}}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
list: [] |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.getList() |
||||
|
}, |
||||
|
methods: { |
||||
|
// 根据code获取推荐线路 |
||||
|
getList() { |
||||
|
this.post({ |
||||
|
code: this.$route.query.code |
||||
|
},'/api/emap/getLineByCode').then(res => { |
||||
|
this.list = res.data |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.bg { |
||||
|
width: 100%; |
||||
|
min-height: 100vh; |
||||
|
background: #F7F7F7; |
||||
|
padding-top: 31px; |
||||
|
} |
||||
|
|
||||
|
.item { |
||||
|
width: 697px; |
||||
|
height: 240px; |
||||
|
background: #FFFFFF; |
||||
|
box-shadow: 0px 1px 16px 0px rgba(153,153,153,0.35); |
||||
|
border-radius: 20px; |
||||
|
margin: 0 auto 33px; |
||||
|
padding: 13px; |
||||
|
display: flex; |
||||
|
|
||||
|
img { |
||||
|
object-fit: cover; |
||||
|
width: 213px; |
||||
|
height: 213px; |
||||
|
border-radius: 13px; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
margin-left: 25px; |
||||
|
padding: 15px 0; |
||||
|
width: 410px; |
||||
|
|
||||
|
.title { |
||||
|
font-weight: bold; |
||||
|
font-size: 33px; |
||||
|
color: #111111; |
||||
|
} |
||||
|
|
||||
|
.subtitle { |
||||
|
margin-top: 8px; |
||||
|
font-weight: 500; |
||||
|
font-size: 27px; |
||||
|
color: #666666; |
||||
|
} |
||||
|
|
||||
|
.tags { |
||||
|
display: flex; |
||||
|
margin-top: 15px; |
||||
|
|
||||
|
.tag { |
||||
|
font-weight: 500; |
||||
|
font-size: 23px; |
||||
|
color: #71B580; |
||||
|
line-height: 40px; |
||||
|
border-radius: 5px; |
||||
|
border: 1px solid #69AF78; |
||||
|
padding: 0 12px; |
||||
|
margin-right: 13px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,245 @@ |
|||||
|
|
||||
|
<template> |
||||
|
<div class="bg"> |
||||
|
<div class="top"> |
||||
|
线路标题 |
||||
|
<span>{{lineDate}}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="center"> |
||||
|
<div class="center-items flex-between" v-for="(item,index) in list" :key="index"> |
||||
|
<div class="center-line"></div> |
||||
|
<div class="center-num">{{index + 1}}</div> |
||||
|
<div class="center-item"> |
||||
|
<img :src="util.showImg(item.image)" class="center-img"> |
||||
|
<div class="center-content"> |
||||
|
<div class="title text-overflow">{{item.title}}{{index}}</div> |
||||
|
<div class="subtitle text-overflow">营业时间:{{item.open_time}}-{{item.close_time}}</div> |
||||
|
<div class="subtitle text-overflow">地址:{{item.address}}</div> |
||||
|
<div class="location" @click="util.openMap(item)"> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/lineLocation.png" alt=""> |
||||
|
导航 |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/delLine.png" alt="" @click="delLine(index)"> |
||||
|
</div> |
||||
|
|
||||
|
<div class="center-btns flex-between" @click="addLine"> |
||||
|
<div class="center-line" :style="{top: list.length == 0 ? '20px' : ''}" v-if="list.length == 0"></div> |
||||
|
<div class="center-num">{{list.length == 0 ? '1' : ''}}</div> |
||||
|
<div class="center-btn"> |
||||
|
+添加行程 |
||||
|
</div> |
||||
|
<div></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="btns flex-around"> |
||||
|
<div @click="submit(0)">取消</div> |
||||
|
<div @click="submit(1)">保存</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
props: ['id','lineDate'], |
||||
|
data() { |
||||
|
return { |
||||
|
list: [], |
||||
|
itemObj: { |
||||
|
image: '/uploads/20240826/a87488f6225789aa19dbb437671d388d.png', |
||||
|
title: '线路推荐-测试', |
||||
|
open_time: '', |
||||
|
close_time: '', |
||||
|
address: '地址' |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
|
||||
|
}, |
||||
|
methods: { |
||||
|
addLine() { |
||||
|
this.$parent.$parent.addlineRoute(1) |
||||
|
}, |
||||
|
addLineList() { |
||||
|
this.list.push(this.itemObj) |
||||
|
this.$parent.$parent.lineRouteShow = true |
||||
|
}, |
||||
|
// 删除线路 |
||||
|
delLine(index) { |
||||
|
this.list.splice(index,1) |
||||
|
}, |
||||
|
submit(status) { |
||||
|
if(status) { |
||||
|
// 确认 |
||||
|
}else { |
||||
|
// 取消 |
||||
|
this.$parent.$parent.addlineRoute(0) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.bg { |
||||
|
width: 750px; |
||||
|
max-height: 60vh; |
||||
|
overflow-x: hidden; |
||||
|
overflow-y: auto; |
||||
|
padding: 40px 27px 180px 27px; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.top { |
||||
|
font-weight: 500; |
||||
|
font-size: 40px; |
||||
|
color: #000000; |
||||
|
|
||||
|
span { |
||||
|
font-weight: 400; |
||||
|
font-size: 24px; |
||||
|
color: #666666; |
||||
|
margin-left: 20px; |
||||
|
vertical-align: text-bottom; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.center { |
||||
|
height: 650px; |
||||
|
overflow-y: auto; |
||||
|
margin-top: 50px; |
||||
|
|
||||
|
.center-items { |
||||
|
position: relative; |
||||
|
padding-bottom: 27px; |
||||
|
|
||||
|
.center-item { |
||||
|
width: 573px; |
||||
|
height: 201px; |
||||
|
background: #FFFFFF; |
||||
|
box-shadow: 0px 0px 20px 0px rgba(142,142,142,0.3); |
||||
|
border-radius: 13px; |
||||
|
padding: 7px; |
||||
|
display: flex; |
||||
|
|
||||
|
.center-img { |
||||
|
width: 187px; |
||||
|
height: 187px; |
||||
|
border-radius: 7px; |
||||
|
} |
||||
|
|
||||
|
.center-content { |
||||
|
padding: 7px 0; |
||||
|
margin-left: 15px; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: space-between; |
||||
|
width: 344px; |
||||
|
|
||||
|
.title { |
||||
|
font-weight: bold; |
||||
|
font-size: 29px; |
||||
|
color: #333333; |
||||
|
width: 344px; |
||||
|
} |
||||
|
|
||||
|
.subtitle { |
||||
|
font-weight: 500; |
||||
|
font-size: 23px; |
||||
|
color: #666666; |
||||
|
width: 344px; |
||||
|
} |
||||
|
|
||||
|
.location { |
||||
|
font-weight: bold; |
||||
|
font-size: 23px; |
||||
|
color: #71B580; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-left: auto; |
||||
|
|
||||
|
img { |
||||
|
width: 32px; |
||||
|
height: 32px; |
||||
|
margin-right: 5px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
img { |
||||
|
width: 33px; |
||||
|
height: 33px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.center-btns { |
||||
|
position: relative; |
||||
|
|
||||
|
.center-btn { |
||||
|
width: 573px; |
||||
|
line-height: 73px; |
||||
|
background: #71B580; |
||||
|
border-radius: 13px; |
||||
|
text-align: center; |
||||
|
font-weight: 400; |
||||
|
font-size: 29px; |
||||
|
color: #FFFFFF; |
||||
|
} |
||||
|
|
||||
|
div:last-child { |
||||
|
width: 33px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.center-num { |
||||
|
width: 38px; |
||||
|
line-height: 38px; |
||||
|
background: #71B580; |
||||
|
border-radius: 50%; |
||||
|
text-align: center; |
||||
|
font-weight: 500; |
||||
|
font-size: 32px; |
||||
|
color: #FFFFFF; |
||||
|
position: relative; |
||||
|
} |
||||
|
.center-line { |
||||
|
position: absolute; |
||||
|
width: 2px; |
||||
|
height: 100%; |
||||
|
background: #71B580; |
||||
|
top: 85px; |
||||
|
left: 18px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.btns { |
||||
|
width: 750px; |
||||
|
height: 173px; |
||||
|
background: #FFFFFF; |
||||
|
box-shadow: 0px 0px 20px 0px rgba(142,142,142,0.3); |
||||
|
padding: 0 20px; |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
|
||||
|
div { |
||||
|
width: 233px; |
||||
|
line-height: 67px; |
||||
|
background: #EAEAEA; |
||||
|
border-radius: 13px; |
||||
|
text-align: center; |
||||
|
font-weight: 400; |
||||
|
font-size: 27px; |
||||
|
color: #000000; |
||||
|
} |
||||
|
|
||||
|
div:last-child { |
||||
|
background: #71B580; |
||||
|
color: #FFFFFF; |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,176 @@ |
|||||
|
|
||||
|
<template> |
||||
|
<div class="bg"> |
||||
|
<div class="top flex-between"> |
||||
|
标题标题 |
||||
|
<div class="top-btn" v-if="type">购买</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="img-box" v-if="type"> |
||||
|
<img src="https://tongli.sz-trip.com/uploads/20240912/bfc1df32e7bc7cd53781ef6671f88cda.png" alt="" /> |
||||
|
<img src="https://tongli.sz-trip.com/uploads/20240912/bfc1df32e7bc7cd53781ef6671f88cda.png" alt="" /> |
||||
|
<img src="https://tongli.sz-trip.com/uploads/20240912/bfc1df32e7bc7cd53781ef6671f88cda.png" alt="" /> |
||||
|
<img src="https://tongli.sz-trip.com/uploads/20240912/bfc1df32e7bc7cd53781ef6671f88cda.png" alt="" /> |
||||
|
<img src="https://tongli.sz-trip.com/uploads/20240912/bfc1df32e7bc7cd53781ef6671f88cda.png" alt="" /> |
||||
|
<img src="https://tongli.sz-trip.com/uploads/20240912/bfc1df32e7bc7cd53781ef6671f88cda.png" alt="" /> |
||||
|
</div> |
||||
|
|
||||
|
<div class="scenic-detail flex-between" :style="{marginTop: type ? '' : '0'}"> |
||||
|
<div class="scenic-left flex-between"> |
||||
|
<div class="text-overflow" v-if="type">营业时间:09:00-17:00</div> |
||||
|
<div :class="[type ? 'text-overflow' : 'text-overflowRows']">地址:盐城市盐都区学富镇周伙盐城市盐都区学富镇周伙</div> |
||||
|
</div> |
||||
|
<div class="scenic-right flex-between"> |
||||
|
<div v-if="type"> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/pause.png" v-if="isAudioPlay" @click="audioPlay(false)"> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/play.png" v-else @click="audioPlay(true)"> |
||||
|
<div>讲解</div> |
||||
|
</div> |
||||
|
<div v-else></div> |
||||
|
|
||||
|
<div @click="util.openMap()"> |
||||
|
<img src="https://static.ticket.sz-trip.com/yandu/images/map/navigation.png" alt=""> |
||||
|
<div>导航</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="scenic-content" v-if="type"> |
||||
|
简介: |
||||
|
<div> |
||||
|
草房子乐园是童话文学的IP实景还原,是国内较早儿童文学实景体验基地、较早乡野童话体验基地和儿童文学研学基地。致力于打造集旅游住宿、餐饮服务、休闲娱乐、文化传播、研学美育、亲子互动、青少年实践、爱心公益于一体的社会化服务新平台。研学赋能景区瞄准“研学+”新领域,建设标准化研学场景,葳蕤的田园风光,推出亲子研学个性化的消费体验产品和游玩项目 |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 音频讲解 --> |
||||
|
<audio src="" ref="audio" controls v-show="false"></audio> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
props: { |
||||
|
type: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
isAudioPlay: false, |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$refs.audio.src = "https://static.ticket.sz-trip.com/uploads/20220419/47fcfa763aa0d3283a2d47e3cce71428.mp3" |
||||
|
}, |
||||
|
methods: { |
||||
|
audioPlay(status) { |
||||
|
console.log(this.$refs.audio.paused) |
||||
|
if(status) { |
||||
|
this.$refs.audio.play() |
||||
|
this.isAudioPlay = true |
||||
|
}else { |
||||
|
this.$refs.audio.pause() |
||||
|
this.isAudioPlay = false |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.bg { |
||||
|
width: 750px; |
||||
|
max-height: 60vh; |
||||
|
overflow-x: hidden; |
||||
|
overflow-y: auto; |
||||
|
padding: 0 40px 40px; |
||||
|
} |
||||
|
.top { |
||||
|
height: 156px; |
||||
|
font-weight: 500; |
||||
|
font-size: 40px; |
||||
|
color: #000000; |
||||
|
|
||||
|
.top-btn { |
||||
|
width: 133px; |
||||
|
line-height: 59px; |
||||
|
background: #F74A57; |
||||
|
border-radius: 13px; |
||||
|
text-align: center; |
||||
|
font-size: 32px; |
||||
|
color: #FFFFFF; |
||||
|
} |
||||
|
} |
||||
|
.img-box { |
||||
|
overflow-x: auto; |
||||
|
display: flex; |
||||
|
overflow-x: auto; |
||||
|
|
||||
|
img { |
||||
|
width: 180px; |
||||
|
height: 180px; |
||||
|
border-radius: 27px; |
||||
|
margin-right: 27px; |
||||
|
object-fit: cover; |
||||
|
} |
||||
|
} |
||||
|
.img-box::-webkit-scrollbar { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.scenic-detail { |
||||
|
width: 670px; |
||||
|
height: 145px; |
||||
|
background: #E8F6EB; |
||||
|
border-radius: 13px; |
||||
|
margin-top: 36px; |
||||
|
padding: 30px 20px 30px 25px; |
||||
|
font-weight: 500; |
||||
|
font-size: 27px; |
||||
|
color: #000000; |
||||
|
|
||||
|
.scenic-left { |
||||
|
flex-direction: column; |
||||
|
align-items: left; |
||||
|
width: 450px; |
||||
|
height: 100%; |
||||
|
|
||||
|
div { |
||||
|
width: 450px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.scenic-right { |
||||
|
width: 150px; |
||||
|
font-weight: 500; |
||||
|
font-size: 24px; |
||||
|
color: #71B580; |
||||
|
|
||||
|
img { |
||||
|
width: 37px; |
||||
|
height: 37px; |
||||
|
margin-bottom: 5px; |
||||
|
} |
||||
|
|
||||
|
div { |
||||
|
text-align: center; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.scenic-content { |
||||
|
margin-top: 42px; |
||||
|
font-weight: bold; |
||||
|
font-size: 32px; |
||||
|
color: #000000; |
||||
|
|
||||
|
div { |
||||
|
font-weight: 500; |
||||
|
font-size: 27px; |
||||
|
color: #333333; |
||||
|
line-height: 44px; |
||||
|
margin-top: 10px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,79 @@ |
|||||
|
const path = require('path') // 引入path模块
|
||||
|
// const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; |
||||
|
|
||||
|
function resolve(dir) { |
||||
|
return path.join(__dirname, dir) // path.join(__dirname)设置绝对路径
|
||||
|
} |
||||
|
const { |
||||
|
defineConfig |
||||
|
} = require('@vue/cli-service') |
||||
|
module.exports = defineConfig({ |
||||
|
lintOnSave: false, // 关闭eslint校验
|
||||
|
transpileDependencies: true, |
||||
|
publicPath: '/', |
||||
|
// 将构建好的文件输出到哪里
|
||||
|
outputDir: process.env.VUE_APP_OUTPUTDIR, |
||||
|
// 放置生成的静态资源(js、css、img、fonts)的目录
|
||||
|
assetsDir: 'static', |
||||
|
// 指定生成的 index.html 的输出路径
|
||||
|
indexPath: 'index.html', |
||||
|
// 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度
|
||||
|
productionSourceMap: false, |
||||
|
// 是一个函数,允许对内部的 webpack 配置进行更细粒度的修改。
|
||||
|
chainWebpack: (config) => { |
||||
|
// 配置别名
|
||||
|
config.resolve.alias |
||||
|
.set('@', resolve('src')) |
||||
|
.set('assets', resolve('src/assets')) |
||||
|
.set('components', resolve('src/components')) |
||||
|
.set('views', resolve('src/views')) |
||||
|
|
||||
|
config.optimization.minimizer('terser').tap((args) => { |
||||
|
// 去除生产环境console
|
||||
|
args[0].terserOptions.compress.drop_console = true |
||||
|
return args |
||||
|
}) |
||||
|
}, |
||||
|
// 配置 Webpack 相关的配置项
|
||||
|
configureWebpack: config => { |
||||
|
// 配置 Webpack 插件
|
||||
|
// config.plugins.push(new HtmlWebpackPlugin({
|
||||
|
// template: './public/index.html'
|
||||
|
// }))
|
||||
|
if(process.env.NODE_ENV == 'production'){ |
||||
|
config.plugins.push(new BundleAnalyzerPlugin({ |
||||
|
analyzerMode: 'server', |
||||
|
analyzerHost: '127.0.0.1', |
||||
|
analyzerPort: 8888, //注意是否有端口冲突
|
||||
|
reportFilename: 'report.html', |
||||
|
defaultSizes: 'parsed', |
||||
|
openAnalyzer: true, |
||||
|
generateStatsFile: false, |
||||
|
statsFilename: 'stats.json', |
||||
|
statsOptions: null, |
||||
|
logLevel: 'info' |
||||
|
})) |
||||
|
} |
||||
|
}, |
||||
|
// 配置开发服务器
|
||||
|
// 本地项目运行时的环境配置
|
||||
|
devServer: { |
||||
|
host: 'localhost', |
||||
|
port: 8080, // 端口号
|
||||
|
https: false, |
||||
|
open: false, // 配置自动启动浏览器 open: 'Google Chrome'-默认启动谷歌
|
||||
|
hot: true, // 热更新
|
||||
|
|
||||
|
proxy: { |
||||
|
'/api': { |
||||
|
target: 'http://localhost:3000', // 要访问的跨域的域名
|
||||
|
ws: true, // 是否启用websockets
|
||||
|
changeOrigin: true, // 开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样客户端端和服务端进行数据的交互就不会有跨域问题
|
||||
|
pathRewrite: { |
||||
|
'^/api': '' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}) |
Loading…
Reference in new issue