jufubao-third 1.0.21 → 1.0.22-beta10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/package.json +1 -1
  3. package/src/components/JfbThirdPay/WalletMix.js +1 -0
  4. package/src/components/JfbThirdRideCheckPay/Api.js +18 -0
  5. package/src/components/JfbThirdRideCheckPay/Attr.js +17 -0
  6. package/src/components/JfbThirdRideCheckPay/JfbThirdRideCheckPay.vue +217 -0
  7. package/src/components/JfbThirdRideCheckPay/JfbThirdRideCheckPayLess.less +80 -0
  8. package/src/components/JfbThirdRideCheckPay/JfbThirdRideCheckPayMixin.js +30 -0
  9. package/src/components/JfbThirdRideCheckPay/Mock.js +7 -0
  10. package/src/components/JfbThirdRideCheckPay/cusAttr/advanced.js +28 -0
  11. package/src/components/JfbThirdRideCheckPay/cusAttr/content.js +27 -0
  12. package/src/components/JfbThirdRideCheckPay/cusAttr/style.js +7 -0
  13. package/src/components/JfbThirdRideConfirm/Api.js +37 -0
  14. package/src/components/JfbThirdRideConfirm/Attr.js +17 -0
  15. package/src/components/JfbThirdRideConfirm/JfbThirdRideConfirm.vue +527 -0
  16. package/src/components/JfbThirdRideConfirm/JfbThirdRideConfirmLess.less +80 -0
  17. package/src/components/JfbThirdRideConfirm/JfbThirdRideConfirmMixin.js +30 -0
  18. package/src/components/JfbThirdRideConfirm/Mock.js +69 -0
  19. package/src/components/JfbThirdRideConfirm/cusAttr/advanced.js +7 -0
  20. package/src/components/JfbThirdRideConfirm/cusAttr/content.js +27 -0
  21. package/src/components/JfbThirdRideConfirm/cusAttr/style.js +7 -0
  22. package/src/components/JfbThirdRideGenOrder/Api.js +21 -0
  23. package/src/components/JfbThirdRideGenOrder/Attr.js +17 -0
  24. package/src/components/JfbThirdRideGenOrder/JfbThirdRideGenOrder.vue +234 -0
  25. package/src/components/JfbThirdRideGenOrder/JfbThirdRideGenOrderLess.less +80 -0
  26. package/src/components/JfbThirdRideGenOrder/JfbThirdRideGenOrderMixin.js +30 -0
  27. package/src/components/JfbThirdRideGenOrder/Mock.js +11 -0
  28. package/src/components/JfbThirdRideGenOrder/cusAttr/advanced.js +37 -0
  29. package/src/components/JfbThirdRideGenOrder/cusAttr/content.js +7 -0
  30. package/src/components/JfbThirdRideGenOrder/cusAttr/style.js +7 -0
  31. package/src/components/JfbThirdRideHome/Api.js +44 -0
  32. package/src/components/JfbThirdRideHome/Attr.js +17 -0
  33. package/src/components/JfbThirdRideHome/JfbThirdRideHome.vue +831 -0
  34. package/src/components/JfbThirdRideHome/JfbThirdRideHomeLess.less +80 -0
  35. package/src/components/JfbThirdRideHome/JfbThirdRideHomeMixin.js +30 -0
  36. package/src/components/JfbThirdRideHome/Mock.js +13 -0
  37. package/src/components/JfbThirdRideHome/cusAttr/advanced.js +52 -0
  38. package/src/components/JfbThirdRideHome/cusAttr/content.js +27 -0
  39. package/src/components/JfbThirdRideHome/cusAttr/style.js +7 -0
  40. package/src/components/JfbThirdRideLand/Api.js +58 -0
  41. package/src/components/JfbThirdRideLand/Attr.js +17 -0
  42. package/src/components/JfbThirdRideLand/JfbThirdRideLand.vue +256 -0
  43. package/src/components/JfbThirdRideLand/JfbThirdRideLandLess.less +80 -0
  44. package/src/components/JfbThirdRideLand/JfbThirdRideLandMixin.js +30 -0
  45. package/src/components/JfbThirdRideLand/Mock.js +13 -0
  46. package/src/components/JfbThirdRideLand/cusAttr/advanced.js +22 -0
  47. package/src/components/JfbThirdRideLand/cusAttr/content.js +60 -0
  48. package/src/components/JfbThirdRideLand/cusAttr/style.js +109 -0
  49. package/src/components/JfbThirdRideRecord/Api.js +33 -0
  50. package/src/components/JfbThirdRideRecord/Attr.js +17 -0
  51. package/src/components/JfbThirdRideRecord/JfbThirdRideRecord.vue +533 -0
  52. package/src/components/JfbThirdRideRecord/JfbThirdRideRecordLess.less +80 -0
  53. package/src/components/JfbThirdRideRecord/JfbThirdRideRecordMixin.js +30 -0
  54. package/src/components/JfbThirdRideRecord/Mock.js +44 -0
  55. package/src/components/JfbThirdRideRecord/cusAttr/advanced.js +22 -0
  56. package/src/components/JfbThirdRideRecord/cusAttr/content.js +27 -0
  57. package/src/components/JfbThirdRideRecord/cusAttr/style.js +7 -0
  58. package/src/components/JfbThirdRideStartEnd/Api.js +20 -0
  59. package/src/components/JfbThirdRideStartEnd/Attr.js +17 -0
  60. package/src/components/JfbThirdRideStartEnd/JfbThirdRideStartEnd.vue +382 -0
  61. package/src/components/JfbThirdRideStartEnd/JfbThirdRideStartEndLess.less +80 -0
  62. package/src/components/JfbThirdRideStartEnd/JfbThirdRideStartEndMixin.js +30 -0
  63. package/src/components/JfbThirdRideStartEnd/Mock.js +17 -0
  64. package/src/components/JfbThirdRideStartEnd/cusAttr/advanced.js +22 -0
  65. package/src/components/JfbThirdRideStartEnd/cusAttr/content.js +27 -0
  66. package/src/components/JfbThirdRideStartEnd/cusAttr/style.js +7 -0
  67. package/src/mixins/getCoordinatesMixins.js +407 -0
@@ -0,0 +1,831 @@
1
+ <template>
2
+ <view
3
+ class="jfb-third-ride-home"
4
+ @click="handleEditxSelect"
5
+ :class="{ editx : isEditx && active }"
6
+ >
7
+ <!--#ifdef H5-->
8
+ <view
9
+ class="jfb-third-ride-home__edit"
10
+ :class="{ editx : isEditx && active }"
11
+ v-if="isEditx && active"
12
+ >
13
+ <view class="jfb-third-ride-home__edit-icon" @click.stop="delEdit">
14
+ <xd-font-icon icon="iconshanchu-01" color="#fff" size="30"></xd-font-icon>
15
+ </view>
16
+ </view>
17
+ <!-- #endif -->
18
+ <view class="jfb-third-ride-home__body">
19
+ <!-- tab切换:现在用车 / 预约用车 -->
20
+ <view class="jfb-third-ride-home__body-tab">
21
+ <view class="jfb-third-ride-home__body-tab-inner">
22
+ <view
23
+ class="jfb-third-ride-home__tab-item"
24
+ :class="{ 'jfb-third-ride-home__tab-item--active' : tabIndex === 0 }"
25
+ @click="handleTabChange(0)"
26
+ >现在用车</view>
27
+ <view
28
+ class="jfb-third-ride-home__tab-item"
29
+ :class="{ 'jfb-third-ride-home__tab-item--active' : tabIndex === 1 }"
30
+ @click="handleTabChange(1)"
31
+ >预约用车</view>
32
+ </view>
33
+ </view>
34
+
35
+ <!-- 预约区域:出发日期时间 + 起终点地址 + 按钮(白色背景) -->
36
+ <view class="jfb-third-ride-home__body-panel">
37
+ <view
38
+ v-if="tabIndex === 1"
39
+ class="jfb-third-ride-home__body-date"
40
+ @click="handleOpenTimePicker"
41
+ >
42
+ <view class="jfb-third-ride-home__date-label-row">
43
+ <view class="jfb-third-ride-home__date-icon">
44
+ <xd-font-icon icon="iconshijian-01" color="#333" size="28"></xd-font-icon>
45
+ </view>
46
+ <view class="jfb-third-ride-home__date-label">出发日期时间</view>
47
+ </view>
48
+ <view class="jfb-third-ride-home__date-value">{{ bookDateText }}</view>
49
+ </view>
50
+
51
+ <!-- 起终点输入框,点击跳转选择位置 -->
52
+ <view class="jfb-third-ride-home__body-address">
53
+ <view class="jfb-third-ride-home__dot-column">
54
+ <view class="jfb-third-ride-home__dot jfb-third-ride-home__dot--start"></view>
55
+ <view class="jfb-third-ride-home__dot-line"></view>
56
+ <view class="jfb-third-ride-home__dot jfb-third-ride-home__dot--end"></view>
57
+ </view>
58
+ <view class="jfb-third-ride-home__address-content">
59
+ <view class="jfb-third-ride-home__address-item" @click="handleChooseAddress('start')">
60
+ <input
61
+ class="jfb-third-ride-home__address-input"
62
+ v-model="startAddress"
63
+ placeholder="当前位置"
64
+ placeholder-class="jfb-third-ride-home__address-placeholder"
65
+ disabled
66
+ />
67
+ </view>
68
+ <view class="jfb-third-ride-home__address-item" @click="handleChooseAddress('end')">
69
+ <input
70
+ class="jfb-third-ride-home__address-input"
71
+ v-model="endAddress"
72
+ placeholder="你要去哪里?"
73
+ placeholder-class="jfb-third-ride-home__address-placeholder"
74
+ disabled
75
+ />
76
+ </view>
77
+ </view>
78
+ </view>
79
+
80
+ <!-- 操作按钮 -->
81
+ <view class="jfb-third-ride-home__body-btn">
82
+ <xd-button
83
+ width="360rpx"
84
+ type="primary"
85
+ radius="50rpx"
86
+ @click="handleSubmit"
87
+ >{{ btnText }}</xd-button>
88
+ </view>
89
+ </view>
90
+
91
+ <!-- 全部出行记录 -->
92
+ <view class="jfb-third-ride-home__body-record" @click="handleGoRecord">
93
+ <view class="jfb-third-ride-home__record-left">
94
+ <view class="jfb-third-ride-home__record-icon">
95
+ <xd-font-icon icon="iconyuyuejilu" color="#e53a2f" size="32"></xd-font-icon>
96
+ </view>
97
+ <view class="jfb-third-ride-home__record-text">全部出行记录</view>
98
+ </view>
99
+ <view class="jfb-third-ride-home__record-arrow">
100
+ <xd-font-icon icon="iconxiangyou_xian" color="#c8c9cc" size="40"></xd-font-icon>
101
+ </view>
102
+ </view>
103
+ </view>
104
+
105
+ <!-- 预约时间选择器(uniapp picker-view) -->
106
+ <view
107
+ v-if="showTimePicker"
108
+ class="jfb-third-ride-home__picker-mask"
109
+ @click="handleCloseTimePicker"
110
+ >
111
+ <view class="jfb-third-ride-home__picker" @click.stop>
112
+ <view class="jfb-third-ride-home__picker-header">
113
+ <view class="jfb-third-ride-home__picker-btn" @click="handleCloseTimePicker">取消</view>
114
+ <view class="jfb-third-ride-home__picker-title">选择用车时间</view>
115
+ <view class="jfb-third-ride-home__picker-btn jfb-third-ride-home__picker-btn--confirm" @click="handleConfirmTimePicker">确定</view>
116
+ </view>
117
+ <picker-view
118
+ class="jfb-third-ride-home__picker-view"
119
+ :value="pickerValue"
120
+ @change="handlePickerChange"
121
+ >
122
+ <picker-view-column class="jfb-third-ride-home__picker-column">
123
+ <view
124
+ class="jfb-third-ride-home__picker-item"
125
+ v-for="(item, index) in dateList"
126
+ :key="index"
127
+ >{{ item }}</view>
128
+ </picker-view-column>
129
+ <picker-view-column class="jfb-third-ride-home__picker-column">
130
+ <view
131
+ class="jfb-third-ride-home__picker-item"
132
+ v-for="(item, index) in hourList"
133
+ :key="index"
134
+ >{{ item }}</view>
135
+ </picker-view-column>
136
+ <picker-view-column class="jfb-third-ride-home__picker-column">
137
+ <view
138
+ class="jfb-third-ride-home__picker-item"
139
+ v-for="(item, index) in minuteList"
140
+ :key="index"
141
+ >{{ item }}</view>
142
+ </picker-view-column>
143
+ </picker-view>
144
+ </view>
145
+ </view>
146
+ </view>
147
+ </template>
148
+
149
+ <script>
150
+ import XdFontIcon from "@/components/XdFontIcon/XdFontIcon";
151
+ import { jfbRootExec } from "@/utils/xd.event";
152
+ import JfbThirdRideHomeMixin from "./JfbThirdRideHomeMixin";
153
+ import { gCPVal } from "@/utils/xd.base";
154
+ import componentsMixins from "@/mixins/componentsMixins";
155
+ import extsMixins from "@/mixins/extsMixins";
156
+ import XdButton from "@/components/XdButton/XdButton"
157
+ import storage from "@/common/storage"
158
+ //跨页选择地址时用于暂存结果的storage key(选择完成后立即删除)
159
+ const RIDE_ADDRESS_KEY = 'jfb_third_ride_address';
160
+ export default {
161
+ name: "JfbThirdRideHome",
162
+ components: {
163
+ XdFontIcon,
164
+ XdButton
165
+ },
166
+ mixins: [
167
+ componentsMixins, extsMixins, JfbThirdRideHomeMixin
168
+ ],
169
+ data() {
170
+ return {
171
+ //tab: 0=现在用车 1=预约用车
172
+ tabIndex: 0,
173
+ //是否展示预约时间选择器
174
+ showTimePicker: false,
175
+ //picker-view 选中索引[日期, 小时, 分钟]
176
+ pickerValue: [0, 0, 0],
177
+ //日期列(月日,如 08-25 星期二)
178
+ dateList: [],
179
+ //每个日期可预约的起止分钟(当天0点起算),用于首尾日期限制
180
+ dayData: [],
181
+ //小时列(00~23)
182
+ hourList: [],
183
+ //分钟列(00~55 每5分钟)
184
+ minuteList: [],
185
+ //预约时间展示文案
186
+ bookDateText: '',
187
+ //确认后的预约时间(13位毫秒时间戳),用于提交接口
188
+ bookTimeStamp: 0,
189
+ //起点地址
190
+ startAddress: '',
191
+ //终点地址
192
+ endAddress: '',
193
+ //起点完整地址对象(含name/address/lng/lat),用于下单估算接口获取坐标与名称
194
+ startPoint: {},
195
+ //终点完整地址对象(含name/address/lng/lat),用于下单估算接口获取坐标与名称
196
+ endPoint: {},
197
+
198
+ //跳转路径配置
199
+ selectLocationPath: '',
200
+ rideRecordPath: '',
201
+ rideConfirmPath: '',
202
+ //业务线
203
+ xnamespace: '',
204
+ }
205
+ },
206
+ computed: {
207
+ //按钮文案:现在用车->立即叫车 预约用车->预约用车
208
+ btnText() {
209
+ return this.tabIndex === 0 ? '立即叫车' : '预约用车';
210
+ },
211
+ },
212
+ watch: {
213
+ container(value, oldValue) {
214
+ if (JSON.stringify(value) === JSON.stringify(oldValue)) return;
215
+ if (this.$configProject['isPreview']) this.init(value)
216
+ },
217
+ },
218
+ created() {
219
+ this.init(this.container);
220
+ },
221
+ methods: {
222
+ onJfbLoad(options) {
223
+
224
+ // jfbRootExec('baiduUserLogin', {
225
+
226
+ // vm: this,// data: {
227
+
228
+ // account: 'gaoshiyong',// password: '123456789',// type: 3,// ...options
229
+
230
+ // }
231
+
232
+ // }).then().catch()
233
+ },
234
+ /**
235
+ * @description 监听事件变化
236
+ * @param container {object} 业务组件对象自己
237
+ */
238
+ init(container) {
239
+ //跳转路径配置(参考JfbMallCart使用gCPVal从容器配置读取)
240
+ this.selectLocationPath = gCPVal(container, 'content.selectLocationPath', {value: ""}).value;
241
+ console.log('selectLocationPath', this.selectLocationPath)
242
+ this.rideRecordPath = gCPVal(container, 'content.rideRecordPath', {value: ""}).value;
243
+ this.rideConfirmPath = gCPVal(container, 'content.rideConfirmPath', {value: ""}).value;
244
+ //业务线
245
+ this.xnamespace = gCPVal(container, 'xnamespace', '');
246
+ },
247
+ /**
248
+ * @description 切换tab
249
+ * @param index {number} 0:现在用车 1:预约用车
250
+ */
251
+ handleTabChange(index) {
252
+ this.tabIndex = index;
253
+ },
254
+ /**
255
+ * @description 补齐两位数
256
+ * @param n {number}
257
+ * @returns {string}
258
+ */
259
+ formatNum(n) {
260
+ return n < 10 ? '0' + n : '' + n;
261
+ },
262
+ /**
263
+ * @description 数组索引越界保护
264
+ * @param index {number}
265
+ * @param len {number}
266
+ * @returns {number}
267
+ */
268
+ clampIndex(index, len) {
269
+ if (index >= len) return len - 1;
270
+ if (index < 0) return 0;
271
+ return index;
272
+ },
273
+ /**
274
+ * @description 打开预约时间选择器(先请求接口获取最早/最晚可预约时间,再据此生成时间数据)
275
+ */
276
+ handleOpenTimePicker() {
277
+ jfbRootExec("getRideReservationTime", {
278
+ vm: this,
279
+ data: {
280
+ channel_code: 'amapcar',
281
+ }
282
+ }).then(res => {
283
+ this.buildTimePickerData(res && res.start_time, res && res.end_time);
284
+ }).catch(() => {
285
+ //接口异常时无数据,不打开选择器
286
+ });
287
+ },
288
+ /**
289
+ * @description 根据起止时间戳生成三列时间选择数据(月日/时/分)并打开选择器
290
+ * 规则:中间天00:00~23:55、第一天从start_time开始、最后一天到end_time之前
291
+ * @param startTime {number} 接口返回的最早可预约时间戳(秒/毫秒)
292
+ * @param endTime {number} 接口返回的最晚可预约时间戳(秒/毫秒)
293
+ */
294
+ buildTimePickerData(startTime, endTime) {
295
+ //秒级时间戳转毫秒;为空则用当前时间
296
+ if (startTime) startTime = startTime < 1e10 ? startTime * 1000 : startTime;
297
+ else startTime = Date.now();
298
+ if (endTime) endTime = endTime < 1e10 ? endTime * 1000 : endTime;
299
+ else {
300
+ //无截止时间时,默认当天23:55
301
+ const tmp = new Date(startTime);
302
+ endTime = new Date(tmp.getFullYear(), tmp.getMonth(), tmp.getDate(), 23, 55, 59).getTime();
303
+ }
304
+ const sD = new Date(startTime);
305
+ const eD = new Date(endTime);
306
+ if (eD < sD) eD = sD;
307
+ //可预约天数(含首尾)
308
+ const startDayNoon = new Date(sD.getFullYear(), sD.getMonth(), sD.getDate()).getTime();
309
+ const endDayNoon = new Date(eD.getFullYear(), eD.getMonth(), eD.getDate()).getTime();
310
+ const dayCount = Math.round((endDayNoon - startDayNoon) / 86400000) + 1;
311
+ const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
312
+ this.dateList = [];
313
+ this.dayData = [];
314
+ for (let i = 0; i < dayCount; i++) {
315
+ const d = new Date(sD.getFullYear(), sD.getMonth(), sD.getDate() + i);
316
+ //第一天显示"今天",其余显示"周X"
317
+ const suffix = i === 0 ? '今天' : `周${weekdays[d.getDay()]}`;
318
+ this.dateList.push(`${this.formatNum(d.getMonth() + 1)}-${this.formatNum(d.getDate())} ${suffix}`);
319
+ //当天默认时刻范围 00:00 ~ 23:55
320
+ let minTotal = 0;
321
+ let maxTotal = 23 * 60 + 55;
322
+ if (i === 0) {
323
+ //第一天:从 start_time 起,向上取整到5分钟
324
+ minTotal = Math.ceil((sD.getHours() * 60 + sD.getMinutes()) / 5) * 5;
325
+ }
326
+ if (i === dayCount - 1) {
327
+ //最后一天:到 end_time 之前,向下取整到5分钟
328
+ maxTotal = Math.floor((eD.getHours() * 60 + eD.getMinutes() - 1) / 5) * 5;
329
+ }
330
+ if (minTotal > 23 * 60 + 55) minTotal = 23 * 60 + 55;
331
+ if (maxTotal < minTotal) maxTotal = minTotal;
332
+ //记录当天0点时间戳,用于确认后转13位毫秒时间戳
333
+ const dayBase = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
334
+ this.dayData.push({ minTotal, maxTotal, dayBase });
335
+ }
336
+ //默认选中第一天最早可预约时刻
337
+ this.pickerValue = [0, 0, 0];
338
+ this.refreshDay(0);
339
+ this.refreshMinute(0, 0);
340
+ this.bookDateText = this.buildTimeText(0, 0, 0);
341
+ this.showTimePicker = true;
342
+ },
343
+ /**
344
+ * @description 根据日期索引刷新小时列
345
+ * @param dateIndex {number}
346
+ */
347
+ refreshDay(dateIndex) {
348
+ const day = this.dayData[dateIndex];
349
+ if (!day) { this.hourList = []; return; }
350
+ const startHour = Math.floor(day.minTotal / 60);
351
+ const endHour = Math.floor(day.maxTotal / 60);
352
+ const list = [];
353
+ for (let h = startHour; h <= endHour; h++) {
354
+ const hStart = h * 60;
355
+ const hEnd = h * 60 + 55;
356
+ if (hEnd >= day.minTotal && hStart <= day.maxTotal) list.push(`${this.formatNum(h)}点`);
357
+ }
358
+ this.hourList = list;
359
+ },
360
+ /**
361
+ * @description 根据日期索引与小时索引刷新分钟列(每5分钟)
362
+ * @param dateIndex {number}
363
+ * @param hourIndex {number}
364
+ */
365
+ refreshMinute(dateIndex, hourIndex) {
366
+ const day = this.dayData[dateIndex];
367
+ const hour = parseInt(this.hourList[hourIndex]);
368
+ if (!day || isNaN(hour)) { this.minuteList = []; return; }
369
+ const list = [];
370
+ for (let m = 0; m < 60; m += 5) {
371
+ const total = hour * 60 + m;
372
+ if (total >= day.minTotal && total <= day.maxTotal) list.push(`${this.formatNum(m)}分`);
373
+ }
374
+ this.minuteList = list;
375
+ },
376
+ /**
377
+ * @description 拼接选择时间文案
378
+ * @param dateIndex {number}
379
+ * @param hourIndex {number}
380
+ * @param minuteIndex {number}
381
+ * @returns {string}
382
+ */
383
+ buildTimeText(dateIndex, hourIndex, minuteIndex) {
384
+ const date = this.dateList[dateIndex] || '';
385
+ const hour = (this.hourList[hourIndex] || '00点').replace(/点$/, '');
386
+ const minute = (this.minuteList[minuteIndex] || '00分').replace(/分$/, '');
387
+ return `${date} ${hour}:${minute}`;
388
+ },
389
+ /**
390
+ * @description 根据三列值生成13位毫秒时间戳
391
+ * @param dateIndex {number}
392
+ * @param hourIndex {number}
393
+ * @param minuteIndex {number}
394
+ * @returns {number|0} 13位毫秒时间戳,非法时返回0
395
+ */
396
+ buildTimeStamp(dateIndex, hourIndex, minuteIndex) {
397
+ const day = this.dayData[dateIndex];
398
+ const hour = parseInt(this.hourList[hourIndex]);
399
+ const minute = parseInt(this.minuteList[minuteIndex]);
400
+ if (!day || isNaN(hour) || isNaN(minute)) return 0;
401
+ //当天0点时间戳 + 时、分对应毫秒
402
+ return day.dayBase + hour * 60 * 60 * 1000 + minute * 60 * 1000;
403
+ },
404
+ /**
405
+ * @description 关闭预约时间选择器
406
+ */
407
+ handleCloseTimePicker() {
408
+ this.showTimePicker = false;
409
+ },
410
+ /**
411
+ * @description picker-view 三列联动滚动
412
+ * @param e {object} 事件对象
413
+ */
414
+ handlePickerChange(e) {
415
+ const [d, h, m] = e.detail.value;
416
+ const dateIndex = this.clampIndex(d, this.dateList.length);
417
+ const hourIndex = this.clampIndex(h, this.hourList.length);
418
+ const minuteIndex = this.clampIndex(m, this.minuteList.length);
419
+ if (dateIndex !== this.pickerValue[0]) {
420
+ //日期变化:重置小时、分钟
421
+ this.pickerValue = [dateIndex, 0, 0];
422
+ this.refreshDay(dateIndex);
423
+ this.refreshMinute(dateIndex, 0);
424
+ } else if (hourIndex !== this.pickerValue[1]) {
425
+ //小时变化:重置分钟
426
+ this.pickerValue = [dateIndex, hourIndex, 0];
427
+ this.refreshMinute(dateIndex, hourIndex);
428
+ } else {
429
+ this.pickerValue = [dateIndex, hourIndex, minuteIndex];
430
+ }
431
+ },
432
+ /**
433
+ * @description 确认选择预约时间
434
+ */
435
+ handleConfirmTimePicker() {
436
+ const [dateIndex, hourIndex, minuteIndex] = this.pickerValue;
437
+ this.bookDateText = this.buildTimeText(dateIndex, hourIndex, minuteIndex);
438
+ //生成13位毫秒时间戳供接口使用
439
+ this.bookTimeStamp = this.buildTimeStamp(dateIndex, hourIndex, minuteIndex);
440
+ this.showTimePicker = false;
441
+ },
442
+ /**
443
+ * @description 选择起/终点位置
444
+ * @param type {string} start:起点 end:终点
445
+ */
446
+ handleChooseAddress(type) {
447
+ // if (!this.selectLocationPath) {
448
+ // console.warn('未配置选择位置路径 selectLocationPath');
449
+ // return;
450
+ // }
451
+ this.$xdUniHelper.navigateTo({ url: `${this.selectLocationPath}?type=${type}` });
452
+ },
453
+ /**
454
+ * @description 从选择地址页返回后,读取暂存地址并回显,随后立即删除避免存储过多
455
+ */
456
+ restoreSelectedAddress() {
457
+ const saved = storage.get(RIDE_ADDRESS_KEY);
458
+ if (!saved) return;
459
+ if (saved.start) {
460
+ this.startPoint = saved.start;
461
+ this.startAddress = saved.start.name || saved.start.address || '';
462
+ }
463
+ if (saved.end) {
464
+ this.endPoint = saved.end;
465
+ this.endAddress = saved.end.name || saved.end.address || '';
466
+ }
467
+ //及时删除存储信息,避免本地缓存过多(数据已回显到组件状态,提交时直接取组件状态)
468
+ storage.remove(RIDE_ADDRESS_KEY);
469
+ },
470
+ /**
471
+ * @description 跳转全部出行记录
472
+ */
473
+ handleGoRecord() {
474
+ // if (!this.rideRecordPath) {
475
+ // console.warn('未配置出行记录路径 rideRecordPath');
476
+ // return;
477
+ // }
478
+ this.$xdUniHelper.redirectTo({ url: this.rideRecordPath });
479
+ },
480
+ /**
481
+ * @description 提交叫车/预约
482
+ */
483
+ handleSubmit() {
484
+ // if (!this.rideConfirmPath) {
485
+ // console.warn('未配置下单确认路径 rideConfirmPath');
486
+ // return;
487
+ // }
488
+ //起终点完整地址对象从storage回显到组件状态后读取
489
+ const start = this.startPoint || {};
490
+ const end = this.endPoint || {};
491
+ const data = {
492
+ xnamespace: this.xnamespace,
493
+ channel_code: 'amapcar',
494
+ start_lng: start.lng != null ? String(start.lng) : '',
495
+ start_lat: start.lat != null ? String(start.lat) : '',
496
+ end_lng: end.lng != null ? String(end.lng) : '',
497
+ end_lat: end.lat != null ? String(end.lat) : '',
498
+ start_name: start.name || '',
499
+ end_name: end.name || '',
500
+ start_address: start.address || '',
501
+ end_address: end.address || '',
502
+ service_type: this.tabIndex === 0 ? 1 : 2,
503
+ ride_types: '1,12,3,4',
504
+ };
505
+ //仅预约用车才传departure_time(所选时间的13位毫秒时间戳);现在用车不传
506
+ if (this.tabIndex !== 0) {
507
+ data.departure_time = this.bookTimeStamp;
508
+ }
509
+ jfbRootExec('getRideEstimatePrice', { vm: this, data })
510
+ .then(res => {
511
+ //接口返回 {list:[{name,address,lng,lat,distance}]}
512
+ console.log('getRideEstimatePrice result', res);
513
+ this.$xdUniHelper.navigateTo({
514
+ url: this.rideConfirmPath + `?estimate_id=${res.estimate_id}`
515
+ })
516
+ })
517
+ .catch(err => {
518
+ console.warn('getRideEstimatePrice error', err);
519
+ });
520
+ },
521
+ onJfbScroll(options) {
522
+ console.log('event.onJfbScroll', options)
523
+ },
524
+ onJfbReachBottom(options) {
525
+ console.log('event.onJfbReachBottom', options)
526
+ },
527
+ onJfbShow(options) {
528
+ console.log('event.onJfbShow', options)
529
+ //从选择地址页返回,读取暂存的地址并回显
530
+ this.restoreSelectedAddress();
531
+ },
532
+ onJfbHide(options) {
533
+ console.log('event.onJfbHide', options)
534
+ },
535
+ onJfbBack(options) {
536
+ console.log('event.onJfbBack', options)
537
+ },
538
+ onJfbUpdate(...data) {
539
+ console.log('event.onJfbUpdate', data)
540
+ },
541
+ onJfbCustomEvent(options) {
542
+ console.log('event.onJfbReachBottom', options)
543
+ },
544
+ }
545
+ }
546
+
547
+ </script>
548
+
549
+ <style lang="less" scoped>
550
+ @import "./JfbThirdRideHomeLess.less";
551
+
552
+ //start 页面新增样式
553
+ .jfb-third-ride-home {
554
+ box-sizing: border-box;
555
+
556
+ &__body{
557
+ position: relative;
558
+ overflow: hidden;
559
+ z-index: 2;
560
+ background: #f8f8f8;
561
+ border-radius: 20rpx;
562
+ // padding: 20rpx 24rpx 20rpx;
563
+ box-sizing: border-box;
564
+
565
+ &-tab {
566
+ display: flex;
567
+ align-items: center;
568
+ width: 100%;
569
+ background: #ffffff;
570
+ box-sizing: border-box;
571
+ }
572
+
573
+ &-tab-inner {
574
+ display: flex;
575
+ align-items: center;
576
+ flex: 1;
577
+ background: #f8f8f8;
578
+ border-radius: 16rpx;
579
+ margin: 16rpx 24rpx;
580
+ box-sizing: border-box;
581
+ border: 2rpx solid #EEEEEE;
582
+ }
583
+
584
+ &-panel {
585
+ background: #ffffff;
586
+ margin: 16rpx;
587
+ padding: 32rpx;
588
+ }
589
+
590
+ &-date {
591
+ display: flex;
592
+ flex-direction: column;
593
+ border: 1rpx solid #ebedf0;
594
+ border-radius: 16rpx;
595
+ background: #ffffff;
596
+ padding: 16rpx;
597
+ }
598
+
599
+ &-address {
600
+ display: flex;
601
+ align-items: stretch;
602
+ margin-top: 32rpx;
603
+ }
604
+
605
+ &-btn {
606
+ display: flex;
607
+ justify-content: center;
608
+ margin-top: 32rpx;
609
+ }
610
+
611
+ &-record {
612
+ display: flex;
613
+ align-items: center;
614
+ justify-content: space-between;
615
+ background-color: #ffffff;
616
+ margin: 16rpx 16rpx 0 16rpx;
617
+ padding: 24rpx;
618
+ border-radius: 16rpx;
619
+ }
620
+ }
621
+
622
+ &__tab-item {
623
+ position: relative;
624
+ flex: 1;
625
+ padding: 18rpx 0;
626
+ font-size: unit(30, rpx);
627
+ color: #333333;
628
+ text-align: center;
629
+ border-radius: 12rpx;
630
+
631
+ //两个tab间距为4px
632
+ & + & {
633
+ margin-left: 4px;
634
+ }
635
+
636
+ &--active {
637
+ background: #ffffff;
638
+ color: #e5010e;
639
+ }
640
+ }
641
+
642
+ &__date-icon {
643
+ display: flex;
644
+ align-items: center;
645
+ margin-right: 12rpx;
646
+ }
647
+
648
+ &__date-label-row {
649
+ display: flex;
650
+ align-items: center;
651
+ margin-bottom: 8rpx;
652
+ }
653
+
654
+ &__date-label {
655
+ font-size: unit(24, rpx);
656
+ color: #999999;
657
+ }
658
+
659
+ &__date-value {
660
+ font-size: unit(30, rpx);
661
+ font-weight: bold;
662
+ color: #333333;
663
+ }
664
+
665
+ &__date-arrow {
666
+ display: flex;
667
+ align-items: center;
668
+ }
669
+
670
+ &__address-item {
671
+ display: flex;
672
+ align-items: center;
673
+ height: 92rpx;
674
+ padding: 0 20rpx;
675
+ background: #f7f8fa;
676
+ border-radius: 16rpx;
677
+
678
+ & + & {
679
+ margin-top: 16rpx;
680
+ }
681
+ }
682
+
683
+ &__address-content {
684
+ flex: 1;
685
+ min-width: 0;
686
+ }
687
+
688
+ &__dot-column {
689
+ display: flex;
690
+ flex-direction: column;
691
+ align-items: center;
692
+ margin-right: 16rpx;
693
+ padding: 40rpx 0;
694
+ }
695
+
696
+ &__dot {
697
+ width: 16rpx;
698
+ height: 16rpx;
699
+ border-radius: 50%;
700
+
701
+ &--start {
702
+ background: #00b578;
703
+ }
704
+
705
+ &--end {
706
+ background: #ee0a24;
707
+ }
708
+ }
709
+
710
+ &__dot-line {
711
+ flex: 1;
712
+ width: 2rpx;
713
+ min-height: 20rpx;
714
+ background: #dcdee0;
715
+ margin: 4rpx 0;
716
+ }
717
+
718
+ &__address-input {
719
+ flex: 1;
720
+ height: 100%;
721
+ font-size: unit(30, rpx);
722
+ color: #333333;
723
+ //H5上disabled的input会拦截点击,穿透到父级view的@click
724
+ pointer-events: none;
725
+ }
726
+
727
+ &__address-placeholder {
728
+ color: #999999;
729
+ }
730
+
731
+ &__record-left {
732
+ display: flex;
733
+ align-items: center;
734
+ }
735
+
736
+ &__record-icon {
737
+ display: flex;
738
+ align-items: center;
739
+ justify-content: center;
740
+ width: 56rpx;
741
+ height: 56rpx;
742
+ margin-right: 16rpx;
743
+ background: #fdeaea;
744
+ border-radius: 16rpx;
745
+ }
746
+
747
+ &__record-text {
748
+ font-size: unit(28, rpx);
749
+ color: #333333;
750
+ font-weight: bold;
751
+ }
752
+
753
+ &__record-arrow {
754
+ display: flex;
755
+ align-items: center;
756
+ }
757
+
758
+ //预约时间选择器
759
+ &__picker-mask {
760
+ position: fixed;
761
+ top: 0;
762
+ left: 0;
763
+ right: 0;
764
+ bottom: 0;
765
+ z-index: 9999;
766
+ background: rgba(0, 0, 0, .5);
767
+ }
768
+
769
+ &__picker {
770
+ position: absolute;
771
+ left: 0;
772
+ right: 0;
773
+ bottom: 0;
774
+ background: #ffffff;
775
+ border-radius: 24rpx 24rpx 0 0;
776
+ padding-bottom: constant(safe-area-inset-bottom);
777
+ padding-bottom: env(safe-area-inset-bottom);
778
+ }
779
+
780
+ &__picker-header {
781
+ display: flex;
782
+ align-items: center;
783
+ justify-content: space-between;
784
+ height: 88rpx;
785
+ padding: 0 30rpx;
786
+ }
787
+
788
+ &__picker-title {
789
+ font-size: unit(30, rpx);
790
+ font-weight: bold;
791
+ color: #333333;
792
+ }
793
+
794
+ &__picker-btn {
795
+ font-size: unit(28, rpx);
796
+ color: #999999;
797
+ padding: 10rpx;
798
+
799
+ &--confirm {
800
+ color: #e53a2f;
801
+ }
802
+ }
803
+
804
+ &__picker-view {
805
+ width: 100%;
806
+ height: 400rpx;
807
+ }
808
+
809
+ /deep/ .uni-picker-view-indicator {
810
+ height: 80rpx;
811
+ top: 50%;
812
+ -webkit-transform: translateY(-50%);
813
+ transform: translateY(-50%);
814
+ }
815
+
816
+ &__picker-column {
817
+ height: 400rpx;
818
+ }
819
+
820
+ &__picker-item {
821
+ height: 80rpx;
822
+ display: flex;
823
+ align-items: center;
824
+ justify-content: center;
825
+ font-size: unit(30, rpx);
826
+ color: #333333;
827
+ text-align: center;
828
+ }
829
+ }
830
+ //end
831
+ </style>