createOrder.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <template>
  2. <view>
  3. <map class="map" :latitude="map.latitude" :longitude="map.longitude" :scale="map.scale" :polyline="map.polyline" :markers="map.covers"></map>
  4. <view class="bottom" v-show="status == 1">
  5. <view class="input">
  6. <text class="icon green">&#xe608;</text>
  7. <input type="text" :value="start ? start.title : ''" disabled="true" @tap="selectAddress('start')" placeholder="输入您的起点位置" placeholder-class="input-placeholder" />
  8. </view>
  9. <view class="input">
  10. <text class="icon orange">&#xe608;</text>
  11. <input type="text" :value="end ? end.title : ''" disabled="true" @tap="selectAddress('end')" placeholder="输入您的终点位置" placeholder-class="input-placeholder" />
  12. </view>
  13. <button type="primary" @tap="direction">查看路线</button>
  14. </view>
  15. <view class="bottom1" v-show="status == 2">
  16. <view class="input">
  17. <text class="icon green">&#xe608;</text>
  18. <input type="text" :value="start ? start.title : ''" disabled="true" placeholder="输入您的起点位置" placeholder-class="input-placeholder" />
  19. </view>
  20. <view class="input">
  21. <text class="icon orange">&#xe608;</text>
  22. <input type="text" :value="end ? end.title : ''" disabled="true" placeholder="输入您的终点位置" placeholder-class="input-placeholder" />
  23. </view>
  24. <view class="money">
  25. <text>预计{{ route.duration }}分钟</text>
  26. <text>{{ route.distance | kilometer }}公里</text>
  27. <text>大约费用{{ price }}元</text>
  28. </view>
  29. </view>
  30. <!--地址输入-->
  31. <uni-popup class="popup" ref="popup" type="top">
  32. <view class="destination">
  33. <input type="text" v-model="input" :focus="focus" @input="onInputAddress" placeholder="请输入地址" />
  34. <text @tap="closePopup">取消</text>
  35. </view>
  36. <view class="addressHistory" v-for="(v, i) in suggestion" :key="i" @tap="setAddress(v)">
  37. <text>{{ v.title }}</text>
  38. {{ v.addr }}
  39. </view>
  40. </uni-popup>
  41. <!--地址输入-->
  42. </view>
  43. </template>
  44. <script>
  45. import QQMapWX from '../../libs/qqmap-wx-jssdk/qqmap-wx-jssdk.js';
  46. import uniPopup from '@/components/uni-popup/uni-popup.vue';
  47. import helper from '../../common/helper.js';
  48. import api from '../../common/api.js';
  49. export default {
  50. components: {
  51. uniPopup
  52. },
  53. filters: {
  54. kilometer: value => {
  55. let distance = parseFloat(value/1000);
  56. return distance.toFixed(2);
  57. }
  58. },
  59. data() {
  60. return {
  61. status: 1,
  62. currLocation: {},
  63. currAddress: {},
  64. toAddress: {},
  65. map: {
  66. latitude: '',
  67. longitude: '',
  68. covers: [],
  69. scale: 16,
  70. polyline: []
  71. },
  72. suggestion: [],
  73. selectType: '',
  74. start: {},
  75. end: {},
  76. input: '',
  77. focus: false,
  78. route: {},
  79. price: ''
  80. };
  81. },
  82. onShow() {
  83. this.initSdk();
  84. this.getLocation();
  85. },
  86. methods: {
  87. async getPrice() {
  88. let res = await api.getPrice(this.route.distance,0);
  89. this.price = res.data;
  90. this.status = 2;
  91. },
  92. // 路径规划
  93. direction() {
  94. this.qqmapsdk.direction({
  95. mode: 'driving',
  96. from: this.start.latitude + ',' + this.start.longitude,
  97. to: this.end.latitude + ',' + this.end.longitude,
  98. complete: res => {
  99. console.log(res);
  100. if (!res.result || !res.result.routes || res.result.routes.length == 0) {
  101. helper.toast('未获取到有效路线');
  102. return false;
  103. }
  104. let coors = res.result.routes[0].polyline,
  105. pl = []; //坐标解压(返回的点串坐标,通过前向差分进行压缩)
  106. let kr = 1000000;
  107. // 处理坐标
  108. for (let i = 2; i < coors.length; i++) {
  109. coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
  110. }
  111. for (let i = 0; i < coors.length; i += 2) {
  112. pl.push({ latitude: coors[i], longitude: coors[i + 1] });
  113. }
  114. // 计算缩放级别
  115. let zoom = [50, 100, 200, 500, 1900, 2000, 5000, 10000, 20000, 25000, 50000, 100000, 200000, 500000];
  116. let scale = 18;
  117. let distance = res.result.routes[0].distance;
  118. for (let i = 0; i < zoom.length; i++) {
  119. if (zoom[i] - distance > 0) {
  120. scale = 18 - i + 4;
  121. break;
  122. }
  123. }
  124. this.map = {
  125. latitude: pl[0].latitude,
  126. longitude: pl[0].longitude,
  127. scale: scale,
  128. polyline: [
  129. {
  130. points: pl,
  131. color: '#227AFF',
  132. width: 4
  133. }
  134. ]
  135. };
  136. this.route = res.result.routes[0];
  137. this.getPrice();
  138. }
  139. });
  140. },
  141. selectAddress(selectType) {
  142. this.selectType = selectType;
  143. this.$refs.popup.open();
  144. this.focus = true;
  145. },
  146. setAddress(data) {
  147. if (this.selectType == 'start') {
  148. this.start = data;
  149. } else {
  150. this.end = data;
  151. }
  152. this.closePopup();
  153. },
  154. closePopup() {
  155. this.focus = false;
  156. this.input = '';
  157. this.suggestion = [];
  158. this.$refs.popup.close();
  159. },
  160. onInputAddress(e) {
  161. let address = e.detail.value;
  162. //调用关键词提示接口
  163. this.qqmapsdk.getSuggestion({
  164. //获取输入框值并设置keyword参数
  165. keyword: address,
  166. region: this.currAddress.address_component.city,
  167. success: res => {
  168. //搜索成功后的回调
  169. console.log(res);
  170. let sug = [];
  171. for (let i = 0; i < res.data.length; i++) {
  172. sug.push({
  173. // 获取返回结果,放到sug数组中
  174. title: res.data[i].title,
  175. id: res.data[i].id,
  176. addr: res.data[i].address,
  177. city: res.data[i].city,
  178. district: res.data[i].district,
  179. latitude: res.data[i].location.lat,
  180. longitude: res.data[i].location.lng
  181. });
  182. }
  183. this.suggestion = sug;
  184. },
  185. fail: function(error) {
  186. console.error(error);
  187. },
  188. complete: function(res) {
  189. console.log(res);
  190. }
  191. });
  192. },
  193. initSdk() {
  194. this.qqmapsdk = new QQMapWX({
  195. key: helper.config.qqmapsdk.key
  196. });
  197. },
  198. getLocation() {
  199. uni.getLocation({
  200. type: 'gcj02',
  201. success: res => {
  202. // 当前地址
  203. this.currLocation = res;
  204. // 设置地图信息
  205. this.map.latitude = res.latitude;
  206. this.map.longitude = res.longitude;
  207. // 坐标点
  208. this.map.covers.push({
  209. latitude: res.latitude,
  210. longitude: res.longitude,
  211. iconPath: '../../static/marker.png'
  212. });
  213. // 坐标转地址信息
  214. this.qqmapsdk.reverseGeocoder({
  215. location: {
  216. latitude: res.latitude,
  217. longitude: res.longitude
  218. },
  219. complete: res => {
  220. console.log(res);
  221. if (res.status == 0) {
  222. this.currAddress = res.result;
  223. }
  224. }
  225. });
  226. },
  227. complete: res => {
  228. console.log(res);
  229. }
  230. });
  231. }
  232. }
  233. };
  234. </script>
  235. <style lang="scss" scoped>
  236. .popup {
  237. height: 100%;
  238. .destination {
  239. display: flex;
  240. justify-content: space-between;
  241. align-items: center;
  242. padding: 10upx 0;
  243. border-bottom: 1px solid #eeeeee;
  244. text {
  245. font-size: 28upx;
  246. color: #d2d2d2;
  247. }
  248. }
  249. .addressHistory {
  250. padding: 20upx 0;
  251. border-bottom: 1px solid #eeeeee;
  252. display: flex;
  253. flex-direction: column;
  254. font-size: 24upx;
  255. color: #d2d2d2;
  256. text {
  257. color: #101010;
  258. font-size: 28upx;
  259. }
  260. }
  261. }
  262. .map {
  263. width: 100%;
  264. height: calc(100vh - 400upx);
  265. }
  266. .icon {
  267. font-size: 48upx;
  268. }
  269. .bottom1 {
  270. width: 100%;
  271. padding: 30upx;
  272. .input {
  273. width: 90%;
  274. display: flex;
  275. align-items: center;
  276. text {
  277. width: 10%;
  278. }
  279. input {
  280. width: 90%;
  281. padding: 20upx 0upx;
  282. border-bottom: 1px solid #f0f0f0;
  283. }
  284. }
  285. .money {
  286. width: 90%;
  287. display: flex;
  288. justify-content: space-evenly;
  289. font-size: 26upx;
  290. padding: 30upx;
  291. }
  292. button {
  293. border-radius: 0;
  294. background-color: #32c45e;
  295. font-size: 28upx;
  296. }
  297. }
  298. .bottom {
  299. width: 100%;
  300. padding: 30upx;
  301. .input {
  302. width: 90%;
  303. display: flex;
  304. align-items: center;
  305. text {
  306. width: 10%;
  307. }
  308. input {
  309. width: 90%;
  310. padding: 20upx 0upx;
  311. border-bottom: 1px solid #f0f0f0;
  312. }
  313. }
  314. button {
  315. width: 50%;
  316. margin-top: 50upx;
  317. border-radius: 0;
  318. background-color: #32c45e;
  319. font-size: 28upx;
  320. margin-bottom: 20upx;
  321. border-radius: 50upx;
  322. }
  323. }
  324. </style>