Commit 74b5d9c1b15bcb4cb5577d99c7834f84d370b55f
1 parent
6283a76f
提交12-19
Showing
11 changed files
with
527 additions
and
289 deletions
garbage-removal/src/components/clash-disposal-dispatch/index.vue
| @@ -142,7 +142,7 @@ function changeVerify(current, chooseList) { | @@ -142,7 +142,7 @@ function changeVerify(current, chooseList) { | ||
| 142 | function open(dataList) { | 142 | function open(dataList) { |
| 143 | treeData.value = handlerTreeData(dataList) | 143 | treeData.value = handlerTreeData(dataList) |
| 144 | treeData.value = treeData.value.filter(item => { | 144 | treeData.value = treeData.value.filter(item => { |
| 145 | - return item.children[0].id | 145 | + return item.children && item.children.length > 0 && item.children[0] && item.children[0].id |
| 146 | }) | 146 | }) |
| 147 | setTimeout(() => { | 147 | setTimeout(() => { |
| 148 | nextTick(() => { | 148 | nextTick(() => { |
| @@ -158,7 +158,7 @@ function handlerTreeData(dataList) { | @@ -158,7 +158,7 @@ function handlerTreeData(dataList) { | ||
| 158 | "id": (index + 1), | 158 | "id": (index + 1), |
| 159 | "name": item.garOrderDisposalCompanyName, | 159 | "name": item.garOrderDisposalCompanyName, |
| 160 | "label": item.garOrderDisposalCompanyName, | 160 | "label": item.garOrderDisposalCompanyName, |
| 161 | - "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | 161 | + "children": (item.personnelInfo || []).map((childrenItem, childrenIndex) => { |
| 162 | return { | 162 | return { |
| 163 | "id": (index + 1) + '-' + (childrenIndex + 1), | 163 | "id": (index + 1) + '-' + (childrenIndex + 1), |
| 164 | "tel": childrenItem.tel, | 164 | "tel": childrenItem.tel, |
garbage-removal/src/components/clash-driver-dispatch/index.vue
| @@ -123,7 +123,7 @@ function changeVerify(current, chooseList) { | @@ -123,7 +123,7 @@ function changeVerify(current, chooseList) { | ||
| 123 | function open(dataList) { | 123 | function open(dataList) { |
| 124 | treeData.value = handlerTreeData(dataList) | 124 | treeData.value = handlerTreeData(dataList) |
| 125 | treeData.value = treeData.value.filter(item => { | 125 | treeData.value = treeData.value.filter(item => { |
| 126 | - return item.children[0].id | 126 | + return item.children && item.children.length > 0 && item.children[0] && item.children[0].id |
| 127 | }) | 127 | }) |
| 128 | setTimeout(() => { | 128 | setTimeout(() => { |
| 129 | nextTick(() => { | 129 | nextTick(() => { |
| @@ -140,7 +140,7 @@ function handlerTreeData(dataList) { | @@ -140,7 +140,7 @@ function handlerTreeData(dataList) { | ||
| 140 | "licensePlateNumber": item.licensePlateNumber, | 140 | "licensePlateNumber": item.licensePlateNumber, |
| 141 | "containerVolume": item.containerVolume + "方车", | 141 | "containerVolume": item.containerVolume + "方车", |
| 142 | "label": item.containerVolume + "方车" + '-' + item.licensePlateNumber, | 142 | "label": item.containerVolume + "方车" + '-' + item.licensePlateNumber, |
| 143 | - "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | 143 | + "children": (item.personnelInfo || []).map((childrenItem, childrenIndex) => { |
| 144 | return { | 144 | return { |
| 145 | "id": (index + 1) + '-' + (childrenIndex + 1), | 145 | "id": (index + 1) + '-' + (childrenIndex + 1), |
| 146 | "garOrderContainerVolume": item.containerVolume, | 146 | "garOrderContainerVolume": item.containerVolume, |
garbage-removal/src/components/next-tree/next-tree.vue
| @@ -347,6 +347,10 @@ export default { | @@ -347,6 +347,10 @@ export default { | ||
| 347 | }, | 347 | }, |
| 348 | //扁平化树结构 | 348 | //扁平化树结构 |
| 349 | _renderTreeList(list = [], rank = 0, parentId = [], parents = []) { | 349 | _renderTreeList(list = [], rank = 0, parentId = [], parents = []) { |
| 350 | + if (!Array.isArray(list)) { | ||
| 351 | + console.warn('next-tree: _renderTreeList received non-array data:', list); | ||
| 352 | + return; | ||
| 353 | + } | ||
| 350 | list.forEach(item => { | 354 | list.forEach(item => { |
| 351 | const halfChecked = this.getHalfCheckedFormTreeData(item); | 355 | const halfChecked = this.getHalfCheckedFormTreeData(item); |
| 352 | let ouputText = ''; | 356 | let ouputText = ''; |
| @@ -375,24 +379,25 @@ export default { | @@ -375,24 +379,25 @@ export default { | ||
| 375 | halfChecked, | 379 | halfChecked, |
| 376 | disabled: this.disabledKey && item[this.disabledKey] === true | 380 | disabled: this.disabledKey && item[this.disabledKey] === true |
| 377 | }) | 381 | }) |
| 378 | - if ( | ||
| 379 | - (Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length > 0) || | ||
| 380 | - (this.loadData && Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length === 0) | ||
| 381 | - ) { | ||
| 382 | - let parentid = [...parentId], | ||
| 383 | - parentArr = [...parents], | ||
| 384 | - childrenid = []; | ||
| 385 | - delete parentArr.children | ||
| 386 | - parentid.push(item[this.valueKey]); | ||
| 387 | - parentArr.push({ | ||
| 388 | - [this.valueKey]: item[this.valueKey], | ||
| 389 | - [this.labelKey]: item[this.labelKey], | ||
| 390 | - "data": item | ||
| 391 | - }) | ||
| 392 | - this._renderTreeList(item[this.childrenKey], rank + 1, parentid, parentArr); | ||
| 393 | - } else { | ||
| 394 | - this.treeList[this.treeList.length - 1].lastRank = true; | ||
| 395 | - } | 382 | + const children = item[this.childrenKey]; |
| 383 | + if ( | ||
| 384 | + (Array.isArray(children) && children.length > 0) || | ||
| 385 | + (this.loadData && Array.isArray(children) && children.length === 0) | ||
| 386 | + ) { | ||
| 387 | + let parentid = [...parentId], | ||
| 388 | + parentArr = [...parents], | ||
| 389 | + childrenid = []; | ||
| 390 | + delete parentArr.children | ||
| 391 | + parentid.push(item[this.valueKey]); | ||
| 392 | + parentArr.push({ | ||
| 393 | + [this.valueKey]: item[this.valueKey], | ||
| 394 | + [this.labelKey]: item[this.labelKey], | ||
| 395 | + "data": item | ||
| 396 | + }) | ||
| 397 | + this._renderTreeList(children, rank + 1, parentid, parentArr); | ||
| 398 | + } else { | ||
| 399 | + this.treeList[this.treeList.length - 1].lastRank = true; | ||
| 400 | + } | ||
| 396 | }) | 401 | }) |
| 397 | }, | 402 | }, |
| 398 | // 处理默认选择 | 403 | // 处理默认选择 |
| @@ -522,38 +527,39 @@ export default { | @@ -522,38 +527,39 @@ export default { | ||
| 522 | } else if (!this.showHalfCheckedTips) { | 527 | } else if (!this.showHalfCheckedTips) { |
| 523 | return false | 528 | return false |
| 524 | } else { | 529 | } else { |
| 525 | - if (item[this.childrenKey] && item[this.childrenKey].length) { | ||
| 526 | - return item[this.childrenKey].some(it => { | ||
| 527 | - if (it.checked === true) { | ||
| 528 | - return true; | ||
| 529 | - } else if (it[this.childrenKey] && it[this.childrenKey].length) { | ||
| 530 | - return this.getHalfCheckedFormTreeData(it); | ||
| 531 | - } else { | ||
| 532 | - return false; | ||
| 533 | - }; | ||
| 534 | - }); | ||
| 535 | - } else { | ||
| 536 | - return false; | ||
| 537 | - } | 530 | + const children = item[this.childrenKey]; |
| 531 | + if (Array.isArray(children) && children.length) { | ||
| 532 | + return children.some(it => { | ||
| 533 | + if (it.checked === true) { | ||
| 534 | + return true; | ||
| 535 | + } else if (it[this.childrenKey] && Array.isArray(it[this.childrenKey]) && it[this.childrenKey].length) { | ||
| 536 | + return this.getHalfCheckedFormTreeData(it); | ||
| 537 | + } else { | ||
| 538 | + return false; | ||
| 539 | + }; | ||
| 540 | + }); | ||
| 541 | + } else { | ||
| 542 | + return false; | ||
| 543 | + } | ||
| 538 | } | 544 | } |
| 539 | }, | 545 | }, |
| 540 | getItemFromTreeData(treeData, id) { | 546 | getItemFromTreeData(treeData, id) { |
| 541 | - if (id) { | ||
| 542 | - let item = null; | ||
| 543 | - (treeData || []).some(it => { | ||
| 544 | - if (it[this.valueKey] === id) { | ||
| 545 | - item = it | ||
| 546 | - return true | ||
| 547 | - } else if (it[this.childrenKey] && it[this.childrenKey].length) { | ||
| 548 | - item = this.getItemFromTreeData(it[this.childrenKey], id) | ||
| 549 | - return !!item | ||
| 550 | - } else { | ||
| 551 | - return false | ||
| 552 | - } | ||
| 553 | - }); | ||
| 554 | - return item | ||
| 555 | - }; | ||
| 556 | - return null | 547 | + if (id) { |
| 548 | + let item = null; | ||
| 549 | + (treeData || []).some(it => { | ||
| 550 | + if (it[this.valueKey] === id) { | ||
| 551 | + item = it | ||
| 552 | + return true | ||
| 553 | + } else if (it[this.childrenKey] && Array.isArray(it[this.childrenKey]) && it[this.childrenKey].length) { | ||
| 554 | + item = this.getItemFromTreeData(it[this.childrenKey], id) | ||
| 555 | + return !!item | ||
| 556 | + } else { | ||
| 557 | + return false | ||
| 558 | + } | ||
| 559 | + }); | ||
| 560 | + return item | ||
| 561 | + }; | ||
| 562 | + return null | ||
| 557 | }, | 563 | }, |
| 558 | _treeItemSelect(item, _index) { | 564 | _treeItemSelect(item, _index) { |
| 559 | const index = this.treeList.findIndex(it => it.id === item.id); | 565 | const index = this.treeList.findIndex(it => it.id === item.id); |
| @@ -598,79 +604,87 @@ export default { | @@ -598,79 +604,87 @@ export default { | ||
| 598 | this._fixMultiple(index); | 604 | this._fixMultiple(index); |
| 599 | } | 605 | } |
| 600 | }, | 606 | }, |
| 601 | - updateParentChecked(index) { | ||
| 602 | - const parentId = (this.treeList[index].parentId || []).concat([]).reverse(); | ||
| 603 | - if (parentId && parentId.length) { | ||
| 604 | - parentId.map(id => { | ||
| 605 | - const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id); | ||
| 606 | - const childrenIds = (parentTreeDataItem[this.childrenKey] || []).map(item => item[this.valueKey]); | ||
| 607 | - const bool = this.treeList | ||
| 608 | - .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 609 | - .every(it => it.checked === true); | 607 | + updateParentChecked(index) { |
| 608 | + const parentId = (this.treeList[index].parentId || []).concat([]).reverse(); | ||
| 609 | + if (parentId && parentId.length) { | ||
| 610 | + parentId.map(id => { | ||
| 611 | + const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id); | ||
| 612 | + // 添加安全检查:确保parentTreeDataItem和childrenKey存在 | ||
| 613 | + const children = parentTreeDataItem && parentTreeDataItem[this.childrenKey]; | ||
| 614 | + if (!Array.isArray(children)) return; | ||
| 610 | 615 | ||
| 611 | - const _bool = this.treeList | ||
| 612 | - .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 613 | - .every(it => it.checked === false); | 616 | + const childrenIds = children.map(item => item[this.valueKey]); |
| 617 | + const bool = this.treeList | ||
| 618 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 619 | + .every(it => it.checked === true); | ||
| 614 | 620 | ||
| 615 | - const parentItem = this.treeList.find(it => it.id === id); | ||
| 616 | - if (parentItem) { | ||
| 617 | - if (this.checkStrictlyModel === 'weak') { | ||
| 618 | - if (bool && !parentItem.disabled) { | ||
| 619 | - parentItem.checked = true; | ||
| 620 | - } else if (_bool && !parentItem.disabled) { | ||
| 621 | - parentItem.checked = false; | ||
| 622 | - } | ||
| 623 | - } else if (this.checkStrictlyModel === 'strong') { | ||
| 624 | - if (bool) { | ||
| 625 | - parentItem.checked = true; | ||
| 626 | - } else { | ||
| 627 | - parentItem.checked = false; | ||
| 628 | - } | ||
| 629 | - } | ||
| 630 | - } | ||
| 631 | - }) | ||
| 632 | - } | ||
| 633 | - }, | ||
| 634 | - updateHalfChecked(index) { | ||
| 635 | - const _parentId = this.treeList[index].parentId || []; | ||
| 636 | - const parentId = _parentId.concat([]).reverse(); | ||
| 637 | - if (parentId && parentId.length) { | ||
| 638 | - parentId.map(id => { | ||
| 639 | - const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id); | ||
| 640 | - const childrenIds = (parentTreeDataItem[this.childrenKey] || []).map(item => item[this.valueKey]); | 621 | + const _bool = this.treeList |
| 622 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 623 | + .every(it => it.checked === false); | ||
| 641 | 624 | ||
| 642 | - const bool = this.treeList | ||
| 643 | - .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 644 | - .every(it => it.checked === false && it.halfChecked === false); | 625 | + const parentItem = this.treeList.find(it => it.id === id); |
| 626 | + if (parentItem) { | ||
| 627 | + if (this.checkStrictlyModel === 'weak') { | ||
| 628 | + if (bool && !parentItem.disabled) { | ||
| 629 | + parentItem.checked = true; | ||
| 630 | + } else if (_bool && !parentItem.disabled) { | ||
| 631 | + parentItem.checked = false; | ||
| 632 | + } | ||
| 633 | + } else if (this.checkStrictlyModel === 'strong') { | ||
| 634 | + if (bool) { | ||
| 635 | + parentItem.checked = true; | ||
| 636 | + } else { | ||
| 637 | + parentItem.checked = false; | ||
| 638 | + } | ||
| 639 | + } | ||
| 640 | + } | ||
| 641 | + }) | ||
| 642 | + } | ||
| 643 | + }, | ||
| 644 | + updateHalfChecked(index) { | ||
| 645 | + const _parentId = this.treeList[index].parentId || []; | ||
| 646 | + const parentId = _parentId.concat([]).reverse(); | ||
| 647 | + if (parentId && parentId.length) { | ||
| 648 | + parentId.map(id => { | ||
| 649 | + const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id); | ||
| 650 | + // 添加安全检查:确保parentTreeDataItem和childrenKey存在 | ||
| 651 | + const children = parentTreeDataItem && parentTreeDataItem[this.childrenKey]; | ||
| 652 | + if (!Array.isArray(children)) return; | ||
| 645 | 653 | ||
| 646 | - const _bool = this.treeList | ||
| 647 | - .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 648 | - .some(it => it.checked === true || it.halfChecked === true); | 654 | + const childrenIds = children.map(item => item[this.valueKey]); |
| 649 | 655 | ||
| 650 | - const parentItem = this.treeList.find(it => it.id === id); | ||
| 651 | - if (parentItem) { | ||
| 652 | - if (!parentItem.checked) { | ||
| 653 | - if (bool) { | ||
| 654 | - parentItem.halfChecked = false | ||
| 655 | - } else if (_bool) { | ||
| 656 | - parentItem.halfChecked = true | ||
| 657 | - } else { | ||
| 658 | - parentItem.halfChecked = false | ||
| 659 | - } | ||
| 660 | - } | ||
| 661 | - } | ||
| 662 | - }) | ||
| 663 | - } | ||
| 664 | - if (this.treeList[index].checked == false) { | ||
| 665 | - const source = this.treeList[index].source || {}; | ||
| 666 | - const children = source[this.childrenKey] || []; | ||
| 667 | - const checkedKeyList = this.getChildrenKeys(children); | ||
| 668 | - const bool = this.treeList.filter(item => checkedKeyList.indexOf(item.id) !== -1).some(item => item.checked); | ||
| 669 | - if (bool) { | ||
| 670 | - this.treeList[index].halfChecked = true; | ||
| 671 | - } | ||
| 672 | - } | ||
| 673 | - }, | 656 | + const bool = this.treeList |
| 657 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 658 | + .every(it => it.checked === false && it.halfChecked === false); | ||
| 659 | + | ||
| 660 | + const _bool = this.treeList | ||
| 661 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | ||
| 662 | + .some(it => it.checked === true || it.halfChecked === true); | ||
| 663 | + | ||
| 664 | + const parentItem = this.treeList.find(it => it.id === id); | ||
| 665 | + if (parentItem) { | ||
| 666 | + if (!parentItem.checked) { | ||
| 667 | + if (bool) { | ||
| 668 | + parentItem.halfChecked = false | ||
| 669 | + } else if (_bool) { | ||
| 670 | + parentItem.halfChecked = true | ||
| 671 | + } else { | ||
| 672 | + parentItem.halfChecked = false | ||
| 673 | + } | ||
| 674 | + } | ||
| 675 | + } | ||
| 676 | + }) | ||
| 677 | + } | ||
| 678 | + if (this.treeList[index].checked == false) { | ||
| 679 | + const source = this.treeList[index].source || {}; | ||
| 680 | + const children = source[this.childrenKey] || []; | ||
| 681 | + const checkedKeyList = this.getChildrenKeys(children); | ||
| 682 | + const bool = this.treeList.filter(item => checkedKeyList.indexOf(item.id) !== -1).some(item => item.checked); | ||
| 683 | + if (bool) { | ||
| 684 | + this.treeList[index].halfChecked = true; | ||
| 685 | + } | ||
| 686 | + } | ||
| 687 | + }, | ||
| 674 | showHalfChecked(item) { | 688 | showHalfChecked(item) { |
| 675 | if (this.multiple && !this.checkStrictly && item.halfChecked === true) { | 689 | if (this.multiple && !this.checkStrictly && item.halfChecked === true) { |
| 676 | return true | 690 | return true |
| @@ -678,16 +692,19 @@ export default { | @@ -678,16 +692,19 @@ export default { | ||
| 678 | return false | 692 | return false |
| 679 | } | 693 | } |
| 680 | }, | 694 | }, |
| 681 | - getChildrenKeys(children) { | ||
| 682 | - let keys = []; | ||
| 683 | - (children || []).map(item => { | ||
| 684 | - keys.push(item[this.valueKey]) | ||
| 685 | - if (item[this.childrenKey] && item[this.childrenKey].length) { | ||
| 686 | - keys = keys.concat(this.getChildrenKeys(item[this.childrenKey])) | ||
| 687 | - } | ||
| 688 | - }) | ||
| 689 | - return keys | ||
| 690 | - }, | 695 | + getChildrenKeys(children) { |
| 696 | + let keys = []; | ||
| 697 | + (children || []).map(item => { | ||
| 698 | + // 添加安全检查:确保item和valueKey存在 | ||
| 699 | + if (item && item[this.valueKey]) { | ||
| 700 | + keys.push(item[this.valueKey]) | ||
| 701 | + if (item[this.childrenKey] && Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length) { | ||
| 702 | + keys = keys.concat(this.getChildrenKeys(item[this.childrenKey])) | ||
| 703 | + } | ||
| 704 | + } | ||
| 705 | + }) | ||
| 706 | + return keys | ||
| 707 | + }, | ||
| 691 | // 处理单选多选 | 708 | // 处理单选多选 |
| 692 | _fixMultiple(index) { | 709 | _fixMultiple(index) { |
| 693 | if (!this.multiple) { | 710 | if (!this.multiple) { |
garbage-removal/src/pages/home-info/clean/index.vue
| @@ -619,7 +619,6 @@ | @@ -619,7 +619,6 @@ | ||
| 619 | console.log("----------------------->5"); | 619 | console.log("----------------------->5"); |
| 620 | if (!validateParams(params)) { | 620 | if (!validateParams(params)) { |
| 621 | console.log("未通过", params); | 621 | console.log("未通过", params); |
| 622 | - | ||
| 623 | return; | 622 | return; |
| 624 | } | 623 | } |
| 625 | 624 |
garbage-removal/src/pages/order-info/order-disposal/scan-detail/index.vue
| @@ -97,7 +97,8 @@ | @@ -97,7 +97,8 @@ | ||
| 97 | import { | 97 | import { |
| 98 | askTransport, | 98 | askTransport, |
| 99 | scanDetail, | 99 | scanDetail, |
| 100 | - queryMileage | 100 | + queryMileage, |
| 101 | + queryLatitudeLongitude | ||
| 101 | } from '@/apis/order.js'; | 102 | } from '@/apis/order.js'; |
| 102 | import { | 103 | import { |
| 103 | onLoad | 104 | onLoad |
| @@ -158,59 +159,47 @@ | @@ -158,59 +159,47 @@ | ||
| 158 | const mileageData = JSON.parse(res.data.data); | 159 | const mileageData = JSON.parse(res.data.data); |
| 159 | details.value.transportDistance = mileageData.mileage+ ' 公里'; // 米转公里 | 160 | details.value.transportDistance = mileageData.mileage+ ' 公里'; // 米转公里 |
| 160 | 161 | ||
| 161 | - // 使用接口返回的定位信息 | ||
| 162 | - if (mileageData.endLatitude && mileageData.endLongitude) { | ||
| 163 | - location.value = { | ||
| 164 | - latitude: mileageData.endLatitude, | ||
| 165 | - longitude: mileageData.endLongitude | ||
| 166 | - }; | ||
| 167 | - } else { | ||
| 168 | - // 当接口返回的定位信息为空时,调用手机定位 | ||
| 169 | - console.log("接口返回的定位信息为空,尝试获取手机定位"); | ||
| 170 | - details.value.transportDistance = "1 公里"; | ||
| 171 | - getPhoneLocation(); | ||
| 172 | - } | 162 | + // 统一使用车辆实时定位接口(避免不同接口返回坐标差异) |
| 163 | + await getLocationFromApi(); | ||
| 173 | } else { | 164 | } else { |
| 174 | console.log("获取运距失败:" + res.data.msg); | 165 | console.log("获取运距失败:" + res.data.msg); |
| 175 | - // 运距获取失败时,尝试获取手机定位 | 166 | + // 运距获取失败时,同样使用车辆实时定位接口 |
| 176 | details.value.transportDistance = "1 公里"; | 167 | details.value.transportDistance = "1 公里"; |
| 177 | - getPhoneLocation(); | 168 | + await getLocationFromApi(); |
| 178 | } | 169 | } |
| 179 | } catch (error) { | 170 | } catch (error) { |
| 180 | console.error("调用运距接口出错:", error); | 171 | console.error("调用运距接口出错:", error); |
| 181 | details.value.transportDistance = "1 公里"; | 172 | details.value.transportDistance = "1 公里"; |
| 182 | - // 接口调用异常时,尝试获取手机定位 | ||
| 183 | - getPhoneLocation(); | 173 | + // 接口调用异常时,改为获取车辆实时定位 |
| 174 | + await getLocationFromApi(); | ||
| 184 | } | 175 | } |
| 185 | }; | 176 | }; |
| 186 | 177 | ||
| 187 | - const getPhoneLocation = () => { | ||
| 188 | - // 设置5秒超时 | ||
| 189 | - const timeout = setTimeout(() => { | ||
| 190 | - uni.$u.toast('获取手机定位超时,请检查定位权限'); | ||
| 191 | - }, 5000); | ||
| 192 | - | ||
| 193 | - // 调用uni.getLocation获取手机GPS定位 | ||
| 194 | - uni.getLocation({ | ||
| 195 | - type: 'gcj02', | ||
| 196 | - success: (res) => { | ||
| 197 | - clearTimeout(timeout); | ||
| 198 | - console.log('手机定位获取成功', res); | ||
| 199 | - location.value = { | ||
| 200 | - latitude: res.latitude, | ||
| 201 | - longitude: res.longitude | ||
| 202 | - }; | ||
| 203 | - uni.$u.toast('手机定位获取成功'); | ||
| 204 | - }, | ||
| 205 | - fail: (err) => { | ||
| 206 | - clearTimeout(timeout); | ||
| 207 | - console.error('手机定位获取失败', err); | ||
| 208 | - uni.$u.toast('获取手机定位失败,请检查定位权限'); | ||
| 209 | - }, | ||
| 210 | - complete: () => { | ||
| 211 | - clearTimeout(timeout); | 178 | + // 通过接口获取车辆实时定位(coordinates 由后端/车辆服务统一口径) |
| 179 | + const getLocationFromApi = async () => { | ||
| 180 | + const carNo = details.value?.garHandlerCarCode; | ||
| 181 | + if (!carNo) return; | ||
| 182 | + | ||
| 183 | + try { | ||
| 184 | + const res = await queryLatitudeLongitude(carNo); | ||
| 185 | + if (res?.data?.success) { | ||
| 186 | + const data = res.data.data || {}; | ||
| 187 | + if (typeof data.latitude !== "undefined" && typeof data.longitude !== "undefined") { | ||
| 188 | + location.value = { | ||
| 189 | + latitude: data.latitude, | ||
| 190 | + longitude: data.longitude | ||
| 191 | + }; | ||
| 192 | + uni.$u.toast("车辆位置获取成功"); | ||
| 193 | + } else { | ||
| 194 | + uni.$u.toast("车辆位置返回为空"); | ||
| 195 | + } | ||
| 196 | + } else { | ||
| 197 | + uni.$u.toast("车辆位置获取失败"); | ||
| 212 | } | 198 | } |
| 213 | - }); | 199 | + } catch (err) { |
| 200 | + console.error("获取车辆位置失败:", err); | ||
| 201 | + uni.$u.toast("车辆位置获取异常"); | ||
| 202 | + } | ||
| 214 | }; | 203 | }; |
| 215 | 204 | ||
| 216 | 205 |
garbage-removal/src/pages/order-info/order-driver/detail/guest/index.vue
| @@ -144,7 +144,7 @@ | @@ -144,7 +144,7 @@ | ||
| 144 | <text class=" order-detail-container-header-title">装车照片:</text> | 144 | <text class=" order-detail-container-header-title">装车照片:</text> |
| 145 | 145 | ||
| 146 | <view class="order-detail-container-header-content" style="flex-direction: column;"> | 146 | <view class="order-detail-container-header-content" style="flex-direction: column;"> |
| 147 | - <view v-for="group in putOnImagesGrouped" :key="group.index" class="image-group"> | 147 | + <view v-for="group in putOnImages" :key="group.index" class="image-group"> |
| 148 | <view class="image-group-header"> | 148 | <view class="image-group-header"> |
| 149 | <view class="image-group-title">{{ group.carName}}第 {{ group.index }} 趟</view> | 149 | <view class="image-group-title">{{ group.carName}}第 {{ group.index }} 趟</view> |
| 150 | <!-- 根据group.index与真实发车数比较显示状态 --> | 150 | <!-- 根据group.index与真实发车数比较显示状态 --> |
garbage-removal/src/pages/order-info/order-driver/detail/index.vue
| @@ -19,12 +19,12 @@ | @@ -19,12 +19,12 @@ | ||
| 19 | 订单信息 | 19 | 订单信息 |
| 20 | </view> | 20 | </view> |
| 21 | <view class="order-detail-container-header-item" | 21 | <view class="order-detail-container-header-item" |
| 22 | - @click.stop="handlerJumpOtherApp(dataGram.garOrderAddress + dataGram.garOrderAddressDetails)"> | ||
| 23 | - <text class="order-detail-container-header-title">清运地点:</text> | ||
| 24 | - <view class="order-detail-container-header-content" style="text-decoration: underline"> | ||
| 25 | - <text selectable='true'>{{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }}</text> | ||
| 26 | - </view> | 22 | + @click.stop="showNavDialog(dataGram.garLongitude,dataGram.garLatitude, dataGram.garOrderAddressDetails)"> |
| 23 | + <text class="order-detail-container-header-title">清运地点:</text> | ||
| 24 | + <view class="order-detail-container-header-content" style="text-decoration: underline"> | ||
| 25 | + <text selectable='true'>{{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }}</text> | ||
| 27 | </view> | 26 | </view> |
| 27 | + </view> | ||
| 28 | <view class="order-detail-container-header-item"> | 28 | <view class="order-detail-container-header-item"> |
| 29 | <text class="order-detail-container-header-title">现场图片:</text> | 29 | <text class="order-detail-container-header-title">现场图片:</text> |
| 30 | <view class="order-detail-container-header-content"> | 30 | <view class="order-detail-container-header-content"> |
| @@ -57,7 +57,7 @@ | @@ -57,7 +57,7 @@ | ||
| 57 | </view> | 57 | </view> |
| 58 | </view> | 58 | </view> |
| 59 | 59 | ||
| 60 | - | 60 | + |
| 61 | <view class="order-detail-container-header-item"> | 61 | <view class="order-detail-container-header-item"> |
| 62 | <text class="order-detail-container-header-title">订单号:</text> | 62 | <text class="order-detail-container-header-title">订单号:</text> |
| 63 | <view class="order-detail-container-header-content"> | 63 | <view class="order-detail-container-header-content"> |
| @@ -448,10 +448,37 @@ const handleContactClick = (val) => { | @@ -448,10 +448,37 @@ const handleContactClick = (val) => { | ||
| 448 | }).catch(err => { }); | 448 | }).catch(err => { }); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | -const handlerJumpOtherApp = (locationName) => { | ||
| 452 | - // 方案一:使用腾讯地图URI API(推荐) | ||
| 453 | - // 构建腾讯地图搜索链接,使用更完整的参数 | ||
| 454 | - window.location.href =`https://apis.map.qq.com/uri/v1/search?keyword=${encodeURIComponent(locationName)}®ion=${encodeURIComponent(locationName)}&referer=XICBZ-ALWKT-2KPXZ-VCBL7-XMRYO-2QFS4&policy=1`; | 451 | +const showNavDialog = (longitude, latitude, locationName) => { |
| 452 | + // 校验经纬度有效性 | ||
| 453 | + if (!longitude || !latitude) { | ||
| 454 | + uni.$u.toast('暂无有效导航坐标'); | ||
| 455 | + return; | ||
| 456 | + } | ||
| 457 | + | ||
| 458 | + uni.showActionSheet({ | ||
| 459 | + itemList: ['高德导航', '百度导航'], | ||
| 460 | + success: function (res) { | ||
| 461 | + if (res.tapIndex === 0) { | ||
| 462 | + // 调用你原来的高德导航方法 | ||
| 463 | + handlerJumpGaoDeApp(longitude, latitude, locationName); | ||
| 464 | + } else if (res.tapIndex === 1) { | ||
| 465 | + // 调用你原来的百度导航方法 | ||
| 466 | + handlerJumpBaiDuApp(longitude, latitude, locationName); | ||
| 467 | + } | ||
| 468 | + }, | ||
| 469 | + fail: function (res) { | ||
| 470 | + console.log('取消导航选择:', res.errMsg); | ||
| 471 | + } | ||
| 472 | + }); | ||
| 473 | +}; | ||
| 474 | +// ===== 新增结束 ===== | ||
| 475 | + | ||
| 476 | +const handlerJumpGaoDeApp = (longitude,latitude,locationName) => { | ||
| 477 | + window.location.href =`https://uri.amap.com/marker?position=${longitude},${latitude}&name=${locationName}`; | ||
| 478 | +} | ||
| 479 | + | ||
| 480 | +const handlerJumpBaiDuApp = (longitude,latitude,locationName) => { | ||
| 481 | + window.location.href =`http://api.map.baidu.com/marker?location=${longitude},${latitude}&title=${locationName}&output=html`; | ||
| 455 | } | 482 | } |
| 456 | 483 | ||
| 457 | 484 |
garbage-removal/src/pages/order-info/order-other/detail/index.vue
| @@ -73,7 +73,7 @@ | @@ -73,7 +73,7 @@ | ||
| 73 | <u-icon name="map" size="16" color="#19a97c" style="margin-right: 8rpx;"></u-icon> | 73 | <u-icon name="map" size="16" color="#19a97c" style="margin-right: 8rpx;"></u-icon> |
| 74 | <text>清运地点:</text> | 74 | <text>清运地点:</text> |
| 75 | </view> | 75 | </view> |
| 76 | - <view class="info-content" @click.stop="handlerJumpOtherApp(dataGram.garLatitude, dataGram.garLongitude, dataGram.garCoordinate)"> | 76 | + <view class="info-content" @click.stop="showNavDialog(dataGram.garLongitude,dataGram.garLatitude, dataGram.garOrderAddressDetails)"> |
| 77 | <text class="content-text" selectable='true'>{{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }}</text> | 77 | <text class="content-text" selectable='true'>{{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }}</text> |
| 78 | </view> | 78 | </view> |
| 79 | </view> | 79 | </view> |
| @@ -941,20 +941,84 @@ const handleOrderDispatchClick = (orderId) => { | @@ -941,20 +941,84 @@ const handleOrderDispatchClick = (orderId) => { | ||
| 941 | // 获取订单车辆数量 | 941 | // 获取订单车辆数量 |
| 942 | const orderCarCount = dataGram.value?.garCarInfoList?.length || 0; | 942 | const orderCarCount = dataGram.value?.garCarInfoList?.length || 0; |
| 943 | 943 | ||
| 944 | - // 获取驾驶员人员 | ||
| 945 | - queryOrderDispatch(orderId).then(res => { | ||
| 946 | - console.log(res.data.data); | ||
| 947 | - if (res.data.success) { | ||
| 948 | - // 过滤车辆 非用户选择的车辆无法选中 | ||
| 949 | - driverPersonnelList.value = res.data.data; | ||
| 950 | - // 恢复原始的open调用方式,只传递dataList | ||
| 951 | - clashDriverDispatchRef.value.open(res.data.data); | ||
| 952 | - refreshOrderData() | ||
| 953 | - } else { | ||
| 954 | - uni.$u.toast("驾驶员分配成功!"); | ||
| 955 | - refreshOrderData() | 944 | + // 在调用API前验证token有效性 |
| 945 | + const validateTokenAndCallAPI = async () => { | ||
| 946 | + try { | ||
| 947 | + // 检查当前token是否存在 | ||
| 948 | + if (!store.token) { | ||
| 949 | + uni.$u.toast("登录已过期,请重新登录"); | ||
| 950 | + // 跳转到登录页面 | ||
| 951 | + uni.reLaunch({ | ||
| 952 | + url: "/pages/login/code", | ||
| 953 | + }); | ||
| 954 | + return; | ||
| 955 | + } | ||
| 956 | + | ||
| 957 | + // 获取驾驶员人员 - 添加时间戳避免缓存 | ||
| 958 | + const timestamp = new Date().getTime(); | ||
| 959 | + | ||
| 960 | + // 添加重试机制 | ||
| 961 | + let retryCount = 0; | ||
| 962 | + const maxRetries = 2; | ||
| 963 | + | ||
| 964 | + const attemptRequest = async () => { | ||
| 965 | + try { | ||
| 966 | + const res = await queryOrderDispatch(`${orderId}?t=${timestamp}`); | ||
| 967 | + | ||
| 968 | + if (res.data.success) { | ||
| 969 | + // 过滤车辆 非用户选择的车辆无法选中 | ||
| 970 | + driverPersonnelList.value = res.data.data; | ||
| 971 | + // 恢复原始的open调用方式,只传递dataList | ||
| 972 | + clashDriverDispatchRef.value.open(res.data.data); | ||
| 973 | + refreshOrderData(); | ||
| 974 | + } else { | ||
| 975 | + uni.$u.toast("驾驶员分配成功!"); | ||
| 976 | + refreshOrderData(); | ||
| 977 | + } | ||
| 978 | + } catch (error) { | ||
| 979 | + console.error('获取驾驶员信息失败:', error); | ||
| 980 | + | ||
| 981 | + // 检查是否是token相关错误 | ||
| 982 | + if (error.response && (error.response.status === 401 || error.response.status === 403)) { | ||
| 983 | + retryCount++; | ||
| 984 | + | ||
| 985 | + if (retryCount <= maxRetries) { | ||
| 986 | + console.log(`token可能已过期,正在进行第${retryCount}次重试`); | ||
| 987 | + | ||
| 988 | + // 清除当前token | ||
| 989 | + store.token = null; | ||
| 990 | + setRequestToken(null); | ||
| 991 | + uni.removeStorageSync("Authorization"); | ||
| 992 | + | ||
| 993 | + // 跳转重新登录 | ||
| 994 | + uni.$u.toast("登录已过期,请重新登录"); | ||
| 995 | + setTimeout(() => { | ||
| 996 | + uni.reLaunch({ | ||
| 997 | + url: "/pages/login/code", | ||
| 998 | + }); | ||
| 999 | + }, 1500); | ||
| 1000 | + return; | ||
| 1001 | + } | ||
| 1002 | + } | ||
| 1003 | + | ||
| 1004 | + // 其他错误或重试次数用完 | ||
| 1005 | + uni.$u.toast("获取驾驶员信息失败,请稍后重试"); | ||
| 1006 | + } | ||
| 1007 | + }; | ||
| 1008 | + | ||
| 1009 | + await attemptRequest(); | ||
| 1010 | + | ||
| 1011 | + } catch (error) { | ||
| 1012 | + console.error('验证token时发生错误:', error); | ||
| 1013 | + uni.$u.toast("系统错误,请重新登录"); | ||
| 1014 | + uni.reLaunch({ | ||
| 1015 | + url: "/pages/login/code", | ||
| 1016 | + }); | ||
| 956 | } | 1017 | } |
| 957 | - }) | 1018 | + }; |
| 1019 | + | ||
| 1020 | + // 执行验证和API调用 | ||
| 1021 | + validateTokenAndCallAPI(); | ||
| 958 | } | 1022 | } |
| 959 | const handleDisposalDispatchClick = (orderId) => { | 1023 | const handleDisposalDispatchClick = (orderId) => { |
| 960 | // 获取处置场所人员 | 1024 | // 获取处置场所人员 |
| @@ -1575,6 +1639,39 @@ const submitUpdateCarInfo = () => { | @@ -1575,6 +1639,39 @@ const submitUpdateCarInfo = () => { | ||
| 1575 | }) | 1639 | }) |
| 1576 | } | 1640 | } |
| 1577 | 1641 | ||
| 1642 | +const showNavDialog = (longitude, latitude, locationName) => { | ||
| 1643 | + // 校验经纬度有效性 | ||
| 1644 | + if (!longitude || !latitude) { | ||
| 1645 | + uni.$u.toast('暂无有效导航坐标'); | ||
| 1646 | + return; | ||
| 1647 | + } | ||
| 1648 | + | ||
| 1649 | + uni.showActionSheet({ | ||
| 1650 | + itemList: ['高德导航', '百度导航'], | ||
| 1651 | + success: function (res) { | ||
| 1652 | + if (res.tapIndex === 0) { | ||
| 1653 | + // 调用你原来的高德导航方法 | ||
| 1654 | + handlerJumpGaoDeApp(longitude, latitude, locationName); | ||
| 1655 | + } else if (res.tapIndex === 1) { | ||
| 1656 | + // 调用你原来的百度导航方法 | ||
| 1657 | + handlerJumpBaiDuApp(longitude, latitude, locationName); | ||
| 1658 | + } | ||
| 1659 | + }, | ||
| 1660 | + fail: function (res) { | ||
| 1661 | + console.log('取消导航选择:', res.errMsg); | ||
| 1662 | + } | ||
| 1663 | + }); | ||
| 1664 | +}; | ||
| 1665 | +// ===== 新增结束 ===== | ||
| 1666 | + | ||
| 1667 | +const handlerJumpGaoDeApp = (longitude,latitude,locationName) => { | ||
| 1668 | + window.location.href =`https://uri.amap.com/marker?position=${longitude},${latitude}&name=${locationName}`; | ||
| 1669 | +} | ||
| 1670 | + | ||
| 1671 | +const handlerJumpBaiDuApp = (longitude,latitude,locationName) => { | ||
| 1672 | + window.location.href =`http://api.map.baidu.com/marker?location=${longitude},${latitude}&title=${locationName}&output=html`; | ||
| 1673 | +} | ||
| 1674 | + | ||
| 1578 | 1675 | ||
| 1579 | const deleteHandler = (handler) => { | 1676 | const deleteHandler = (handler) => { |
| 1580 | uni.showModal({ | 1677 | uni.showModal({ |
garbage-removal/src/pages/order/order-disposal/index.vue
| 1 | <template> | 1 | <template> |
| 2 | - <view class="order-container"> | ||
| 3 | - <!-- #ifdef H5 --> | ||
| 4 | - <z-paging-swiper :fixed="false"> | ||
| 5 | - <!-- #endif --> | ||
| 6 | - <!-- #ifdef MP-WEIXIN --> | ||
| 7 | - <z-paging-swiper> | ||
| 8 | - <!-- #endif --> | ||
| 9 | - <template v-slot:top> | ||
| 10 | - <view class="header-box" :style="{ | 2 | + <view class="order-container"> |
| 3 | + <!-- #ifdef H5 --> | ||
| 4 | + <z-paging-swiper :fixed="false"> | ||
| 5 | + <!-- #endif --> | ||
| 6 | + <!-- #ifdef MP-WEIXIN --> | ||
| 7 | + <z-paging-swiper> | ||
| 8 | + <!-- #endif --> | ||
| 9 | + <template v-slot:top> | ||
| 10 | + <view class="header-box" :style="{ | ||
| 11 | 'height': lightHeight, 'line-height': lightHeight, | 11 | 'height': lightHeight, 'line-height': lightHeight, |
| 12 | 'padding-top': topMargin | 12 | 'padding-top': topMargin |
| 13 | } | 13 | } |
| 14 | "> | 14 | "> |
| 15 | - <view class="header-box-left-message"> | ||
| 16 | - | ||
| 17 | - </view> | ||
| 18 | - <view class="header-box-title"> | ||
| 19 | - {{ title }} | ||
| 20 | - </view> | ||
| 21 | - </view> | ||
| 22 | - <u-tabs lineWidth=" 40" lineColor="#ffffff" lineHeight="6" | ||
| 23 | - :activeStyle="{ 'color': '#ffffff', 'font-weight': 'bolder' }" | ||
| 24 | - :inactiveStyle="{ color: '#ffffff' }" ref="uTabsElement" :list="displayList" :current="current" | ||
| 25 | - @change="tabsChange" :scrollable="false"></u-tabs> | ||
| 26 | - </template> | ||
| 27 | - | ||
| 28 | - <swiper class="swiper" :current="swiperCurrent" @translation="translation" | ||
| 29 | - @animationfinish="animationfinish"> | ||
| 30 | - <swiper-item class="swiper-item" v-for="( item, index ) in list " :key="index"> | ||
| 31 | - <swiper-list-item :tabIndex="index" :currentIndex="swiperCurrent"></swiper-list-item> | ||
| 32 | - </swiper-item> | ||
| 33 | - </swiper> | ||
| 34 | - | ||
| 35 | - </z-paging-swiper> | ||
| 36 | - | ||
| 37 | - </view> | ||
| 38 | - <view class="scan-box"> | 15 | + <view class="header-box-left-message"> |
| 16 | + | ||
| 17 | + </view> | ||
| 18 | + <view class="header-box-title"> | ||
| 19 | + {{ title }} | ||
| 20 | + </view> | ||
| 21 | + </view> | ||
| 22 | + <u-tabs lineWidth=" 40" lineColor="#ffffff" lineHeight="6" | ||
| 23 | + :activeStyle="{ 'color': '#ffffff', 'font-weight': 'bolder' }" | ||
| 24 | + :inactiveStyle="{ color: '#ffffff' }" ref="uTabsElement" :list="displayList" :current="current" | ||
| 25 | + @change="tabsChange" :scrollable="false"></u-tabs> | ||
| 26 | + </template> | ||
| 27 | + | ||
| 28 | + <swiper class="swiper" :current="swiperCurrent" @translation="translation" | ||
| 29 | + @animationfinish="animationfinish"> | ||
| 30 | + <swiper-item class="swiper-item" v-for="( item, index ) in list " :key="index"> | ||
| 31 | + <swiper-list-item :tabIndex="index" :currentIndex="swiperCurrent"></swiper-list-item> | ||
| 32 | + </swiper-item> | ||
| 33 | + </swiper> | ||
| 34 | + | ||
| 35 | + </z-paging-swiper> | ||
| 36 | + | ||
| 37 | + </view> | ||
| 38 | + <view class="scan-box"> | ||
| 39 | <view class="scan-tip">在此处扫码</view> | 39 | <view class="scan-tip">在此处扫码</view> |
| 40 | - <view class="scan-btn"> | ||
| 41 | - <view class="scan-icon"> | ||
| 42 | - <!-- #ifdef H5 --> | ||
| 43 | - <u-icon @click="handleScanH5" name="scan" :size="180" color="#fff"></u-icon> | ||
| 44 | - <!-- #endif --> | ||
| 45 | - </view> | ||
| 46 | - </view> | ||
| 47 | - </view> | ||
| 48 | - <QrScannerVue v-if="showScan" @decode="onDecodeHandler" @close="qrReaderClose" /> | 40 | + <view class="scan-btn"> |
| 41 | + <view class="scan-icon"> | ||
| 42 | + <!-- #ifdef H5 --> | ||
| 43 | + <u-icon @click="handleScanH5" name="scan" :size="180" color="#fff"></u-icon> | ||
| 44 | + <!-- #endif --> | ||
| 45 | + </view> | ||
| 46 | + </view> | ||
| 47 | + </view> | ||
| 48 | + <QrScannerVue v-if="showScan" @decode="onDecodeHandler" @close="qrReaderClose" /> | ||
| 49 | </template> | 49 | </template> |
| 50 | 50 | ||
| 51 | <script setup> | 51 | <script setup> |
| @@ -115,7 +115,7 @@ const handleScan = () => { | @@ -115,7 +115,7 @@ const handleScan = () => { | ||
| 115 | url: `pages/order-info/order-disposal/scan-detail/index`, | 115 | url: `pages/order-info/order-disposal/scan-detail/index`, |
| 116 | params: { | 116 | params: { |
| 117 | data: encodeURIComponent(JSON.stringify(res.data | 117 | data: encodeURIComponent(JSON.stringify(res.data |
| 118 | - .data)) | 118 | + .data)) |
| 119 | } | 119 | } |
| 120 | }) | 120 | }) |
| 121 | return | 121 | return |
| @@ -134,29 +134,36 @@ const handleScan = () => { | @@ -134,29 +134,36 @@ const handleScan = () => { | ||
| 134 | } | 134 | } |
| 135 | }); | 135 | }); |
| 136 | } | 136 | } |
| 137 | -const takeLocation = () => { | ||
| 138 | - window.JsInterface.takeLocation(); | ||
| 139 | -} | ||
| 140 | - | ||
| 141 | -// 接收定位结果的回调函数 | ||
| 142 | -const takeLocalCallBack = (lngLat) => { | ||
| 143 | - const ll = lngLat.split(","); | ||
| 144 | - location.value = { | ||
| 145 | - longitude: ll[0], | ||
| 146 | - latitude: ll[1] | ||
| 147 | - }; | ||
| 148 | -} | ||
| 149 | - | ||
| 150 | -// 设置全局回调 | ||
| 151 | -onMounted(() => { | ||
| 152 | - window.takeLocationCallBack = takeLocalCallBack | ||
| 153 | -}) | ||
| 154 | - | ||
| 155 | -onLoad((options) => { | ||
| 156 | - // 获取定位信息 | ||
| 157 | - takeLocation(); | ||
| 158 | -}); | ||
| 159 | 137 | ||
| 138 | +// 获取手机定位(GCJ-02 坐标系) | ||
| 139 | +const getPhoneLocation = () => { | ||
| 140 | + // 设置 5 秒超时 | ||
| 141 | + const timeout = setTimeout(() => { | ||
| 142 | + uni.$u.toast('获取手机定位超时,请检查定位权限'); | ||
| 143 | + }, 5000); | ||
| 144 | + | ||
| 145 | + // 调用 uni.getLocation 获取手机 GPS 定位 | ||
| 146 | + uni.getLocation({ | ||
| 147 | + type: 'gcj02', | ||
| 148 | + success: (res) => { | ||
| 149 | + clearTimeout(timeout); | ||
| 150 | + console.log('手机定位获取成功', res); | ||
| 151 | + location.value = { | ||
| 152 | + latitude: res.latitude, | ||
| 153 | + longitude: res.longitude | ||
| 154 | + }; | ||
| 155 | + console.log('定位信息:', location.value); | ||
| 156 | + }, | ||
| 157 | + fail: (err) => { | ||
| 158 | + clearTimeout(timeout); | ||
| 159 | + console.error('手机定位获取失败', err); | ||
| 160 | + uni.$u.toast('获取手机定位失败,请检查定位权限'); | ||
| 161 | + }, | ||
| 162 | + complete: () => { | ||
| 163 | + clearTimeout(timeout); | ||
| 164 | + } | ||
| 165 | + }); | ||
| 166 | +}; | ||
| 160 | 167 | ||
| 161 | const handleScanH5 = async () => { | 168 | const handleScanH5 = async () => { |
| 162 | showScan.value = true; | 169 | showScan.value = true; |
| @@ -174,9 +181,9 @@ const handleScanH5 = async () => { | @@ -174,9 +181,9 @@ const handleScanH5 = async () => { | ||
| 174 | // if (error.message.includes("用户拒绝")) { | 181 | // if (error.message.includes("用户拒绝")) { |
| 175 | // uni.$u.toast("请允许访问位置信息以验证卸货地址"); | 182 | // uni.$u.toast("请允许访问位置信息以验证卸货地址"); |
| 176 | // } else if (error.message.includes("安全来源")) { | 183 | // } else if (error.message.includes("安全来源")) { |
| 177 | - // uni.$u.toast("当前环境不支持位置验证,请使用HTTPS访问"); | 184 | + // uni.$u.toast("当前环境不支持位置验证,请使用 HTTPS 访问"); |
| 178 | // } else { | 185 | // } else { |
| 179 | - // uni.$u.toast("位置验证失败: " + error.message); | 186 | + // uni.$u.toast("位置验证失败:" + error.message); |
| 180 | // } | 187 | // } |
| 181 | // } | 188 | // } |
| 182 | } | 189 | } |
| @@ -199,7 +206,7 @@ const validateUnloadingSite = async (location) => { | @@ -199,7 +206,7 @@ const validateUnloadingSite = async (location) => { | ||
| 199 | site.garLongitude // 使用 garLongitude | 206 | site.garLongitude // 使用 garLongitude |
| 200 | ); | 207 | ); |
| 201 | console.log(distance) | 208 | console.log(distance) |
| 202 | - return distance <= 200; // 200米范围内 | 209 | + return distance <= 200; // 200 米范围内 |
| 203 | }); | 210 | }); |
| 204 | } catch (error) { | 211 | } catch (error) { |
| 205 | console.error('验证卸货地址失败:', error); | 212 | console.error('验证卸货地址失败:', error); |
| @@ -221,26 +228,26 @@ const calculateDistance = (lat1, lng1, lat2, lng2) => { | @@ -221,26 +228,26 @@ const calculateDistance = (lat1, lng1, lat2, lng2) => { | ||
| 221 | ) | 228 | ) |
| 222 | ); | 229 | ); |
| 223 | 230 | ||
| 224 | - return distance * 6371000; // 地球半径(米) | 231 | + return distance * 6371000; // 地球半径 (米) |
| 225 | } | 232 | } |
| 226 | 233 | ||
| 227 | const onDecodeHandler = (data) => { | 234 | const onDecodeHandler = (data) => { |
| 228 | showScan.value = false | 235 | showScan.value = false |
| 229 | try { | 236 | try { |
| 230 | - checkCode(data).then(res => { | ||
| 231 | - console.log(res); | ||
| 232 | - if (res.data.code == 200) { | ||
| 233 | - uni.$u.route({ | ||
| 234 | - url: `pages/order-info/order-disposal/scan-detail/index`, | ||
| 235 | - params: { | ||
| 236 | - data: encodeURIComponent(JSON.stringify(res.data | ||
| 237 | - .data)) | ||
| 238 | - } | ||
| 239 | - }) | ||
| 240 | - return | ||
| 241 | - } | ||
| 242 | - alert(res.data.msg); | ||
| 243 | - }) | 237 | + checkCode(data).then(res => { |
| 238 | + console.log(res); | ||
| 239 | + if (res.data.code == 200) { | ||
| 240 | + uni.$u.route({ | ||
| 241 | + url: `pages/order-info/order-disposal/scan-detail/index`, | ||
| 242 | + params: { | ||
| 243 | + data: encodeURIComponent(JSON.stringify(res.data | ||
| 244 | + .data)) | ||
| 245 | + } | ||
| 246 | + }) | ||
| 247 | + return | ||
| 248 | + } | ||
| 249 | + alert(res.data.msg); | ||
| 250 | + }) | ||
| 244 | } catch (error) { | 251 | } catch (error) { |
| 245 | alert("无法确认当前二维码趟次,请扫描正在进行的运输趟次"); | 252 | alert("无法确认当前二维码趟次,请扫描正在进行的运输趟次"); |
| 246 | } | 253 | } |
| @@ -253,7 +260,7 @@ const getOrderCountByType = (tabIndex) => { | @@ -253,7 +260,7 @@ const getOrderCountByType = (tabIndex) => { | ||
| 253 | const type = tabIndex === 0 ? 1 : 3; | 260 | const type = tabIndex === 0 ? 1 : 3; |
| 254 | queryOrderList({ type, pageNo: 1, pageSize: 1 }).then((res) => { | 261 | queryOrderList({ type, pageNo: 1, pageSize: 1 }).then((res) => { |
| 255 | if (res.data && res.data.data) { | 262 | if (res.data && res.data.data) { |
| 256 | - // 这里假设接口返回的total是订单总数 | 263 | + // 这里假设接口返回的 total 是订单总数 |
| 257 | list.value[tabIndex].count = res.data.data.total || 0; | 264 | list.value[tabIndex].count = res.data.data.total || 0; |
| 258 | } | 265 | } |
| 259 | }).catch(() => { | 266 | }).catch(() => { |
| @@ -284,6 +291,11 @@ onMounted(() => { | @@ -284,6 +291,11 @@ onMounted(() => { | ||
| 284 | getAllOrderCounts(); | 291 | getAllOrderCounts(); |
| 285 | }) | 292 | }) |
| 286 | }) | 293 | }) |
| 294 | + | ||
| 295 | +onLoad((options) => { | ||
| 296 | + // 获取定位信息 | ||
| 297 | + getPhoneLocation(); | ||
| 298 | +}); | ||
| 287 | </script> | 299 | </script> |
| 288 | <style lang="scss" scoped> | 300 | <style lang="scss" scoped> |
| 289 | .scanCode { | 301 | .scanCode { |
garbage-removal/src/pages/wode/index.vue
| @@ -130,6 +130,8 @@ const handleLoginOut = () => { | @@ -130,6 +130,8 @@ const handleLoginOut = () => { | ||
| 130 | if (res.confirm) { | 130 | if (res.confirm) { |
| 131 | loginOut().then(res => { | 131 | loginOut().then(res => { |
| 132 | if (res.data.success) { | 132 | if (res.data.success) { |
| 133 | + // 清除所有缓存 | ||
| 134 | + clearAllCache(); | ||
| 133 | store.token = null; | 135 | store.token = null; |
| 134 | setRequestToken(); | 136 | setRequestToken(); |
| 135 | uni.$u.toast("已退出") | 137 | uni.$u.toast("已退出") |
| @@ -146,6 +148,77 @@ const handleLoginOut = () => { | @@ -146,6 +148,77 @@ const handleLoginOut = () => { | ||
| 146 | }); | 148 | }); |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 151 | +// 清除所有缓存的函数 | ||
| 152 | +const clearAllCache = () => { | ||
| 153 | + try { | ||
| 154 | + // 1. 清除Pinia持久化存储 | ||
| 155 | + store.$reset(); | ||
| 156 | + | ||
| 157 | + // 2. 清除所有本地存储 | ||
| 158 | + const storageKeys = [ | ||
| 159 | + 'cancelFlag', | ||
| 160 | + 'refreshFlag', | ||
| 161 | + 'Z-PAGING-CONFIG-STORAGE-KEY' | ||
| 162 | + ]; | ||
| 163 | + | ||
| 164 | + // 获取所有存储的key并清除 | ||
| 165 | + const allKeys = getAllStorageKeys(); | ||
| 166 | + allKeys.forEach(key => { | ||
| 167 | + // 保留一些必要的系统key,清除业务相关的key | ||
| 168 | + if (!isSystemKey(key)) { | ||
| 169 | + uni.removeStorageSync(key); | ||
| 170 | + } | ||
| 171 | + }); | ||
| 172 | + | ||
| 173 | + // 3. 清除z-paging相关缓存 | ||
| 174 | + clearZPagingCache(); | ||
| 175 | + | ||
| 176 | + // 4. 清除请求token | ||
| 177 | + setRequestToken(); | ||
| 178 | + | ||
| 179 | + console.log('所有缓存已清除'); | ||
| 180 | + } catch (error) { | ||
| 181 | + console.error('清除缓存时发生错误:', error); | ||
| 182 | + } | ||
| 183 | +}; | ||
| 184 | + | ||
| 185 | +// 获取所有存储的key | ||
| 186 | +const getAllStorageKeys = () => { | ||
| 187 | + const res = uni.getStorageInfoSync(); | ||
| 188 | + return res.keys || []; | ||
| 189 | +}; | ||
| 190 | + | ||
| 191 | +// 判断是否为系统保留的key | ||
| 192 | +const isSystemKey = (key) => { | ||
| 193 | + // 系统保留的key,不要清除 | ||
| 194 | + const systemKeys = [ | ||
| 195 | + '__webviewId__', | ||
| 196 | + '__uniapp__', | ||
| 197 | + '__UNI__', | ||
| 198 | + // 可以根据实际情况添加其他系统key | ||
| 199 | + ]; | ||
| 200 | + | ||
| 201 | + return systemKeys.some(systemKey => key.includes(systemKey)); | ||
| 202 | +}; | ||
| 203 | + | ||
| 204 | +// 清除z-paging缓存 | ||
| 205 | +const clearZPagingCache = () => { | ||
| 206 | + try { | ||
| 207 | + // 清除z-paging配置缓存 | ||
| 208 | + uni.removeStorageSync('Z-PAGING-CONFIG-STORAGE-KEY'); | ||
| 209 | + | ||
| 210 | + // 清除所有z-paging缓存前缀的数据 | ||
| 211 | + const allKeys = getAllStorageKeys(); | ||
| 212 | + allKeys.forEach(key => { | ||
| 213 | + if (key.startsWith('z-paging-cache')) { | ||
| 214 | + uni.removeStorageSync(key); | ||
| 215 | + } | ||
| 216 | + }); | ||
| 217 | + } catch (error) { | ||
| 218 | + console.error('清除z-paging缓存时发生错误:', error); | ||
| 219 | + } | ||
| 220 | +}; | ||
| 221 | + | ||
| 149 | 222 | ||
| 150 | </script> | 223 | </script> |
| 151 | 224 |
garbage-removal/src/utils/request/request.js
| @@ -61,28 +61,38 @@ instance.interceptors.request.use((config) => { | @@ -61,28 +61,38 @@ instance.interceptors.request.use((config) => { | ||
| 61 | }); | 61 | }); |
| 62 | // 响应拦截器 | 62 | // 响应拦截器 |
| 63 | instance.interceptors.response.use((response) => { | 63 | instance.interceptors.response.use((response) => { |
| 64 | - | ||
| 65 | // 没有网络时 message的内容为"Network Error" | 64 | // 没有网络时 message的内容为"Network Error" |
| 66 | if (response.errMsg === "request:fail") { | 65 | if (response.errMsg === "request:fail") { |
| 67 | uni.$u.toast("网络错误~") | 66 | uni.$u.toast("网络错误~") |
| 68 | return response; | 67 | return response; |
| 69 | } | 68 | } |
| 69 | + | ||
| 70 | + // 特别处理queryOrderDispatch相关的401/403错误 | ||
| 71 | + const url = response.config?.url || ''; | ||
| 72 | + const isOrderDispatchRequest = url.includes('/order/queryDispatch/'); | ||
| 73 | + | ||
| 70 | if (response.data.code != 200) { | 74 | if (response.data.code != 200) { |
| 71 | // 对于匿名访问的页面,不处理401和403错误 | 75 | // 对于匿名访问的页面,不处理401和403错误 |
| 72 | - const url = response.config?.url || ''; | ||
| 73 | const isGuestAccess = url.startsWith("/order-info/order-other/webDetail/") || | 76 | const isGuestAccess = url.startsWith("/order-info/order-other/webDetail/") || |
| 74 | url.startsWith("/order-info/order-driver/detail/guest/")|| | 77 | url.startsWith("/order-info/order-driver/detail/guest/")|| |
| 75 | url.startsWith("/gar/car/requestStrByEnergyType"); | 78 | url.startsWith("/gar/car/requestStrByEnergyType"); |
| 76 | 79 | ||
| 77 | if (response.data.code == 401 || response.data.code == 403) { | 80 | if (response.data.code == 401 || response.data.code == 403) { |
| 78 | if (!isGuestAccess) { | 81 | if (!isGuestAccess) { |
| 82 | + // 如果是订单分配相关的请求,给出明确提示 | ||
| 83 | + if (isOrderDispatchRequest) { | ||
| 84 | + uni.$u.toast("登录已过期,请重新登录"); | ||
| 85 | + } | ||
| 79 | reSetLoginStatus(); | 86 | reSetLoginStatus(); |
| 80 | } | 87 | } |
| 81 | } else { | 88 | } else { |
| 82 | - uni.showToast({ | ||
| 83 | - title: response.data.msg, | ||
| 84 | - icon: "none", | ||
| 85 | - }); | 89 | + // 非权限错误才显示具体错误信息 |
| 90 | + if (!isOrderDispatchRequest || response.data.code !== 401) { | ||
| 91 | + uni.showToast({ | ||
| 92 | + title: response.data.msg, | ||
| 93 | + icon: "none", | ||
| 94 | + }); | ||
| 95 | + } | ||
| 86 | } | 96 | } |
| 87 | } | 97 | } |
| 88 | return response; | 98 | return response; |
| @@ -92,18 +102,32 @@ instance.interceptors.response.use((response) => { | @@ -92,18 +102,32 @@ instance.interceptors.response.use((response) => { | ||
| 92 | const isGuestAccess = url.startsWith("/order-info/order-other/webDetail/") || | 102 | const isGuestAccess = url.startsWith("/order-info/order-other/webDetail/") || |
| 93 | url.startsWith("/order-info/order-driver/detail/guest/")|| | 103 | url.startsWith("/order-info/order-driver/detail/guest/")|| |
| 94 | url.startsWith("/gar/car/requestStrByEnergyType"); | 104 | url.startsWith("/gar/car/requestStrByEnergyType"); |
| 105 | + const isOrderDispatchRequest = url.includes('/order/queryDispatch/'); | ||
| 95 | 106 | ||
| 96 | - if (error.response.status) { | 107 | + if (error.response && error.response.status) { |
| 97 | switch (error.response.status) { | 108 | switch (error.response.status) { |
| 98 | case 401: | 109 | case 401: |
| 99 | case 403: | 110 | case 403: |
| 100 | if (!isGuestAccess) { | 111 | if (!isGuestAccess) { |
| 112 | + // 订单分配请求的特殊处理 | ||
| 113 | + if (isOrderDispatchRequest) { | ||
| 114 | + uni.$u.toast("登录已过期,请重新登录"); | ||
| 115 | + } | ||
| 101 | reSetLoginStatus(); | 116 | reSetLoginStatus(); |
| 102 | } | 117 | } |
| 103 | break; | 118 | break; |
| 104 | default: | 119 | default: |
| 120 | + // 其他HTTP错误 | ||
| 121 | + if (!isOrderDispatchRequest) { | ||
| 122 | + uni.$u.toast("请求失败,请稍后重试"); | ||
| 123 | + } | ||
| 105 | break; | 124 | break; |
| 106 | } | 125 | } |
| 126 | + } else { | ||
| 127 | + // 网络错误 | ||
| 128 | + if (!isOrderDispatchRequest) { | ||
| 129 | + uni.$u.toast("网络连接异常"); | ||
| 130 | + } | ||
| 107 | } | 131 | } |
| 108 | return Promise.reject(error) | 132 | return Promise.reject(error) |
| 109 | }); | 133 | }); |