Commit d9b9463fa7a33957fc092dfdbfcc1cbde74797f1
1 parent
fbca9085
提交12-12
Showing
10 changed files
with
345 additions
and
182 deletions
garbage-removal/src/components/liu-delivery-time/liu-delivery-time.vue
| ... | ... | @@ -96,34 +96,33 @@ const init = () => { |
| 96 | 96 | |
| 97 | 97 | } |
| 98 | 98 | const getFutureDays = () => { |
| 99 | - const days = []; | |
| 100 | - for (let i = 0; i < props.day; i++) { | |
| 101 | - const date = new Date(); | |
| 102 | - date.setDate(date.getDate() + i); | |
| 103 | - const year = date.getFullYear(); | |
| 104 | - const month = (date.getMonth() + 1).toString().padStart(2, '0'); | |
| 105 | - const day = date.getDate().toString().padStart(2, '0'); | |
| 106 | - if (i === 0) { | |
| 107 | - let hours = date.getHours(); | |
| 108 | - console.log(hours); | |
| 109 | - // if (hours >= 13) { | |
| 110 | - // continue; | |
| 111 | - // } | |
| 112 | - days.push({ | |
| 113 | - day: `${year}-${month}-${day}`, | |
| 114 | - timeList: getCurrentDayTimeList(0, hours, 1) | |
| 115 | - }); | |
| 116 | - } else { | |
| 117 | - days.push({ | |
| 118 | - day: `${year}-${month}-${day}`, | |
| 119 | - timeList: getTimeList() | |
| 120 | - }); | |
| 121 | - } | |
| 122 | - } | |
| 123 | - return days; | |
| 99 | + const days = []; | |
| 100 | + for (let i = 0; i < props.day; i++) { | |
| 101 | + const date = new Date(); | |
| 102 | + date.setDate(date.getDate() + i); | |
| 103 | + const year = date.getFullYear(); | |
| 104 | + const month = (date.getMonth() + 1).toString().padStart(2, '0'); | |
| 105 | + const day = date.getDate().toString().padStart(2, '0'); | |
| 106 | + if (i === 0) { | |
| 107 | + let hours = date.getHours(); | |
| 108 | + let minutes = date.getMinutes(); | |
| 109 | + console.log(hours, minutes); | |
| 110 | + days.push({ | |
| 111 | + day: `${year}-${month}-${day}`, | |
| 112 | + timeList: getCurrentDayTimeList(0, hours, minutes, 1) | |
| 113 | + }); | |
| 114 | + } else { | |
| 115 | + days.push({ | |
| 116 | + day: `${year}-${month}-${day}`, | |
| 117 | + timeList: getTimeList() | |
| 118 | + }); | |
| 119 | + } | |
| 120 | + } | |
| 121 | + return days; | |
| 124 | 122 | } |
| 125 | 123 | |
| 126 | 124 | |
| 125 | + | |
| 127 | 126 | const getTimeList = () => { |
| 128 | 127 | const timeList = [{ |
| 129 | 128 | time: '00:00-02:00', |
| ... | ... | @@ -196,17 +195,65 @@ const getTimeList = () => { |
| 196 | 195 | * @param {*} hours 当前几点 |
| 197 | 196 | * @param {*} skip 跳过几个 |
| 198 | 197 | */ |
| 199 | -const getCurrentDayTimeList = (startTime, hours, skip) => { | |
| 200 | - const timeList = getTimeList(); | |
| 201 | - // 计算当前小时所属的时间段索引 | |
| 202 | - // 每个时间段是2小时,从00:00-02:00开始 | |
| 203 | - let index = Math.floor(hours / 2) + 1; // 加1是为了跳过已过期的时间段 | |
| 204 | - // 确保不会超出数组范围 | |
| 205 | - if (index >= timeList.length) { | |
| 206 | - return []; // 如果没有可选时间段,返回空数组 | |
| 198 | +const getCurrentDayTimeList = (startTime, hours, minutes, skip) => { | |
| 199 | + const dynamicTimeList = []; | |
| 200 | + | |
| 201 | + // 根据当前时间计算最早可预约的开始时间 | |
| 202 | + let startHour = hours; | |
| 203 | + let startMinute = 0; | |
| 204 | + | |
| 205 | + if (minutes < 30) { | |
| 206 | + // 如果当前分钟小于30,则最早可预约时间是当前小时+30分钟开始 | |
| 207 | + startMinute = 30; | |
| 208 | + } else { | |
| 209 | + // 如果当前分钟大于等于30,则最早可预约时间是下一个小时开始 | |
| 210 | + startHour += 1; | |
| 211 | + startMinute = 0; | |
| 207 | 212 | } |
| 208 | - return timeList.slice(index, timeList.length) | |
| 213 | + | |
| 214 | + // 生成未来的时间段,每个时间段跨度2小时 | |
| 215 | + for (let i = 0; i < 10; i++) { // 生成10个时间段足够使用 | |
| 216 | + let endHour = startHour + 2; | |
| 217 | + const endMinute = startMinute; | |
| 218 | + | |
| 219 | + // 处理时间超过24小时的情况 | |
| 220 | + const formattedEndHour = endHour > 24 ? endHour - 24 : endHour; | |
| 221 | + const formattedEndMinute = endMinute; | |
| 222 | + | |
| 223 | + // 格式化时间字符串 | |
| 224 | + const startStr = `${startHour.toString().padStart(2, '0')}:${startMinute.toString().padStart(2, '0')}`; | |
| 225 | + const endStr = endHour >= 24 ? `24:00` : `${formattedEndHour.toString().padStart(2, '0')}:${formattedEndMinute.toString().padStart(2, '0')}`; | |
| 226 | + const timeStr = `${startStr}-${endStr}`; | |
| 227 | + | |
| 228 | + // 确定timeStr(根据原代码推测可能是时间段的标签) | |
| 229 | + let periodTimeStr = ''; | |
| 230 | + if (startHour >= 7 && startHour < 22) { | |
| 231 | + periodTimeStr = `${startHour.toString().padStart(2, '0')}-${(startHour + 1).toString().padStart(2, '0')}`; | |
| 232 | + } else { | |
| 233 | + periodTimeStr = '22-07'; | |
| 234 | + } | |
| 235 | + | |
| 236 | + // 添加到时间列表 | |
| 237 | + dynamicTimeList.push({ | |
| 238 | + time: timeStr, | |
| 239 | + start: startStr, | |
| 240 | + end: endStr, | |
| 241 | + timeStr: periodTimeStr | |
| 242 | + }); | |
| 243 | + | |
| 244 | + // 更新下一个时间段的开始时间为当前时间段的结束时间(跨度2小时) | |
| 245 | + startHour += 2; | |
| 246 | + // 这里不需要改变分钟,因为我们是按2小时递增的 | |
| 247 | + | |
| 248 | + // 如果开始时间超过24小时,停止生成(当天不再生成新的时间段) | |
| 249 | + if (startHour >= 24) { | |
| 250 | + break; | |
| 251 | + } | |
| 252 | + } | |
| 253 | + | |
| 254 | + return dynamicTimeList; | |
| 209 | 255 | } |
| 256 | + | |
| 210 | 257 | const open = () => { |
| 211 | 258 | isShow.value = true; |
| 212 | 259 | init(); | ... | ... |
garbage-removal/src/pages/home-info/address/addSite.vue
| ... | ... | @@ -165,94 +165,21 @@ const submit = () => { |
| 165 | 165 | * 打开地图选择地址(自动定位到当前位置,修复 startCompass:fail 问题) |
| 166 | 166 | */ |
| 167 | 167 | const chooseAddressDetail = () => { |
| 168 | - console.log('打开地图选择地址(自动定位)'); | |
| 169 | - | |
| 170 | - // 1. 先获取当前位置的经纬度(关键:统一坐标系为 gcj02,关闭 altitude 避免额外权限) | |
| 171 | - uni.getLocation({ | |
| 172 | - type: 'gcj02', // 必须使用 gcj02(腾讯/高德地图标准,避免坐标系不匹配) | |
| 173 | - altitude: false, // 关闭海拔获取,减少权限要求 | |
| 174 | - isHighAccuracy: false, // 关闭高精度定位(降低硬件依赖) | |
| 175 | - success: (locationRes) => { | |
| 176 | - console.log('当前位置经纬度:', locationRes); | |
| 177 | - const { latitude, longitude } = locationRes; | |
| 178 | - | |
| 179 | - // 2. 打开地图选择器(移除可能触发指南针的参数) | |
| 180 | - uni.chooseLocation({ | |
| 181 | - latitude: latitude, | |
| 182 | - longitude: longitude, | |
| 183 | - scale: 16, | |
| 184 | - name: addressInfo.addressDetail || '', | |
| 185 | - address: addressInfo.addressArea || '', | |
| 186 | - success: (res) => { | |
| 187 | - addressInfo.addressDetail = res.name; | |
| 188 | - addressInfo.garLongitude = res.longitude; | |
| 189 | - addressInfo.garLatitude = res.latitude; | |
| 190 | - }, | |
| 191 | - fail: (err) => { | |
| 192 | - console.error('地图选择失败:', err); | |
| 193 | - handleLocationError(err); | |
| 194 | - } | |
| 195 | - }); | |
| 168 | + console.log('打开地图选择地址'); | |
| 169 | + | |
| 170 | + // 直接打开地图选择器,不进行定位 | |
| 171 | + uni.chooseLocation({ | |
| 172 | + success: (res) => { | |
| 173 | + addressInfo.addressDetail = res.name; | |
| 174 | + addressInfo.garLongitude = res.longitude; | |
| 175 | + addressInfo.garLatitude = res.latitude; | |
| 196 | 176 | }, |
| 197 | 177 | fail: (err) => { |
| 198 | - console.error('获取当前位置失败:', err); | |
| 199 | - handleLocationError(err); | |
| 178 | + console.error('地图选择失败:', err); | |
| 200 | 179 | } |
| 201 | 180 | }); |
| 202 | 181 | }; |
| 203 | 182 | |
| 204 | -/** | |
| 205 | - * 统一处理定位/地图错误 | |
| 206 | - */ | |
| 207 | -const handleLocationError = (err) => { | |
| 208 | - const errMsg = err.errMsg || ''; | |
| 209 | - | |
| 210 | - // 1. 处理权限拒绝 | |
| 211 | - if (errMsg.includes('auth deny') || errMsg.includes('permission denied')) { | |
| 212 | - uni.showModal({ | |
| 213 | - title: '授权提示', | |
| 214 | - content: '需要获取您的位置权限才能自动定位,请在设置中开启', | |
| 215 | - confirmText: '去设置', | |
| 216 | - cancelText: '手动输入', | |
| 217 | - success: (modalRes) => { | |
| 218 | - if (modalRes.confirm) { | |
| 219 | - uni.openSetting(); // 打开系统设置 | |
| 220 | - } else { | |
| 221 | - // 手动输入地址(隐藏地图选择,直接让用户输入) | |
| 222 | - uni.showToast({ title: '请手动输入详细地址', icon: 'none' }); | |
| 223 | - } | |
| 224 | - } | |
| 225 | - }); | |
| 226 | - } | |
| 227 | - | |
| 228 | - // 2. 处理指南针失败(startCompass:fail) | |
| 229 | - else if (errMsg.includes('startCompass:fail')) { | |
| 230 | - uni.showModal({ | |
| 231 | - title: '提示', | |
| 232 | - content: '当前设备不支持指南针功能,将为您打开地图手动选择地址', | |
| 233 | - showCancel: false, | |
| 234 | - success: () => { | |
| 235 | - // 降级方案:不传递初始经纬度,直接打开地图 | |
| 236 | - uni.chooseLocation({ | |
| 237 | - success: (res) => { | |
| 238 | - addressInfo.addressDetail = res.name; | |
| 239 | - addressInfo.garLongitude = res.longitude; | |
| 240 | - addressInfo.garLatitude = res.latitude; | |
| 241 | - }, | |
| 242 | - fail: () => { | |
| 243 | - uni.showToast({ title: '地图选择失败,请手动输入地址', icon: 'none' }); | |
| 244 | - } | |
| 245 | - }); | |
| 246 | - } | |
| 247 | - }); | |
| 248 | - } | |
| 249 | - | |
| 250 | - // 3. 其他错误(网络/设备问题) | |
| 251 | - else { | |
| 252 | - uni.showToast({ title: '定位失败,请手动输入地址', icon: 'none' }); | |
| 253 | - } | |
| 254 | -}; | |
| 255 | - | |
| 256 | 183 | onMounted(() => { |
| 257 | 184 | proxy.$refs.addressFrom.setRules(rules) |
| 258 | 185 | }) | ... | ... |
garbage-removal/src/pages/home-info/clean/index.vue
| ... | ... | @@ -630,30 +630,31 @@ |
| 630 | 630 | uni.$u.toast("请勿频繁操作") |
| 631 | 631 | } |
| 632 | 632 | } |
| 633 | - const handlerSaveOrder = async (params) => { | |
| 634 | - await saveOrder(params).then(res => { | |
| 635 | - if (res.data.success) { | |
| 633 | + const handlerSaveOrder = async (params) => { | |
| 634 | + await saveOrder(params).then(res => { | |
| 635 | + if (res.data.success) { | |
| 636 | 636 | store.updateUnreadOrderCount(); |
| 637 | - if (userType.value != "用户") { | |
| 638 | - uni.$u.toast("下单成功,请切换成且角色查看订单详情") | |
| 639 | - uni.$u.route({ | |
| 640 | - type: 'navigateBack', | |
| 641 | - url: `pages/home/index`, | |
| 642 | - }) | |
| 643 | - } else { | |
| 644 | - uni.$u.toast('下单成功') | |
| 645 | - uni.$u.route({ | |
| 646 | - type: "redirect", | |
| 647 | - url: `pages/order-info/order-other/detail/index`, | |
| 648 | - params: { | |
| 649 | - orderId: res.data.data | |
| 650 | - } | |
| 651 | - }) | |
| 652 | - } | |
| 653 | - } | |
| 654 | - }) | |
| 655 | - | |
| 656 | - } | |
| 637 | + // 发送自定义事件通知订单列表更新 | |
| 638 | + uni.$emit('orderCreated', { type: 'newOrder' }); | |
| 639 | + if (userType.value !== "用户") { | |
| 640 | + uni.$u.toast("下单成功,请切换成且角色查看订单详情") | |
| 641 | + uni.$u.route({ | |
| 642 | + type: 'navigateBack', | |
| 643 | + url: `pages/home/index`, | |
| 644 | + }) | |
| 645 | + } else { | |
| 646 | + uni.$u.toast('下单成功') | |
| 647 | + uni.$u.route({ | |
| 648 | + type: "redirect", | |
| 649 | + url: `pages/order-info/order-other/detail/index`, | |
| 650 | + params: { | |
| 651 | + orderId: res.data.data | |
| 652 | + } | |
| 653 | + }) | |
| 654 | + } | |
| 655 | + } | |
| 656 | + }) | |
| 657 | + } | |
| 657 | 658 | |
| 658 | 659 | const handlerChooseAddress = () => { |
| 659 | 660 | addressPopupRef.value.open(userAddress.value) | ... | ... |
garbage-removal/src/pages/home/index.vue
| ... | ... | @@ -163,6 +163,10 @@ const dropdownOptions = ref([ |
| 163 | 163 | label: '湘江新区', |
| 164 | 164 | value: '湘江新区' |
| 165 | 165 | }, |
| 166 | + { | |
| 167 | + label: '芙蓉区', | |
| 168 | + value: '芙蓉区' | |
| 169 | + }, | |
| 166 | 170 | { |
| 167 | 171 | label: '天心区', |
| 168 | 172 | value: '天心区' |
| ... | ... | @@ -190,10 +194,6 @@ const dropdownOptions = ref([ |
| 190 | 194 | { |
| 191 | 195 | label: '宁乡市', |
| 192 | 196 | value: '宁乡市' |
| 193 | - }, | |
| 194 | - { | |
| 195 | - label: '芙蓉区', | |
| 196 | - value: '芙蓉区' | |
| 197 | 197 | } |
| 198 | 198 | ], [{ |
| 199 | 199 | label: '暂未开放', | ... | ... |
garbage-removal/src/pages/order-info/order-driver/detail/index.vue
| ... | ... | @@ -45,14 +45,14 @@ |
| 45 | 45 | </view> |
| 46 | 46 | </view> |
| 47 | 47 | |
| 48 | - | |
| 48 | + | |
| 49 | 49 | <view class="order-detail-container-header-item" v-for="(disposal,index) in dataGram.disposalSites"> |
| 50 | 50 | <view> |
| 51 | 51 | <text class="order-detail-container-header-title" v-if="index == 0" >处置场地:</text> |
| 52 | 52 | <text class="order-detail-container-header-title" v-else >     </text> |
| 53 | 53 | </view> |
| 54 | 54 | <view class="order-detail-container-header-content" style="text-decoration: underline" @click.stop="handlerJumpOtherApp(disposal.latitude, disposal.longitude, dataGram.garCoordinate)"> |
| 55 | - <text>{{ disposal.addrStr }}</text> | |
| 55 | + <text>{{ disposal.addrStr }}</text> | |
| 56 | 56 | </view> |
| 57 | 57 | </view> |
| 58 | 58 | |
| ... | ... | @@ -90,7 +90,7 @@ |
| 90 | 90 | <view class="order-detail-container-box-card"> |
| 91 | 91 | <view class="order-detail-container-header-card-title"> |
| 92 | 92 | <view class="order-detail-container-header-card-uicon"></view> |
| 93 | - 订单人员 | |
| 93 | + 订单信息 | |
| 94 | 94 | </view> |
| 95 | 95 | <!-- <view class="order-detail-container-header-item"> |
| 96 | 96 | <text class="order-detail-container-header-title">订单时间:</text> |
| ... | ... | @@ -152,12 +152,12 @@ |
| 152 | 152 | <view v-for="group in putOnImagesGrouped" :key="group.index" class="image-group"> |
| 153 | 153 | <view class="image-group-header"> |
| 154 | 154 | <view class="image-group-title">{{ group.carName}}第 {{ group.index }} 趟</view> |
| 155 | - <!-- 根据group.index与真实发车数比较显示状态 --> | |
| 155 | + <!-- 根据group.carStatus显示状态 --> | |
| 156 | 156 | <view class="car-status" :class="{ |
| 157 | - 'in-transit': isInTransit(group.index), | |
| 158 | - 'completed': isCompleted(group.index) | |
| 159 | - }"> | |
| 160 | - {{ getStatusText(group.index) }} | |
| 157 | + 'in-transit': group.carStatus === '0', | |
| 158 | + 'completed': group.carStatus === '1' || group.carStatus === '2' | |
| 159 | + }"> | |
| 160 | + {{ (group.carStatus === '1'||group.carStatus === '2') ? '已运完' : '正在清运' }} | |
| 161 | 161 | </view> |
| 162 | 162 | </view> |
| 163 | 163 | <u-upload width="180" height="130" :fileList="group.images" name="3" multiple :maxCount="20" |
| ... | ... | @@ -352,32 +352,40 @@ const handleEvaluateDetail = (orderId, userType) => { |
| 352 | 352 | const selectClick = (index) => { |
| 353 | 353 | currentCancelName.value = index.name; |
| 354 | 354 | } |
| 355 | + | |
| 355 | 356 | const handleOrderDetail = (orderId) => { |
| 356 | 357 | queryOrderDetail(orderId).then(res => { |
| 357 | 358 | dataGram.value = res.data.data; |
| 358 | 359 | currentImages.value = res.data.data.currentImages.map(item => { |
| 359 | 360 | return { url: import.meta.env.VITE_BASE_URL + item}; |
| 360 | 361 | }); |
| 361 | - | |
| 362 | + | |
| 362 | 363 | putOnImages.value = res.data.data.putOnImages.map(item => { |
| 363 | 364 | let processedItem = item; |
| 364 | 365 | let carName = ''; |
| 365 | - | |
| 366 | + let carStatus = ''; | |
| 367 | + | |
| 366 | 368 | // 提取name后面的字符串作为carName并从item中移除 |
| 367 | 369 | if (item.includes('name')) { |
| 368 | 370 | const nameIndex = item.indexOf('name'); |
| 369 | 371 | carName = item.substring(nameIndex + 4); |
| 370 | 372 | |
| 373 | + // 检查carName末尾是否包含状态值(0或1) | |
| 374 | + if (carName.endsWith('0') || carName.endsWith('1') || carName.endsWith('2')) { | |
| 375 | + carStatus = carName.slice(-1); | |
| 376 | + carName = carName.slice(0, -1); | |
| 377 | + } | |
| 378 | + | |
| 371 | 379 | processedItem = item.substring(0, nameIndex); |
| 372 | 380 | } |
| 373 | - | |
| 374 | - // 保持原有逻辑不变,但添加carName到返回对象 | |
| 381 | + | |
| 382 | + // 保持原有逻辑不变,但添加carName和carStatus到返回对象 | |
| 375 | 383 | const newItem = processedItem.substring(0, processedItem.length - 6); |
| 376 | 384 | const newIndex = processedItem.substring(processedItem.length - 6); |
| 377 | - return { url: import.meta.env.VITE_BASE_URL + newItem, newIndex, carName }; | |
| 385 | + return { url: import.meta.env.VITE_BASE_URL + newItem, newIndex, carName, carStatus }; | |
| 378 | 386 | }); |
| 379 | 387 | |
| 380 | - | |
| 388 | + | |
| 381 | 389 | // 按照newIndex升序排序 |
| 382 | 390 | putOnImages.value.sort((a, b) => { |
| 383 | 391 | return parseInt(a.newIndex) - parseInt(b.newIndex); |
| ... | ... | @@ -403,7 +411,8 @@ const handleOrderDetail = (orderId) => { |
| 403 | 411 | putOnImagesGrouped.value = Object.keys(newGroupedImages).map(key => ({ |
| 404 | 412 | index: key, |
| 405 | 413 | images: newGroupedImages[key], |
| 406 | - carName: newGroupedImages[key] && newGroupedImages[key].length > 0 ? newGroupedImages[key][0].carName : '' | |
| 414 | + carName: newGroupedImages[key] && newGroupedImages[key].length > 0 ? newGroupedImages[key][0].carName : '', | |
| 415 | + carStatus: newGroupedImages[key] && newGroupedImages[key].length > 0 ? newGroupedImages[key][0].carStatus : '' | |
| 407 | 416 | })); |
| 408 | 417 | putDownImages.value = res.data.data.putDownImages.map(item => { |
| 409 | 418 | return { url: import.meta.env.VITE_BASE_URL + item }; | ... | ... |
garbage-removal/src/pages/order-info/order-other/detail/index.vue
| ... | ... | @@ -136,7 +136,7 @@ |
| 136 | 136 | </view> |
| 137 | 137 | <!-- 车辆信息 --> |
| 138 | 138 | |
| 139 | - <view class="order-detail-container-box-card vehicle-section" v-if="userType !== '用户'"> | |
| 139 | + <view class="order-detail-container-box-card vehicle-section" v-if="dataGram.garOrderHandlerStatus !== 3"> | |
| 140 | 140 | <view class="section-header"> |
| 141 | 141 | <view class="header-icon-bar"></view> |
| 142 | 142 | <u-icon name="car" size="22" color="#fff" style="margin-right: 10rpx;"></u-icon> |
| ... | ... | @@ -150,9 +150,31 @@ |
| 150 | 150 | <text class="summary-value">{{ realCarCount }}</text> |
| 151 | 151 | <text class="summary-unit">次</text> |
| 152 | 152 | </view> |
| 153 | + <view v-if="userType === '用户'" class="reduce-trip-section"> | |
| 154 | + <text class="reduce-label">减少发车次数:</text> | |
| 155 | + <view class="right-controls"> | |
| 156 | + <u-number-box | |
| 157 | + v-model="reduceTripCount" | |
| 158 | + :min="1" | |
| 159 | + :max="realCarCount - 1" | |
| 160 | + integer | |
| 161 | + buttonSize="30" | |
| 162 | + inputWidth="50" | |
| 163 | + style="margin: 0 20rpx;"> | |
| 164 | + </u-number-box> | |
| 165 | + <u-button | |
| 166 | + type="primary" | |
| 167 | + size="mini" | |
| 168 | + @click="handleReduceTrips" | |
| 169 | + :disabled="reduceTripCount <= 0 || realCarCount <= 1" | |
| 170 | + style="background-color: #19a97c; max-width: 120rpx; font-size: 20rpx; padding: 0 10rpx;"> | |
| 171 | + 确认减少 | |
| 172 | + </u-button> | |
| 173 | + </view> | |
| 174 | + </view> | |
| 153 | 175 | </view> |
| 154 | 176 | |
| 155 | - <view class="vehicle-info-card" v-if="dataGram.garCarInfoList && dataGram.garCarInfoList.length > 0"> | |
| 177 | + <view class="vehicle-info-card" v-if="dataGram.garCarInfoList && dataGram.garCarInfoList.length > 0 &&userType !== '用户'"> | |
| 156 | 178 | <view class="card-header"> |
| 157 | 179 | <u-icon name="file-text" size="18" color="#19a97c"></u-icon> |
| 158 | 180 | <text class="card-title">车辆类型详情</text> |
| ... | ... | @@ -173,7 +195,7 @@ |
| 173 | 195 | </view> |
| 174 | 196 | </view> |
| 175 | 197 | |
| 176 | - <view class="handler-list-card" > | |
| 198 | + <view class="handler-list-card" v-if=" userType !== '用户'"> | |
| 177 | 199 | <view class="card-header"> |
| 178 | 200 | <u-icon name="list" size="18" color="#19a97c"></u-icon> |
| 179 | 201 | <text class="card-title">处理人员信息</text> |
| ... | ... | @@ -219,9 +241,10 @@ |
| 219 | 241 | <view class="section-header"> |
| 220 | 242 | <view class="header-icon-bar"></view> |
| 221 | 243 | <u-icon name="account" size="22" color="#fff" style="margin-right: 8rpx;"></u-icon> |
| 222 | - <text class="header-title">订单人员</text> | |
| 244 | + <text class="header-title">订单信息</text> | |
| 223 | 245 | </view> |
| 224 | 246 | |
| 247 | + | |
| 225 | 248 | <view class="info-item"> |
| 226 | 249 | <view class="info-label"> |
| 227 | 250 | <u-icon name="clock" size="16" color="#19a97c" style="margin-right: 8rpx;"></u-icon> |
| ... | ... | @@ -257,6 +280,29 @@ |
| 257 | 280 | |
| 258 | 281 | <view class="info-item"> |
| 259 | 282 | <view class="info-label"> |
| 283 | + <u-icon name="map" size="16" color="#19a97c" style="margin-right: 8rpx;"></u-icon> | |
| 284 | + <text>处理场所:</text> | |
| 285 | + </view> | |
| 286 | + <!-- 修改后 --> | |
| 287 | + <view class="info-content" v-if="selectedDisposalSites.length > 0" style="flex-direction: column; align-items: flex-start;"> | |
| 288 | + <view v-for="(site, index) in selectedDisposalSites" :key="index" style="margin-bottom: 15rpx; width: 100%;"> | |
| 289 | + <text class="content-text">{{ site.companyName }}</text> | |
| 290 | + <view v-if="site.contactName" style="margin-top: 5rpx;"> | |
| 291 | + <text class="content-text">联系人: {{ site.contactName }}</text> | |
| 292 | + </view> | |
| 293 | + <!-- 修改后 --> | |
| 294 | + <view v-if="site.contactPhone" style="margin-top: 5rpx; display: flex; align-items: center;"> | |
| 295 | + <text style="flex: 1;">联系电话: {{ site.contactPhone }}</text> | |
| 296 | + <view style="margin-left: 10rpx;" v-if="dataGram.handleFlag" @click="handleContactClick(site.contactPhone)"> | |
| 297 | + <u-icon name="phone-fill" size="20" color="#19a97c"></u-icon> | |
| 298 | + </view> | |
| 299 | + </view> | |
| 300 | + </view> | |
| 301 | + </view> | |
| 302 | + </view> | |
| 303 | + | |
| 304 | + <view class="info-item"> | |
| 305 | + <view class="info-label"> | |
| 260 | 306 | <u-icon name="file-text" size="16" color="#19a97c" style="margin-right: 8rpx;"></u-icon> |
| 261 | 307 | <text>备注:</text> |
| 262 | 308 | </view> |
| ... | ... | @@ -287,10 +333,10 @@ |
| 287 | 333 | <view class="image-group-header"> |
| 288 | 334 | <view class="image-group-title">{{ group.carName}}第 {{ group.index }} 趟</view> |
| 289 | 335 | <view class="car-status" :class="{ |
| 290 | - 'in-transit': isInTransit(group.index), | |
| 291 | - 'completed': isCompleted(group.index) | |
| 292 | - }"> | |
| 293 | - {{ getStatusText(group.index) }} | |
| 336 | + 'in-transit': group.carStatus === '0', | |
| 337 | + 'completed': group.carStatus === '1' || group.carStatus === '2' | |
| 338 | + }"> | |
| 339 | + {{ (group.carStatus === '1'||group.carStatus === '2') ? '已运完' : '正在清运' }} | |
| 294 | 340 | </view> |
| 295 | 341 | </view> |
| 296 | 342 | <u-upload width="180" height="130" :fileList="group.images" name="3" multiple :maxCount="20" |
| ... | ... | @@ -453,6 +499,7 @@ const carCount = ref(null) |
| 453 | 499 | const tel = ref(null) |
| 454 | 500 | const selectedHandlerTel = ref("") |
| 455 | 501 | const realCarCount = ref(null) |
| 502 | +const reduceTripCount = ref(1) // 要减少的发车次数 | |
| 456 | 503 | const store = useMainStore(); |
| 457 | 504 | const userType = computed(() => store.userType) |
| 458 | 505 | const dataGram = ref(); |
| ... | ... | @@ -475,6 +522,7 @@ const selectedHandlerTels = ref("") |
| 475 | 522 | const garCarTypeList = ref([]) |
| 476 | 523 | const driverAssigned = ref(false); // 添加这行,跟踪驾驶员是否已分配 |
| 477 | 524 | const disposalAssigned = ref(false); // 添加这行,跟踪处置场所是否已分配 |
| 525 | +const selectedDisposalSites = ref([]); | |
| 478 | 526 | // 新增:用于存储待分配的驾驶员列表 |
| 479 | 527 | const pendingDriverAssignments = ref({}) |
| 480 | 528 | |
| ... | ... | @@ -547,6 +595,37 @@ const list = computed(() => { |
| 547 | 595 | return reason |
| 548 | 596 | }) |
| 549 | 597 | |
| 598 | +const handleReduceTrips = () => { | |
| 599 | + if (!reduceTripCount.value || reduceTripCount.value <= 0) { | |
| 600 | + uni.$u.toast('请输入有效的减少次数'); | |
| 601 | + return; | |
| 602 | + } | |
| 603 | + | |
| 604 | + if (realCarCount.value <= reduceTripCount.value) { | |
| 605 | + uni.$u.toast('减少次数不能超过当前总次数'); | |
| 606 | + return; | |
| 607 | + } | |
| 608 | + | |
| 609 | + // 调用接口,传递负数表示减少 | |
| 610 | + updateGarRealCarCount(orderId.value, -reduceTripCount.value) | |
| 611 | + .then(res => { | |
| 612 | + if (res.data.success) { | |
| 613 | + uni.$u.toast(`减少${reduceTripCount.value}次成功!`); | |
| 614 | + // 刷新订单详情 | |
| 615 | + handleOrderDetail(orderId.value); | |
| 616 | + refreshOrderData(); | |
| 617 | + // 重置减少次数 | |
| 618 | + reduceTripCount.value = 1; | |
| 619 | + } else { | |
| 620 | + uni.$u.toast(`减少次数失败!`); | |
| 621 | + } | |
| 622 | + }) | |
| 623 | + .catch(err => { | |
| 624 | + uni.$u.toast('减少次数请求失败'); | |
| 625 | + console.error('减少次数失败:', err); | |
| 626 | + }); | |
| 627 | +} | |
| 628 | + | |
| 550 | 629 | const isDriverAssigned = computed(() => { |
| 551 | 630 | // 检查是否有分配的驾驶员 |
| 552 | 631 | return handlerList.value && handlerList.value.length > 0; |
| ... | ... | @@ -914,22 +993,57 @@ const handleOrderDetail = (orderId) => { |
| 914 | 993 | }; |
| 915 | 994 | }); |
| 916 | 995 | |
| 996 | + // 同时调用queryDisposalDispatch接口获取处理场所信息 | |
| 997 | + queryDisposalDispatch(orderId).then(disposalRes => { | |
| 998 | + if (disposalRes.data.success && disposalRes.data.data && disposalRes.data.data.length > 0) { | |
| 999 | + // 根据实际返回数据结构提取处理场所信息,只显示选中的联系人 | |
| 1000 | + selectedDisposalSites.value = disposalRes.data.data | |
| 1001 | + .map(site => { | |
| 1002 | + // 筛选出personnelInfo中checked为true的联系人 | |
| 1003 | + const selectedPerson = site.personnelInfo && site.personnelInfo.length > 0 ? | |
| 1004 | + site.personnelInfo.find(person => person.checked) : null; | |
| 1005 | + | |
| 1006 | + return { | |
| 1007 | + companyName: site.garOrderDisposalCompanyName, | |
| 1008 | + contactName: selectedPerson ? selectedPerson.personName : '', | |
| 1009 | + contactPhone: selectedPerson ? selectedPerson.tel : '' | |
| 1010 | + }; | |
| 1011 | + }) | |
| 1012 | + // 过滤掉没有选中联系人的处理场所 | |
| 1013 | + .filter(site => site.contactName && site.contactPhone); | |
| 1014 | + | |
| 1015 | + // 设置已分配状态 | |
| 1016 | + disposalAssigned.value = selectedDisposalSites.value.length > 0; | |
| 1017 | + console.log('从queryDisposalDispatch获取的处理场所信息:', selectedDisposalSites.value); | |
| 1018 | + } else { | |
| 1019 | + selectedDisposalSites.value = []; | |
| 1020 | + disposalAssigned.value = false; | |
| 1021 | + } | |
| 1022 | + }); | |
| 1023 | + | |
| 917 | 1024 | putOnImages.value = res.data.data.putOnImages.map(item => { |
| 918 | 1025 | let processedItem = item; |
| 919 | 1026 | let carName = ''; |
| 1027 | + let carStatus = ''; | |
| 920 | 1028 | |
| 921 | 1029 | // 提取name后面的字符串作为carName并从item中移除 |
| 922 | 1030 | if (item.includes('name')) { |
| 923 | 1031 | const nameIndex = item.indexOf('name'); |
| 924 | 1032 | carName = item.substring(nameIndex + 4); |
| 925 | 1033 | |
| 1034 | + // 检查carName末尾是否包含状态值(0或1) | |
| 1035 | + if (carName.endsWith('0') || carName.endsWith('1') || carName.endsWith('2')) { | |
| 1036 | + carStatus = carName.slice(-1); | |
| 1037 | + carName = carName.slice(0, -1); | |
| 1038 | + } | |
| 1039 | + | |
| 926 | 1040 | processedItem = item.substring(0, nameIndex); |
| 927 | 1041 | } |
| 928 | 1042 | |
| 929 | - // 保持原有逻辑不变,但添加carName到返回对象 | |
| 1043 | + // 保持原有逻辑不变,但添加carName和carStatus到返回对象 | |
| 930 | 1044 | const newItem = processedItem.substring(0, processedItem.length - 6); |
| 931 | 1045 | const newIndex = processedItem.substring(processedItem.length - 6); |
| 932 | - return { url: import.meta.env.VITE_BASE_URL + newItem, newIndex, carName }; | |
| 1046 | + return { url: import.meta.env.VITE_BASE_URL + newItem, newIndex, carName, carStatus }; | |
| 933 | 1047 | }); |
| 934 | 1048 | |
| 935 | 1049 | // 按照newIndex升序排序 |
| ... | ... | @@ -957,7 +1071,8 @@ const handleOrderDetail = (orderId) => { |
| 957 | 1071 | putOnImagesGrouped.value = Object.keys(newGroupedImages).map(key => ({ |
| 958 | 1072 | index: key, |
| 959 | 1073 | images: newGroupedImages[key], |
| 960 | - carName: newGroupedImages[key] && newGroupedImages[key].length > 0 ? newGroupedImages[key][0].carName : '' | |
| 1074 | + carName: newGroupedImages[key] && newGroupedImages[key].length > 0 ? newGroupedImages[key][0].carName : '', | |
| 1075 | + carStatus: newGroupedImages[key] && newGroupedImages[key].length > 0 ? newGroupedImages[key][0].carStatus : '' | |
| 961 | 1076 | })); |
| 962 | 1077 | console.log('putOnImagesGrouped.value:', putOnImagesGrouped.value); |
| 963 | 1078 | putDownImages.value = res.data.data.putDownImages.map(item => { |
| ... | ... | @@ -1157,10 +1272,21 @@ const handleDisposalDispatchConfirm = (val) => { |
| 1157 | 1272 | garOrderId: orderId.value, |
| 1158 | 1273 | dispatchList: [] |
| 1159 | 1274 | } |
| 1275 | + | |
| 1276 | + // 新增:存储选中的处理场所信息 | |
| 1277 | + selectedDisposalSites.value = []; | |
| 1278 | + | |
| 1160 | 1279 | for (const key in val) { |
| 1161 | 1280 | data.dispatchList.push({ |
| 1162 | 1281 | ...val[key] |
| 1163 | 1282 | }); |
| 1283 | + | |
| 1284 | + // 新增:提取处理场所信息 | |
| 1285 | + selectedDisposalSites.value.push({ | |
| 1286 | + companyName: val[key].companyName, | |
| 1287 | + contactName: val[key].personName, | |
| 1288 | + contactPhone: val[key].tel | |
| 1289 | + }); | |
| 1164 | 1290 | } |
| 1165 | 1291 | console.log(data); |
| 1166 | 1292 | dispatchDisposalOrders(data).then(res => { |
| ... | ... | @@ -1169,6 +1295,8 @@ const handleDisposalDispatchConfirm = (val) => { |
| 1169 | 1295 | // 标记处置场所已分配 |
| 1170 | 1296 | disposalAssigned.value = true; |
| 1171 | 1297 | // 检查是否两个任务都已完成 |
| 1298 | + // 立即刷新订单详情以确保分配信息得到保存 | |
| 1299 | + handleOrderDetail(orderId.value); | |
| 1172 | 1300 | } else { |
| 1173 | 1301 | uni.$u.toast("指定人员失败,请重试") |
| 1174 | 1302 | } |
| ... | ... | @@ -1176,6 +1304,7 @@ const handleDisposalDispatchConfirm = (val) => { |
| 1176 | 1304 | }) |
| 1177 | 1305 | } |
| 1178 | 1306 | |
| 1307 | + | |
| 1179 | 1308 | const handlerUpdateOrderClick = () => { |
| 1180 | 1309 | carPopupShowFlag.value = true; |
| 1181 | 1310 | // TODO 照搬一键清运得弹窗 |
| ... | ... | @@ -1648,28 +1777,59 @@ $custom-bottom-height: 200rpx; |
| 1648 | 1777 | |
| 1649 | 1778 | /* 发车次数摘要 */ |
| 1650 | 1779 | .trip-summary-card { |
| 1780 | + /* 现有的 summary-content 样式保持不变 */ | |
| 1651 | 1781 | .summary-content { |
| 1652 | 1782 | display: flex; |
| 1653 | 1783 | align-items: center; |
| 1654 | - padding: 20rpx 15rpx; /* 减小内边距 */ | |
| 1784 | + padding: 20rpx 15rpx; | |
| 1655 | 1785 | background: linear-gradient(90deg, #e8f4f0, #fff); |
| 1656 | 1786 | |
| 1657 | 1787 | .summary-label { |
| 1658 | 1788 | color: #666; |
| 1659 | - margin-right: 8rpx; /* 减小右边距 */ | |
| 1660 | - font-size: 24rpx; /* 减小字体大小 */ | |
| 1789 | + margin-right: 8rpx; | |
| 1790 | + font-size: 24rpx; | |
| 1661 | 1791 | } |
| 1662 | 1792 | |
| 1663 | 1793 | .summary-value { |
| 1664 | 1794 | color: #19a97c; |
| 1665 | 1795 | font-weight: bold; |
| 1666 | - font-size: 28rpx; /* 减小字体大小 */ | |
| 1667 | - margin: 0 4rpx; /* 减小边距 */ | |
| 1796 | + font-size: 28rpx; | |
| 1797 | + margin: 0 4rpx; | |
| 1668 | 1798 | } |
| 1669 | 1799 | |
| 1670 | 1800 | .summary-unit { |
| 1671 | 1801 | color: #666; |
| 1672 | - font-size: 24rpx; /* 减小字体大小 */ | |
| 1802 | + font-size: 24rpx; | |
| 1803 | + } | |
| 1804 | + } | |
| 1805 | + | |
| 1806 | + /* 添加 reduce-trip-section 的样式 */ | |
| 1807 | + /* 添加 reduce-trip-section 的样式 */ | |
| 1808 | + .reduce-trip-section { | |
| 1809 | + display: flex; | |
| 1810 | + flex-wrap: wrap; /* 允许内容换行 */ | |
| 1811 | + justify-content: space-between; /* 两端对齐,使右侧控件靠右 */ | |
| 1812 | + align-items: center; | |
| 1813 | + padding: 20rpx 15rpx; | |
| 1814 | + border-top: 1rpx solid #e8f4f0; | |
| 1815 | + | |
| 1816 | + .reduce-label { | |
| 1817 | + color: #666; | |
| 1818 | + font-size: 24rpx; | |
| 1819 | + min-width: 120rpx; /* 固定标签宽度,防止换行 */ | |
| 1820 | + } | |
| 1821 | + | |
| 1822 | + /* 右侧控件容器 */ | |
| 1823 | + .right-controls { | |
| 1824 | + display: flex; | |
| 1825 | + align-items: center; | |
| 1826 | + } | |
| 1827 | + | |
| 1828 | + /* 为按钮添加样式 */ | |
| 1829 | + .u-button { | |
| 1830 | + max-width: 120rpx; /* 限制按钮最大宽度 */ | |
| 1831 | + font-size: 20rpx; /* 减小字体大小 */ | |
| 1832 | + padding: 0 10rpx; /* 调整内边距 */ | |
| 1673 | 1833 | } |
| 1674 | 1834 | } |
| 1675 | 1835 | } | ... | ... |
garbage-removal/src/pages/order/index.vue
| ... | ... | @@ -33,12 +33,20 @@ const getOrderCountByType = async (type) => { |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | onShow(() => { |
| 36 | - // 调用获取订单数量的接口 | |
| 37 | - getOrderCountByType(0).then(res => { | |
| 38 | - // 设置角标显示为实际的订单总数 | |
| 36 | + // 同时获取待清运和清运中订单数量 | |
| 37 | + Promise.all([ | |
| 38 | + getOrderCountByType(0), // 待清运 | |
| 39 | + getOrderCountByType(1) // 清运中 | |
| 40 | + ]).then(results => { | |
| 41 | + // 计算待清运和清运中订单数量之和 | |
| 42 | + const totalCount = results.reduce((sum, res) => { | |
| 43 | + return sum + (res.data.data.total || 0); | |
| 44 | + }, 0); | |
| 45 | + | |
| 46 | + // 设置角标显示为待清运和清运中订单数量之和 | |
| 39 | 47 | uni.setTabBarBadge({ |
| 40 | 48 | index: 1, // 订单tab在tabBar中的索引 |
| 41 | - text: String(res.data.data.total) // 使用实际的订单总数 | |
| 49 | + text: String(totalCount) // 使用实际的订单总数 | |
| 42 | 50 | }); |
| 43 | 51 | }).catch(error => { |
| 44 | 52 | console.error('获取订单数量失败:', error); | ... | ... |
garbage-removal/src/pages/order/order-disposal/swiper-list-item/index.vue
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | 载运量 {{ item.garNowCarCount }} /{{ item.garRealCarCount }} |
| 21 | 21 | </view> |
| 22 | 22 | <view v-if="item.garNowCarCount === item.garRealCarCount" class="completion-tip"> |
| 23 | - 全部完成 | |
| 23 | + {{ props.tabIndex === 0 ? '清运完成待确认' : '已完成' }} | |
| 24 | 24 | </view> |
| 25 | 25 | </view> |
| 26 | 26 | </view> | ... | ... |
garbage-removal/src/pages/order/order-other/index.vue
| ... | ... | @@ -39,7 +39,7 @@ |
| 39 | 39 | <script setup> |
| 40 | 40 | import { queryOrderMessageCount, queryOrderList } from '@/apis/order.js'; |
| 41 | 41 | import { useMainStore } from '@/stores/index.js'; |
| 42 | -import { computed, nextTick, onMounted, ref } from 'vue'; | |
| 42 | +import { computed, nextTick, onMounted, ref ,onUnmounted} from 'vue'; | |
| 43 | 43 | import swiperListItem from './swiper-list-item/index.vue'; |
| 44 | 44 | const store = useMainStore(); |
| 45 | 45 | // 初始化订单类型列表,添加count属性 |
| ... | ... | @@ -128,7 +128,18 @@ onMounted(() => { |
| 128 | 128 | // 页面加载后获取所有订单总数 |
| 129 | 129 | getAllOrderCounts(); |
| 130 | 130 | }) |
| 131 | + uni.$on('orderCreated', handleOrderCreated); | |
| 131 | 132 | }) |
| 133 | + | |
| 134 | +const handleOrderCreated = () => { | |
| 135 | + // 重新获取所有订单数量 | |
| 136 | + getAllOrderCounts(); | |
| 137 | +}; | |
| 138 | + | |
| 139 | +onUnmounted(() => { | |
| 140 | + // 移除事件监听 | |
| 141 | + uni.$off('orderCreated', handleOrderCreated); | |
| 142 | +}); | |
| 132 | 143 | </script> |
| 133 | 144 | <style lang="scss" scoped> |
| 134 | 145 | .order-container { | ... | ... |
garbage-removal/src/pages/order/order-other/swiper-list-item/index.vue
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | <view style="display: flex;align-items: center;"> |
| 14 | 14 | <view v-if="item.garOrderHandlerStatus === 0 && item.garCancelFlag === 0" class="right">待清运 </view> |
| 15 | 15 | <view v-if="item.garCancelFlag === 1" class="right">已取消 </view> |
| 16 | - <view v-if="item.garOrderHandlerStatus === 1 && item.garCancelFlag === 0" class="right">清运中 </view> | |
| 16 | + <view v-if="item.garOrderHandlerStatus === 1 && item.garCancelFlag === 0 && item.garNowCarCount !== item.garRealCarCount" class="right">清运中 </view> | |
| 17 | 17 | <view v-if="item.garOrderHandlerStatus === 1 && item.garCancelFlag === 0 && item.garNowCarCount === item.garRealCarCount" class="right">已完成 </view> |
| 18 | 18 | </view> |
| 19 | 19 | <view v-if="item.garEvaluateFlag === 0 && userType === '用户'" class="right">待评价 | ... | ... |