Commit bea22677ee50d9251fd3310c4b48999084df4d11
1 parent
116fac55
提交
Showing
19 changed files
with
913 additions
and
188 deletions
garbage-removal/src/apis/order.js
| @@ -99,6 +99,14 @@ export async function createHandlerQrCode(orderId) { | @@ -99,6 +99,14 @@ export async function createHandlerQrCode(orderId) { | ||
| 99 | return await request.get(`/order/handler/qrCode/${orderId}`); | 99 | return await request.get(`/order/handler/qrCode/${orderId}`); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | +export async function queryGarOrderMatchAsk(orderId) { | ||
| 103 | + return await request.get(`/order/queryGarOrderMatchAsk/${orderId}`); | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +export async function querySiteByTel() { | ||
| 107 | + return await request.get(`/order/querySiteByTel`); | ||
| 108 | +} | ||
| 109 | + | ||
| 102 | export async function queryOrderMessageCount() { | 110 | export async function queryOrderMessageCount() { |
| 103 | return await request.get(`/order/query/message/count`); | 111 | return await request.get(`/order/query/message/count`); |
| 104 | } | 112 | } |
garbage-removal/src/apis/user.js
| @@ -13,7 +13,13 @@ export async function userLogin( params, config) { | @@ -13,7 +13,13 @@ export async function userLogin( params, config) { | ||
| 13 | config | 13 | config |
| 14 | ); | 14 | ); |
| 15 | } | 15 | } |
| 16 | - | 16 | +export async function updatePassword( params, config) { |
| 17 | + return await request.post( | ||
| 18 | + `${prefix}/updatePassword`, | ||
| 19 | + params, | ||
| 20 | + config | ||
| 21 | + ); | ||
| 22 | +} | ||
| 17 | /** | 23 | /** |
| 18 | * @method 退出登录 | 24 | * @method 退出登录 |
| 19 | */ | 25 | */ |
garbage-removal/src/components/clash-disposal-dispatch/index.vue
| 1 | + | ||
| 1 | <template> | 2 | <template> |
| 2 | - <next-tree :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" | ||
| 3 | - :selectParent="selectParent" :multiple="multiple" :treeData="treeData" @cancel="close" @confirm="onconfirm"> | 3 | + <next-tree |
| 4 | + :changeVerify="changeVerify" | ||
| 5 | + :title="getTitle" | ||
| 6 | + ref="nextTreeRef" | ||
| 7 | + :checkStrictly="checkStrictly" | ||
| 8 | + :selectParent="selectParent" | ||
| 9 | + :multiple="multiple" | ||
| 10 | + :treeData="filteredTreeData" | ||
| 11 | + @cancel="close" | ||
| 12 | + @confirm="onconfirm"> | ||
| 13 | + <template #topBar> | ||
| 14 | + <view class="search-container"> | ||
| 15 | + <view class="search-box"> | ||
| 16 | + <text class="search-icon">🔍</text> | ||
| 17 | + <input | ||
| 18 | + class="search-input" | ||
| 19 | + placeholder="搜索处置场所负责人姓名" | ||
| 20 | + v-model="searchText" /> | ||
| 21 | + <text | ||
| 22 | + v-if="searchText" | ||
| 23 | + class="clear-icon" | ||
| 24 | + @click="clearSearch">✕</text> | ||
| 25 | + </view> | ||
| 26 | + </view> | ||
| 27 | + </template> | ||
| 4 | </next-tree> | 28 | </next-tree> |
| 5 | </template> | 29 | </template> |
| 6 | 30 | ||
| 7 | -<script setup> | ||
| 8 | -import { nextTick, ref, unref } from 'vue'; | 31 | +<script setup>import { nextTick, ref, unref, computed } from 'vue'; |
| 9 | // @ts-ignore | 32 | // @ts-ignore |
| 10 | import nextTree from '../next-tree/next-tree.vue'; | 33 | import nextTree from '../next-tree/next-tree.vue'; |
| 34 | + | ||
| 11 | const props = defineProps({ | 35 | const props = defineProps({ |
| 12 | dataList: { | 36 | dataList: { |
| 13 | type: Array, | 37 | type: Array, |
| @@ -33,28 +57,50 @@ const props = defineProps({ | @@ -33,28 +57,50 @@ const props = defineProps({ | ||
| 33 | type: Function, | 57 | type: Function, |
| 34 | default: () => { } | 58 | default: () => { } |
| 35 | } | 59 | } |
| 36 | - | ||
| 37 | }) | 60 | }) |
| 61 | + | ||
| 38 | const treeData = ref([]) | 62 | const treeData = ref([]) |
| 39 | const nextTreeRef = ref() | 63 | const nextTreeRef = ref() |
| 64 | +const searchText = ref('') | ||
| 65 | + | ||
| 66 | +// 添加计算属性用于过滤数据 | ||
| 67 | +const filteredTreeData = computed(() => { | ||
| 68 | + if (!searchText.value) { | ||
| 69 | + return treeData.value | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + return treeData.value.map(item => { | ||
| 73 | + const filteredChildren = item.children.filter(child => | ||
| 74 | + child.label.toLowerCase().includes(searchText.value.toLowerCase()) | ||
| 75 | + ) | ||
| 76 | + | ||
| 77 | + return { | ||
| 78 | + ...item, | ||
| 79 | + children: filteredChildren | ||
| 80 | + } | ||
| 81 | + }).filter(item => item.children.length > 0) | ||
| 82 | +}) | ||
| 83 | + | ||
| 40 | function getTitle(checked) { | 84 | function getTitle(checked) { |
| 41 | return `已选:${checked.length}位处置场所负责人` | 85 | return `已选:${checked.length}位处置场所负责人` |
| 42 | } | 86 | } |
| 87 | + | ||
| 43 | function changeVerify(current, chooseList) { | 88 | function changeVerify(current, chooseList) { |
| 44 | // 注意:返回非空字符串会阻止原有行为,并提示返回的字符串 | 89 | // 注意:返回非空字符串会阻止原有行为,并提示返回的字符串 |
| 45 | // 如果函数体不做return返回值,即验证通过,控件正常处理业务 | 90 | // 如果函数体不做return返回值,即验证通过,控件正常处理业务 |
| 46 | // 限制条件 只能选择一个处置场所 | 91 | // 限制条件 只能选择一个处置场所 |
| 47 | - if (chooseList && chooseList.length<2) { | 92 | + if (chooseList && chooseList.length < 2) { |
| 48 | for (let index = 0; index < chooseList.length; index++) { | 93 | for (let index = 0; index < chooseList.length; index++) { |
| 49 | const element = chooseList[index]; | 94 | const element = chooseList[index]; |
| 50 | if (current.id.indexOf(element.id) === -1 && element.label.indexOf(current.label) != -1) { | 95 | if (current.id.indexOf(element.id) === -1 && element.label.indexOf(current.label) != -1) { |
| 51 | return "该处置场所负责人已经被选中了" | 96 | return "该处置场所负责人已经被选中了" |
| 52 | } | 97 | } |
| 53 | } | 98 | } |
| 54 | - }else{ | ||
| 55 | - return "只能选择一个处置场所" | 99 | + } else { |
| 100 | + return "只能选择一个处置场所" | ||
| 56 | } | 101 | } |
| 57 | } | 102 | } |
| 103 | + | ||
| 58 | function open(dataList) { | 104 | function open(dataList) { |
| 59 | treeData.value = handlerTreeData(dataList) | 105 | treeData.value = handlerTreeData(dataList) |
| 60 | treeData.value = treeData.value.filter(item => { | 106 | treeData.value = treeData.value.filter(item => { |
| @@ -69,27 +115,28 @@ function open(dataList) { | @@ -69,27 +115,28 @@ function open(dataList) { | ||
| 69 | 115 | ||
| 70 | function handlerTreeData(dataList) { | 116 | function handlerTreeData(dataList) { |
| 71 | return dataList | 117 | return dataList |
| 72 | - .map((item, index) => { | ||
| 73 | - return { | ||
| 74 | - "id": (index + 1), | ||
| 75 | - "name": item.garOrderDisposalCompanyName, | ||
| 76 | - "label": item.garOrderDisposalCompanyName, | ||
| 77 | - "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | ||
| 78 | - return { | ||
| 79 | - "id": (index + 1) + '-' + (childrenIndex + 1), | ||
| 80 | - "tel": childrenItem.tel, | ||
| 81 | - "companyName": item.garOrderDisposalCompanyName, | ||
| 82 | - "companyId": item.garOrderDisposalCompanyId, | ||
| 83 | - "name": childrenItem.personName, | ||
| 84 | - "personName": childrenItem.personName, | ||
| 85 | - "label": childrenItem.personName + "-" + childrenItem.tel, | ||
| 86 | - "checked": childrenItem.checked, | ||
| 87 | - "disabled": childrenItem.checked ? true : childrenItem.tel ? false : true | ||
| 88 | - } | ||
| 89 | - }) | ||
| 90 | - } | ||
| 91 | - }) | 118 | + .map((item, index) => { |
| 119 | + return { | ||
| 120 | + "id": (index + 1), | ||
| 121 | + "name": item.garOrderDisposalCompanyName, | ||
| 122 | + "label": item.garOrderDisposalCompanyName, | ||
| 123 | + "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | ||
| 124 | + return { | ||
| 125 | + "id": (index + 1) + '-' + (childrenIndex + 1), | ||
| 126 | + "tel": childrenItem.tel, | ||
| 127 | + "companyName": item.garOrderDisposalCompanyName, | ||
| 128 | + "companyId": item.garOrderDisposalCompanyId, | ||
| 129 | + "name": childrenItem.personName, | ||
| 130 | + "personName": childrenItem.personName, | ||
| 131 | + "label": childrenItem.personName + "-" + childrenItem.tel, | ||
| 132 | + "checked": childrenItem.checked, | ||
| 133 | + "disabled": childrenItem.checked ? true : childrenItem.tel ? false : true | ||
| 134 | + } | ||
| 135 | + }) | ||
| 136 | + } | ||
| 137 | + }) | ||
| 92 | } | 138 | } |
| 139 | + | ||
| 93 | function cleanTreeData(treeData) { | 140 | function cleanTreeData(treeData) { |
| 94 | treeData.map(item => { | 141 | treeData.map(item => { |
| 95 | item.checked = false | 142 | item.checked = false |
| @@ -98,16 +145,24 @@ function cleanTreeData(treeData) { | @@ -98,16 +145,24 @@ function cleanTreeData(treeData) { | ||
| 98 | } | 145 | } |
| 99 | }) | 146 | }) |
| 100 | } | 147 | } |
| 148 | + | ||
| 101 | function close() { | 149 | function close() { |
| 102 | // 清除treeData的选中状态 | 150 | // 清除treeData的选中状态 |
| 103 | cleanTreeData(unref(treeData)) | 151 | cleanTreeData(unref(treeData)) |
| 152 | + searchText.value = '' // 清空搜索文本 | ||
| 104 | } | 153 | } |
| 154 | + | ||
| 155 | +// 添加清空搜索功能 | ||
| 156 | +function clearSearch() { | ||
| 157 | + searchText.value = '' | ||
| 158 | +} | ||
| 159 | + | ||
| 105 | defineExpose({ | 160 | defineExpose({ |
| 106 | open, close, nextTreeRef | 161 | open, close, nextTreeRef |
| 107 | }) | 162 | }) |
| 108 | </script> | 163 | </script> |
| 109 | -<style lang="scss"> | ||
| 110 | -.line-block { | 164 | + |
| 165 | +<style lang="scss">.line-block { | ||
| 111 | display: flex; | 166 | display: flex; |
| 112 | flex-direction: row; | 167 | flex-direction: row; |
| 113 | justify-content: flex-start; | 168 | justify-content: flex-start; |
| @@ -120,4 +175,43 @@ defineExpose({ | @@ -120,4 +175,43 @@ defineExpose({ | ||
| 120 | margin: 0 20rpx; | 175 | margin: 0 20rpx; |
| 121 | } | 176 | } |
| 122 | } | 177 | } |
| 123 | -</style> | 178 | + |
| 179 | +.search-container { | ||
| 180 | + padding: 15px 10px 10px; | ||
| 181 | + background-color: #fff; | ||
| 182 | + | ||
| 183 | + .search-box { | ||
| 184 | + display: flex; | ||
| 185 | + align-items: center; | ||
| 186 | + background-color: #f5f5f5; | ||
| 187 | + border-radius: 20px; | ||
| 188 | + padding: 8px 15px; | ||
| 189 | + | ||
| 190 | + .search-icon { | ||
| 191 | + font-size: 16px; | ||
| 192 | + margin-right: 8px; | ||
| 193 | + color: #999; | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + .search-input { | ||
| 197 | + flex: 1; | ||
| 198 | + border: none; | ||
| 199 | + background: transparent; | ||
| 200 | + font-size: 14px; | ||
| 201 | + outline: none; | ||
| 202 | + padding: 5px 0; | ||
| 203 | + | ||
| 204 | + &::placeholder { | ||
| 205 | + color: #aaa; | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + .clear-icon { | ||
| 210 | + font-size: 16px; | ||
| 211 | + color: #999; | ||
| 212 | + padding: 2px; | ||
| 213 | + cursor: pointer; | ||
| 214 | + } | ||
| 215 | + } | ||
| 216 | +} | ||
| 217 | +</style> | ||
| 124 | \ No newline at end of file | 218 | \ No newline at end of file |
garbage-removal/src/components/clash-driver-dispatch/index.vue
| 1 | <template> | 1 | <template> |
| 2 | - <next-tree :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" | ||
| 3 | - :selectParent="selectParent" :multiple="multiple" :treeData="treeData" @cancel="close" @confirm="onconfirm"> | ||
| 4 | - <!-- label插槽示意代码 --> | ||
| 5 | - <!-- <template #label="{data: {id, label, iconSrc, prev, post}}"> | ||
| 6 | - <view class="line-block"> | ||
| 7 | - <image class="img" v-if="iconSrc" :src="iconSrc"></image> | ||
| 8 | - <text space="nbsp" v-if="prev">{{prev}} </text><text>{{label}}</text><text space="nbsp" v-if="post"> {{post}}</text> | ||
| 9 | - </view> | ||
| 10 | - </template> --> | ||
| 11 | - <!-- <template #topBar> | ||
| 12 | - <view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view> | ||
| 13 | - <view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;"> | ||
| 14 | - <button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button> | ||
| 15 | - <button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button> | ||
| 16 | - <button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button> | ||
| 17 | - </view> | ||
| 18 | - </template> --> | 2 | + <next-tree |
| 3 | + :changeVerify="changeVerify" | ||
| 4 | + :title="getTitle" | ||
| 5 | + ref="nextTreeRef" | ||
| 6 | + :checkStrictly="checkStrictly" | ||
| 7 | + :selectParent="selectParent" | ||
| 8 | + :multiple="multiple" | ||
| 9 | + :treeData="filteredTreeData" | ||
| 10 | + @cancel="close" | ||
| 11 | + @confirm="onconfirm"> | ||
| 12 | + <template #topBar> | ||
| 13 | + <view class="search-container"> | ||
| 14 | + <view class="search-box"> | ||
| 15 | + <text class="search-icon">🔍</text> | ||
| 16 | + <input | ||
| 17 | + class="search-input" | ||
| 18 | + placeholder="搜索驾驶员姓名" | ||
| 19 | + v-model="searchText" /> | ||
| 20 | + <text | ||
| 21 | + v-if="searchText" | ||
| 22 | + class="clear-icon" | ||
| 23 | + @click="clearSearch">✕</text> | ||
| 24 | + </view> | ||
| 25 | + </view> | ||
| 26 | + </template> | ||
| 19 | </next-tree> | 27 | </next-tree> |
| 20 | </template> | 28 | </template> |
| 21 | 29 | ||
| 22 | -<script setup> | ||
| 23 | -import { nextTick, ref, unref } from 'vue'; | 30 | +<script setup>import { nextTick, ref, unref, computed } from 'vue'; |
| 24 | // @ts-ignore | 31 | // @ts-ignore |
| 25 | import nextTree from '../next-tree/next-tree.vue'; | 32 | import nextTree from '../next-tree/next-tree.vue'; |
| 33 | + | ||
| 26 | const props = defineProps({ | 34 | const props = defineProps({ |
| 27 | dataList: { | 35 | dataList: { |
| 28 | type: Array, | 36 | type: Array, |
| @@ -48,17 +56,35 @@ const props = defineProps({ | @@ -48,17 +56,35 @@ const props = defineProps({ | ||
| 48 | type: Function, | 56 | type: Function, |
| 49 | default: () => { } | 57 | default: () => { } |
| 50 | } | 58 | } |
| 51 | - | ||
| 52 | }) | 59 | }) |
| 60 | + | ||
| 53 | const treeData = ref([]) | 61 | const treeData = ref([]) |
| 54 | const nextTreeRef = ref() | 62 | const nextTreeRef = ref() |
| 63 | +const searchText = ref('') | ||
| 64 | + | ||
| 65 | +// 添加计算属性用于过滤数据 | ||
| 66 | +const filteredTreeData = computed(() => { | ||
| 67 | + if (!searchText.value) { | ||
| 68 | + return treeData.value | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + return treeData.value.map(item => { | ||
| 72 | + const filteredChildren = item.children.filter(child => | ||
| 73 | + child.label.toLowerCase().includes(searchText.value.toLowerCase()) | ||
| 74 | + ) | ||
| 75 | + | ||
| 76 | + return { | ||
| 77 | + ...item, | ||
| 78 | + children: filteredChildren | ||
| 79 | + } | ||
| 80 | + }).filter(item => item.children.length > 0) | ||
| 81 | +}) | ||
| 82 | + | ||
| 55 | function getTitle(checked) { | 83 | function getTitle(checked) { |
| 56 | return `已选:${checked.length}位驾驶员` | 84 | return `已选:${checked.length}位驾驶员` |
| 57 | } | 85 | } |
| 86 | + | ||
| 58 | function changeVerify(current, chooseList) { | 87 | function changeVerify(current, chooseList) { |
| 59 | - // 注意:返回非空字符串会阻止原有行为,并提示返回的字符串 | ||
| 60 | - // 如果函数体不做return返回值,即验证通过,控件正常处理业务 | ||
| 61 | - // 限制条件 | ||
| 62 | if (chooseList) { | 88 | if (chooseList) { |
| 63 | for (let index = 0; index < chooseList.length; index++) { | 89 | for (let index = 0; index < chooseList.length; index++) { |
| 64 | const element = chooseList[index]; | 90 | const element = chooseList[index]; |
| @@ -68,6 +94,7 @@ function changeVerify(current, chooseList) { | @@ -68,6 +94,7 @@ function changeVerify(current, chooseList) { | ||
| 68 | } | 94 | } |
| 69 | } | 95 | } |
| 70 | } | 96 | } |
| 97 | + | ||
| 71 | function open(dataList) { | 98 | function open(dataList) { |
| 72 | treeData.value = handlerTreeData(dataList) | 99 | treeData.value = handlerTreeData(dataList) |
| 73 | treeData.value = treeData.value.filter(item => { | 100 | treeData.value = treeData.value.filter(item => { |
| @@ -82,27 +109,28 @@ function open(dataList) { | @@ -82,27 +109,28 @@ function open(dataList) { | ||
| 82 | 109 | ||
| 83 | function handlerTreeData(dataList) { | 110 | function handlerTreeData(dataList) { |
| 84 | return dataList | 111 | return dataList |
| 85 | - .map((item, index) => { | ||
| 86 | - return { | ||
| 87 | - "id": (index + 1), | ||
| 88 | - "licensePlateNumber": item.licensePlateNumber, | ||
| 89 | - "containerVolume": item.containerVolume + "方车", | ||
| 90 | - "label": item.containerVolume + "方车" + '-' + item.licensePlateNumber, | ||
| 91 | - "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | ||
| 92 | - return { | ||
| 93 | - "id": (index + 1) + '-' + (childrenIndex + 1), | ||
| 94 | - "garOrderContainerVolume": item.containerVolume, | ||
| 95 | - "tel": childrenItem.tel, | ||
| 96 | - "name": childrenItem.name, | ||
| 97 | - "label": childrenItem.name + '-' + childrenItem.tel, | ||
| 98 | - "checked": childrenItem.checked, | ||
| 99 | - "carCode": item.licensePlateNumber, | ||
| 100 | - "disabled": childrenItem.checked ? true : childrenItem.tel ? false : true | ||
| 101 | - } | ||
| 102 | - }) | ||
| 103 | - } | ||
| 104 | - }) | 112 | + .map((item, index) => { |
| 113 | + return { | ||
| 114 | + "id": (index + 1), | ||
| 115 | + "licensePlateNumber": item.licensePlateNumber, | ||
| 116 | + "containerVolume": item.containerVolume + "方车", | ||
| 117 | + "label": item.containerVolume + "方车" + '-' + item.licensePlateNumber, | ||
| 118 | + "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | ||
| 119 | + return { | ||
| 120 | + "id": (index + 1) + '-' + (childrenIndex + 1), | ||
| 121 | + "garOrderContainerVolume": item.containerVolume, | ||
| 122 | + "tel": childrenItem.tel, | ||
| 123 | + "name": childrenItem.name, | ||
| 124 | + "label": childrenItem.name + '-' + childrenItem.tel, | ||
| 125 | + "checked": childrenItem.checked, | ||
| 126 | + "carCode": item.licensePlateNumber, | ||
| 127 | + "disabled": childrenItem.checked ? true : childrenItem.tel ? false : true | ||
| 128 | + } | ||
| 129 | + }) | ||
| 130 | + } | ||
| 131 | + }) | ||
| 105 | } | 132 | } |
| 133 | + | ||
| 106 | function cleanTreeData(treeData) { | 134 | function cleanTreeData(treeData) { |
| 107 | treeData.map(item => { | 135 | treeData.map(item => { |
| 108 | item.checked = false | 136 | item.checked = false |
| @@ -111,16 +139,27 @@ function cleanTreeData(treeData) { | @@ -111,16 +139,27 @@ function cleanTreeData(treeData) { | ||
| 111 | } | 139 | } |
| 112 | }) | 140 | }) |
| 113 | } | 141 | } |
| 142 | + | ||
| 114 | function close() { | 143 | function close() { |
| 115 | - // 清除treeData的选中状态 | ||
| 116 | cleanTreeData(unref(treeData)) | 144 | cleanTreeData(unref(treeData)) |
| 145 | + searchText.value = '' | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +function handleSearch() { | ||
| 149 | + // 搜索逻辑已经在 computed 属性中实现 | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +// 添加清空搜索功能 | ||
| 153 | +function clearSearch() { | ||
| 154 | + searchText.value = '' | ||
| 117 | } | 155 | } |
| 156 | + | ||
| 118 | defineExpose({ | 157 | defineExpose({ |
| 119 | open, close, nextTreeRef | 158 | open, close, nextTreeRef |
| 120 | }) | 159 | }) |
| 121 | </script> | 160 | </script> |
| 122 | -<style lang="scss"> | ||
| 123 | -.line-block { | 161 | + |
| 162 | +<style lang="scss">.line-block { | ||
| 124 | display: flex; | 163 | display: flex; |
| 125 | flex-direction: row; | 164 | flex-direction: row; |
| 126 | justify-content: flex-start; | 165 | justify-content: flex-start; |
| @@ -133,4 +172,43 @@ defineExpose({ | @@ -133,4 +172,43 @@ defineExpose({ | ||
| 133 | margin: 0 20rpx; | 172 | margin: 0 20rpx; |
| 134 | } | 173 | } |
| 135 | } | 174 | } |
| 136 | -</style> | 175 | + |
| 176 | +.search-container { | ||
| 177 | + padding: 15px 10px 10px; | ||
| 178 | + background-color: #fff; | ||
| 179 | + | ||
| 180 | + .search-box { | ||
| 181 | + display: flex; | ||
| 182 | + align-items: center; | ||
| 183 | + background-color: #f5f5f5; | ||
| 184 | + border-radius: 20px; | ||
| 185 | + padding: 8px 15px; | ||
| 186 | + | ||
| 187 | + .search-icon { | ||
| 188 | + font-size: 16px; | ||
| 189 | + margin-right: 8px; | ||
| 190 | + color: #999; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + .search-input { | ||
| 194 | + flex: 1; | ||
| 195 | + border: none; | ||
| 196 | + background: transparent; | ||
| 197 | + font-size: 14px; | ||
| 198 | + outline: none; | ||
| 199 | + padding: 5px 0; | ||
| 200 | + | ||
| 201 | + &::placeholder { | ||
| 202 | + color: #aaa; | ||
| 203 | + } | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + .clear-icon { | ||
| 207 | + font-size: 16px; | ||
| 208 | + color: #999; | ||
| 209 | + padding: 2px; | ||
| 210 | + cursor: pointer; | ||
| 211 | + } | ||
| 212 | + } | ||
| 213 | +} | ||
| 214 | +</style> | ||
| 137 | \ No newline at end of file | 215 | \ No newline at end of file |
garbage-removal/src/pages.json
| @@ -23,6 +23,12 @@ | @@ -23,6 +23,12 @@ | ||
| 23 | } | 23 | } |
| 24 | }, | 24 | }, |
| 25 | { | 25 | { |
| 26 | + "path": "pages/change-password/index", | ||
| 27 | + "style": { | ||
| 28 | + "navigationBarTitleText": "修改密码" | ||
| 29 | + } | ||
| 30 | + }, | ||
| 31 | + { | ||
| 26 | "path": "pages/sign-up/index", | 32 | "path": "pages/sign-up/index", |
| 27 | "style": { | 33 | "style": { |
| 28 | "navigationBarTitleText": "", | 34 | "navigationBarTitleText": "", |
garbage-removal/src/pages/change-password/index.vue
0 → 100644
| 1 | + | ||
| 2 | +<template> | ||
| 3 | + <view class="wrap"> | ||
| 4 | + <view class="form-container"> | ||
| 5 | + <view class="title">修改密码</view> | ||
| 6 | + | ||
| 7 | + <view class="input-wrapper"> | ||
| 8 | + <u-icon name="account" size="36" color="#909399" class="input-icon"></u-icon> | ||
| 9 | + <input | ||
| 10 | + class="login-input" | ||
| 11 | + type="text" | ||
| 12 | + v-model="formData.phone" | ||
| 13 | + placeholder="请输入手机号" | ||
| 14 | + placeholder-class="placeholder-style" | ||
| 15 | + /> | ||
| 16 | + </view> | ||
| 17 | + | ||
| 18 | + <view class="input-wrapper"> | ||
| 19 | + <u-icon name="lock" size="36" color="#909399" class="input-icon"></u-icon> | ||
| 20 | + <input | ||
| 21 | + class="login-input" | ||
| 22 | + type="password" | ||
| 23 | + v-model="formData.oldPassword" | ||
| 24 | + placeholder="请输入原密码" | ||
| 25 | + placeholder-class="placeholder-style" | ||
| 26 | + /> | ||
| 27 | + </view> | ||
| 28 | + | ||
| 29 | + <view class="input-wrapper"> | ||
| 30 | + <u-icon name="lock" size="36" color="#909399" class="input-icon"></u-icon> | ||
| 31 | + <input | ||
| 32 | + class="login-input" | ||
| 33 | + type="password" | ||
| 34 | + v-model="formData.newPassword" | ||
| 35 | + placeholder="请输入新密码" | ||
| 36 | + placeholder-class="placeholder-style" | ||
| 37 | + /> | ||
| 38 | + </view> | ||
| 39 | + | ||
| 40 | + <view class="input-wrapper"> | ||
| 41 | + <u-icon name="lock" size="36" color="#909399" class="input-icon"></u-icon> | ||
| 42 | + <input | ||
| 43 | + class="login-input" | ||
| 44 | + type="password" | ||
| 45 | + v-model="formData.confirmPassword" | ||
| 46 | + placeholder="请再次输入新密码" | ||
| 47 | + placeholder-class="placeholder-style" | ||
| 48 | + /> | ||
| 49 | + </view> | ||
| 50 | + | ||
| 51 | + <button @tap="handleChangePassword" class="submit-btn">确认修改</button> | ||
| 52 | + | ||
| 53 | + <view class="back-to-login"> | ||
| 54 | + <text class="link" @click="backToLogin">返回登录</text> | ||
| 55 | + </view> | ||
| 56 | + </view> | ||
| 57 | + </view> | ||
| 58 | +</template> | ||
| 59 | + | ||
| 60 | +<script setup>import { ref } from "vue"; | ||
| 61 | +import { updatePassword} from "@/apis/user.js"; // 需要在user.js中添加相应API | ||
| 62 | +import { getCurrentInstance } from "vue"; | ||
| 63 | + | ||
| 64 | +const { proxy } = getCurrentInstance(); | ||
| 65 | + | ||
| 66 | +// 表单数据 | ||
| 67 | +const formData = ref({ | ||
| 68 | + phone: "", | ||
| 69 | + oldPassword: "", | ||
| 70 | + newPassword: "", | ||
| 71 | + confirmPassword: "" | ||
| 72 | +}); | ||
| 73 | + | ||
| 74 | +// 验证码相关 | ||
| 75 | +const showCaptcha = ref(true); | ||
| 76 | +const countdown = ref(0); | ||
| 77 | + | ||
| 78 | +// 获取验证码 | ||
| 79 | +const getCaptcha = () => { | ||
| 80 | + if (!proxy.$u.test.mobile(formData.value.phone)) { | ||
| 81 | + proxy.$u.toast("请输入正确的手机号"); | ||
| 82 | + return; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + // 这里应该调用获取验证码的接口 | ||
| 86 | + // sendCode(formData.value.phone).then(res => { | ||
| 87 | + // proxy.$u.toast("验证码已发送"); | ||
| 88 | + // }); | ||
| 89 | + | ||
| 90 | + // 倒计时逻辑 | ||
| 91 | + countdown.value = 60; | ||
| 92 | + showCaptcha.value = false; | ||
| 93 | + | ||
| 94 | + const timer = setInterval(() => { | ||
| 95 | + countdown.value--; | ||
| 96 | + if (countdown.value <= 0) { | ||
| 97 | + showCaptcha.value = true; | ||
| 98 | + clearInterval(timer); | ||
| 99 | + } | ||
| 100 | + }, 1000); | ||
| 101 | +}; | ||
| 102 | + | ||
| 103 | +// 修改密码 | ||
| 104 | +const handleChangePassword = () => { | ||
| 105 | + // 表单验证 | ||
| 106 | + if (!proxy.$u.test.mobile(formData.value.phone)) { | ||
| 107 | + proxy.$u.toast("请输入正确的手机号"); | ||
| 108 | + return; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + if (!formData.value.oldPassword) { | ||
| 112 | + proxy.$u.toast("请输入原密码"); | ||
| 113 | + return; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + if (!formData.value.newPassword) { | ||
| 117 | + proxy.$u.toast("请输入新密码"); | ||
| 118 | + return; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + if (formData.value.newPassword !== formData.value.confirmPassword) { | ||
| 122 | + proxy.$u.toast("两次输入的新密码不一致"); | ||
| 123 | + return; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + // 调用修改密码接口 | ||
| 127 | + const params = { | ||
| 128 | + tel: formData.value.phone, | ||
| 129 | + oldPassword: formData.value.oldPassword, | ||
| 130 | + newPassword: formData.value.newPassword, | ||
| 131 | + }; | ||
| 132 | + | ||
| 133 | + updatePassword(params).then(res => { | ||
| 134 | + if (res.data.code === 200) { | ||
| 135 | + proxy.$u.toast("密码修改成功"); | ||
| 136 | + // 密码修改成功后,清除本地存储的用户信息并跳转到登录页 | ||
| 137 | + setTimeout(() => { | ||
| 138 | + uni.clearStorageSync(); // 清除本地存储的所有信息 | ||
| 139 | + uni.reLaunch({ | ||
| 140 | + url: '/pages/login/index' // 跳转到登录页 | ||
| 141 | + }); | ||
| 142 | + }, 1500); | ||
| 143 | + } else { | ||
| 144 | + proxy.$u.toast(res.data.msg || "修改失败"); | ||
| 145 | + } | ||
| 146 | + }).catch(err => { | ||
| 147 | + proxy.$u.toast("修改密码失败"); | ||
| 148 | + }); | ||
| 149 | +}; | ||
| 150 | + | ||
| 151 | +const backToLogin = () => { | ||
| 152 | + uni.navigateBack(); | ||
| 153 | +}; | ||
| 154 | +</script> | ||
| 155 | + | ||
| 156 | +<style lang="scss" scoped>.wrap { | ||
| 157 | + padding: 80rpx; | ||
| 158 | + background-color: #f5f5f5; | ||
| 159 | + min-height: 100vh; | ||
| 160 | +} | ||
| 161 | + | ||
| 162 | +.form-container { | ||
| 163 | + background-color: #fff; | ||
| 164 | + border-radius: 20rpx; | ||
| 165 | + padding: 40rpx; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +.title { | ||
| 169 | + font-size: 50rpx; | ||
| 170 | + color: #333; | ||
| 171 | + text-align: center; | ||
| 172 | + margin-bottom: 60rpx; | ||
| 173 | + font-weight: bold; | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +.input-wrapper { | ||
| 177 | + display: flex; | ||
| 178 | + align-items: center; | ||
| 179 | + border-bottom: 1px solid #e4e7ed; | ||
| 180 | + padding: 20rpx 0; | ||
| 181 | + margin-bottom: 30rpx; | ||
| 182 | + | ||
| 183 | + .input-icon { | ||
| 184 | + margin-right: 20rpx; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + .login-input { | ||
| 188 | + flex: 1; | ||
| 189 | + font-size: 28rpx; | ||
| 190 | + color: #303133; | ||
| 191 | + padding: 10rpx 0; | ||
| 192 | + | ||
| 193 | + &::placeholder { | ||
| 194 | + color: #c0c4cc; | ||
| 195 | + } | ||
| 196 | + } | ||
| 197 | +} | ||
| 198 | + | ||
| 199 | +.captcha-wrapper { | ||
| 200 | + border: none; | ||
| 201 | + | ||
| 202 | + .input-group { | ||
| 203 | + flex: 1; | ||
| 204 | + display: flex; | ||
| 205 | + align-items: center; | ||
| 206 | + border-bottom: 1px solid #e4e7ed; | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + .captcha { | ||
| 210 | + color: $u-warning; | ||
| 211 | + font-size: 28rpx; | ||
| 212 | + margin-left: 20rpx; | ||
| 213 | + white-space: nowrap; | ||
| 214 | + | ||
| 215 | + .noCaptcha { | ||
| 216 | + display: block; | ||
| 217 | + cursor: pointer; | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + .regain { | ||
| 221 | + display: block; | ||
| 222 | + } | ||
| 223 | + } | ||
| 224 | +} | ||
| 225 | + | ||
| 226 | +.placeholder-style { | ||
| 227 | + color: #c0c4cc; | ||
| 228 | + font-size: 26rpx; | ||
| 229 | +} | ||
| 230 | + | ||
| 231 | +.submit-btn { | ||
| 232 | + background-color: #19a97c; | ||
| 233 | + color: #ffffff; | ||
| 234 | + border: none; | ||
| 235 | + font-size: 30rpx; | ||
| 236 | + padding: 20rpx 0; | ||
| 237 | + border-radius: 50rpx; | ||
| 238 | + margin-top: 60rpx; | ||
| 239 | + width: 100%; | ||
| 240 | + | ||
| 241 | + &::after { | ||
| 242 | + border: none; | ||
| 243 | + } | ||
| 244 | +} | ||
| 245 | + | ||
| 246 | +.back-to-login { | ||
| 247 | + color: $u-tips-color; | ||
| 248 | + display: flex; | ||
| 249 | + justify-content: center; | ||
| 250 | + margin-top: 40rpx; | ||
| 251 | + | ||
| 252 | + .link { | ||
| 253 | + color: $u-warning; | ||
| 254 | + cursor: pointer; | ||
| 255 | + } | ||
| 256 | +} | ||
| 257 | +</style> | ||
| 0 | \ No newline at end of file | 258 | \ No newline at end of file |
garbage-removal/src/pages/home-info/address/index.vue
| @@ -82,9 +82,9 @@ const toAddSite = () => { | @@ -82,9 +82,9 @@ const toAddSite = () => { | ||
| 82 | } | 82 | } |
| 83 | onShow(() => { | 83 | onShow(() => { |
| 84 | getData(); | 84 | getData(); |
| 85 | - if (userType.value == '处置场所负责人') { | ||
| 86 | - updateFlag.value=false; | ||
| 87 | - } | 85 | + // if (userType.value == '处置场所负责人') { |
| 86 | + // updateFlag.value=false; | ||
| 87 | + // } | ||
| 88 | }) | 88 | }) |
| 89 | </script> | 89 | </script> |
| 90 | 90 |
garbage-removal/src/pages/home-info/clean/agreement.vue
| @@ -8,52 +8,44 @@ | @@ -8,52 +8,44 @@ | ||
| 8 | 尊敬的用户: | 8 | 尊敬的用户: |
| 9 | </p> | 9 | </p> |
| 10 | <p> | 10 | <p> |
| 11 | - 欢迎您通过“智慧渣管APP”选择我们的装修垃圾收运服务。为了确保装修垃圾能够得到及时、规范的处理,维护良好的环境卫生,我们特制定本意向协议。请您在仔细阅读并理解本协议的内容后,进行勾选同意。一旦您勾选同意,即代表您对本意向协议内容的认可和接受。 | 11 | + 欢迎您通过“智慧渣管APP”选择我们的装修垃圾收运服务。为了确保装修垃圾能够得到及时、规范的处理,维护良好的环境卫生,我们特制定本意向协议。请您在仔细阅读并理解本协议的内容后,进行勾选同意。一旦您勾选同意,即代表您对本意向协议内容的认可和接受。 |
| 12 | </p> | 12 | </p> |
| 13 | 13 | ||
| 14 | <!-- 服务内容部分 --> | 14 | <!-- 服务内容部分 --> |
| 15 | - <h2>一、服务内容</h2> | 15 | + <h2>一、服务内容和标准</h2> |
| 16 | <p> | 16 | <p> |
| 17 | - 1.我们将为您提供装修垃圾的收运服务,包括但不限于收集、运输、处置等环节。<br> | ||
| 18 | - 2.收运的装修垃圾范围包括但不限于木材、砖块、水泥、沙石、涂料、管材、电线等房屋装修过程中产生的废弃物。 | ||
| 19 | - </p> | ||
| 20 | - | ||
| 21 | - <!-- 服务标准部分 --> | ||
| 22 | - <h2>二、服务标准</h2> | ||
| 23 | - <p> | ||
| 24 | - 1.我们将按照国家和地方相关法律法规、标准及规范的要求,对装修垃圾进行收运和处置。<br> | ||
| 25 | - 2.确保收运车辆的整洁和卫生,避免对周边环境造成二次污染。<br> | ||
| 26 | - 3.按照您指定的时间和地点,及时进行装修垃圾的收集和运输。 | 17 | + 1.我们将按照国家和地方相关法律法规、标准及规范的要求为您提供装修垃圾的收运服务,包括但不限于收集、运输、处置等环节。<br> |
| 18 | + 2.收运的装修垃圾范围包括但不限于木材、砖块、水泥、沙石、涂料、管材、电线等房屋装修过程中产生的废弃物,<span class='jiacu'>但严禁混入生活垃圾、有害垃圾等。</span> | ||
| 19 | + 3.我们将按照您指定的时间和地点,及时进行装修垃圾的收集和运输,确保收运过程的整洁和卫生,并将装修垃圾运送至合法的处置场所。 | ||
| 27 | </p> | 20 | </p> |
| 28 | 21 | ||
| 29 | <!-- 费用说明部分 --> | 22 | <!-- 费用说明部分 --> |
| 30 | - <h2>三、费用说明</h2> | 23 | + <h2>二、费用说明</h2> |
| 31 | <p> | 24 | <p> |
| 32 | - 1.装修垃圾收运服务的费用将根据您的装修垃圾产生量、运输距离等因素进行计算。具体费用标准将在您实际使用服务时进行明确。<br> | 25 | + 1.装修垃圾收运服务的费用将根据您的装修垃圾产生量、运输距离等因素进行计算。具体费用标准将在您实际使用服务时进行明确。 <br> |
| 33 | 2.您同意按照我们协商一致的收费标准支付相应的费用<span class='jiacu'>(具体费用双方协商确认,不通过本预约软件支付),并理解费用可能会根据实际情况双方再协商微调。</span> | 26 | 2.您同意按照我们协商一致的收费标准支付相应的费用<span class='jiacu'>(具体费用双方协商确认,不通过本预约软件支付),并理解费用可能会根据实际情况双方再协商微调。</span> |
| 34 | </p> | 27 | </p> |
| 35 | 28 | ||
| 36 | - <!-- 双方的权利和义务部分 --> | ||
| 37 | - <h2>四、双方的权利和义务</h2> | 29 | + <!-- 权利和义务部分 --> |
| 30 | + <h2>三、双方的权利和义务</h2> | ||
| 38 | <p> | 31 | <p> |
| 39 | 1.您有权要求我们按照本协议的约定提供装修垃圾收运服务。<br> | 32 | 1.您有权要求我们按照本协议的约定提供装修垃圾收运服务。<br> |
| 40 | - 2.我们应按照本协议的约定,为您提供优质、高效的装修垃圾收运服务。<br> | ||
| 41 | - 3.我们应遵守国家和地方相关法律法规、标准及规范的要求,对装修垃圾进行收运和处置。<br> | ||
| 42 | - 4.我们应保护您的隐私和信息安全,不得泄露您的相关信息。 | 33 | + 2.双方应按照本协议的约定,以及国家和地方相关法律法规、标准及规范的要求,对装修垃圾进行投放、收运和处置。<br> |
| 43 | </p> | 34 | </p> |
| 44 | 35 | ||
| 45 | - <!-- 违约责任部分 --> | ||
| 46 | - <h2>五、违约责任</h2> | 36 | + <!-- 违约责任 --> |
| 37 | + <h2>四、违约责任</h2> | ||
| 47 | <p> | 38 | <p> |
| 48 | - 1.若您未按照国家和地方相关法律法规、标准及规范的要求将装修垃圾进行分类、装袋或放置在指定地点,我们有权拒绝收运,并要求您限期整改。若您逾期未整改,我们有权解除本协议,并要求您承担相应的违约责任。<br> | ||
| 49 | - 2.若您在我们已提供收运服务后未按时支付装修垃圾收运服务的费用,我们有权解除本协议,并要求您支付已产生的费用。 | 39 | + 1.若您未按照国家和地方相关法律法规、标准及规范的要求将投放装修垃圾,我们有权拒绝收运,并要求您限期整改。若您逾期未整改,我们有权解除本协议,并要求您承担相应的违约责任。<br> |
| 40 | + 2.若您在我们已提供收运服务后未按时支付装修垃圾收运服务的费用,我们有权解除本协议,并要求您支付已产生的费用。<br> | ||
| 41 | + 3.若垃圾运输过程中存在违法违规行为,所产生的法律后果由我方承担。<br> | ||
| 50 | </p> | 42 | </p> |
| 51 | 43 | ||
| 52 | <!-- 其他条款部分 --> | 44 | <!-- 其他条款部分 --> |
| 53 | - <h2>六、其他条款</h2> | 45 | + <h2>五、其他条款</h2> |
| 54 | <p> | 46 | <p> |
| 55 | - 1、如本协议双方经协商签订线下协议的,以线下协议为准,本协议无效。<br> | ||
| 56 | - 2、本协议经长沙市渣土事务中心开发的“智慧渣管APP”发布,协议双方为使用该APP的预约装修垃圾收运服务的用户以及经用户确认预约的装修垃圾运输企业,<span class='jiacu'>长沙市渣土事务中心不承担该协议约定的权利及义务。</span> | 47 | + 1.如本协议双方经协商签订线下协议的,以线下协议为准,本协议无效。<br> |
| 48 | + 2.本协议经长沙市渣土事务中心开发的“智慧渣管APP”发布,协议双方为使用该APP的预约装修垃圾收运服务的用户以及经用户确认预约的装修垃圾运输企业,<span class='jiacu'>长沙市渣土事务中心不承担该协议约定的权利及义务。</span> | ||
| 57 | </p> | 49 | </p> |
| 58 | </div> | 50 | </div> |
| 59 | </template> | 51 | </template> |
garbage-removal/src/pages/home-info/clean/index.vue
| @@ -55,14 +55,19 @@ | @@ -55,14 +55,19 @@ | ||
| 55 | </swiper> | 55 | </swiper> |
| 56 | </view> | 56 | </view> |
| 57 | 57 | ||
| 58 | - <view class="company-clean-container-car-main-content-type"> | ||
| 59 | - <view class="company-clean-container-car-main-content-type-price-area"> | ||
| 60 | - <text style="color: red;">*</text>车辆容积: | ||
| 61 | - </view> | ||
| 62 | - <view style=" width:100%;display:flex; color:#909399; align-items: center;"> | ||
| 63 | - <text>{{containerVolume}} 方</text> | ||
| 64 | - </view> | ||
| 65 | - </view> | 58 | + <view class="company-clean-container-car-main-content-type"> |
| 59 | + <view class="company-clean-container-car-main-content-type-price-area"> | ||
| 60 | + <text style="color: red;">*</text>车辆容积: | ||
| 61 | + </view> | ||
| 62 | + <view style="width:100%;display:flex; color:#909399; align-items: center; gap: 2rpx;"> | ||
| 63 | + <myPiker | ||
| 64 | + :parentValue="containerVolume" | ||
| 65 | + :title="'车辆容积'" | ||
| 66 | + @change="handleContainerVolumeChange" | ||
| 67 | + :array="containerVolumeList"> | ||
| 68 | + </myPiker> | ||
| 69 | + </view> | ||
| 70 | + </view> | ||
| 66 | 71 | ||
| 67 | <view class="company-clean-container-car-main-content-type"> | 72 | <view class="company-clean-container-car-main-content-type"> |
| 68 | <view class="company-clean-container-car-main-content-type-price-area"> | 73 | <view class="company-clean-container-car-main-content-type-price-area"> |
| @@ -245,6 +250,7 @@ | @@ -245,6 +250,7 @@ | ||
| 245 | const carPopupShowFlag = ref(false) | 250 | const carPopupShowFlag = ref(false) |
| 246 | const addressPopupRef = ref(null); | 251 | const addressPopupRef = ref(null); |
| 247 | const swiperClass = ref("swiperHeight1") | 252 | const swiperClass = ref("swiperHeight1") |
| 253 | + const containerVolumeList = ref([]) | ||
| 248 | const pageStyle = ref("") | 254 | const pageStyle = ref("") |
| 249 | const userAddress = ref({ | 255 | const userAddress = ref({ |
| 250 | garUserContactName: "", | 256 | garUserContactName: "", |
| @@ -403,11 +409,23 @@ | @@ -403,11 +409,23 @@ | ||
| 403 | garCarInfoList.value = res.data.rows; | 409 | garCarInfoList.value = res.data.rows; |
| 404 | if (garCarInfoList.value[0]) { | 410 | if (garCarInfoList.value[0]) { |
| 405 | carName.value = garCarInfoList.value[0].carType; | 411 | carName.value = garCarInfoList.value[0].carType; |
| 406 | - containerVolume.value = garCarInfoList.value[0].containerVolume; | 412 | + containerVolume.value = garCarInfoList.value[0].containerVolume +"方"; |
| 407 | } | 413 | } |
| 414 | + | ||
| 415 | + const volumeSet = new Set(); | ||
| 416 | + garCarInfoList.value.forEach(car => { | ||
| 417 | + if (car.containerVolume) { | ||
| 418 | + volumeSet.add(car.containerVolume +"方"); | ||
| 419 | + } | ||
| 420 | + }); | ||
| 421 | + containerVolumeList.value = Array.from(volumeSet); | ||
| 408 | }) | 422 | }) |
| 409 | } | 423 | } |
| 410 | 424 | ||
| 425 | + const handleContainerVolumeChange = (value) => { | ||
| 426 | + containerVolume.value = value; | ||
| 427 | + } | ||
| 428 | + | ||
| 411 | const handleInCarClick = (val) => { | 429 | const handleInCarClick = (val) => { |
| 412 | // paramFrom.value.garInCarStore = !paramFrom.value.garInCarStore | 430 | // paramFrom.value.garInCarStore = !paramFrom.value.garInCarStore |
| 413 | } | 431 | } |
| @@ -500,6 +518,8 @@ | @@ -500,6 +518,8 @@ | ||
| 500 | carTypeShowFlag.value = false | 518 | carTypeShowFlag.value = false |
| 501 | } | 519 | } |
| 502 | 520 | ||
| 521 | + | ||
| 522 | + | ||
| 503 | const orderClick = ref(true) | 523 | const orderClick = ref(true) |
| 504 | /** | 524 | /** |
| 505 | * 处理下单 | 525 | * 处理下单 |
| @@ -613,6 +633,7 @@ | @@ -613,6 +633,7 @@ | ||
| 613 | const handlerSaveOrder = async (params) => { | 633 | const handlerSaveOrder = async (params) => { |
| 614 | await saveOrder(params).then(res => { | 634 | await saveOrder(params).then(res => { |
| 615 | if (res.data.success) { | 635 | if (res.data.success) { |
| 636 | + store.updateUnreadOrderCount(); | ||
| 616 | if (userType.value != "用户") { | 637 | if (userType.value != "用户") { |
| 617 | uni.$u.toast("下单成功,请切换成且角色查看订单详情") | 638 | uni.$u.toast("下单成功,请切换成且角色查看订单详情") |
| 618 | uni.$u.route({ | 639 | uni.$u.route({ |
| @@ -631,6 +652,7 @@ | @@ -631,6 +652,7 @@ | ||
| 631 | } | 652 | } |
| 632 | } | 653 | } |
| 633 | }) | 654 | }) |
| 655 | + | ||
| 634 | } | 656 | } |
| 635 | 657 | ||
| 636 | const handlerChooseAddress = () => { | 658 | const handlerChooseAddress = () => { |
garbage-removal/src/pages/home/index.vue
| @@ -131,6 +131,7 @@ import { queryRole } from "@/apis/user"; | @@ -131,6 +131,7 @@ import { queryRole } from "@/apis/user"; | ||
| 131 | import { useMainStore } from "@/stores/index.js"; | 131 | import { useMainStore } from "@/stores/index.js"; |
| 132 | import { onLoad, onShow } from '@dcloudio/uni-app'; | 132 | import { onLoad, onShow } from '@dcloudio/uni-app'; |
| 133 | import { computed, ref } from 'vue'; | 133 | import { computed, ref } from 'vue'; |
| 134 | +import {queryOrderList} from "@/apis/order"; | ||
| 134 | const searchKeyword = ref('') | 135 | const searchKeyword = ref('') |
| 135 | const mainStore = useMainStore() | 136 | const mainStore = useMainStore() |
| 136 | const userType = computed(() => mainStore.userType); | 137 | const userType = computed(() => mainStore.userType); |
| @@ -405,6 +406,7 @@ onLoad(() => { | @@ -405,6 +406,7 @@ onLoad(() => { | ||
| 405 | onShow(() => { | 406 | onShow(() => { |
| 406 | // 初始化数据 | 407 | // 初始化数据 |
| 407 | initData() | 408 | initData() |
| 409 | + updateOrderBadge() | ||
| 408 | let flag = uni.getStorageSync("refreshFlag"); | 410 | let flag = uni.getStorageSync("refreshFlag"); |
| 409 | if(flag){ | 411 | if(flag){ |
| 410 | console.log(paging.value); | 412 | console.log(paging.value); |
| @@ -413,6 +415,32 @@ onShow(() => { | @@ -413,6 +415,32 @@ onShow(() => { | ||
| 413 | } | 415 | } |
| 414 | }) | 416 | }) |
| 415 | 417 | ||
| 418 | +const updateOrderBadge = async () => { | ||
| 419 | + try { | ||
| 420 | + const res = await getOrderCountByType(0); | ||
| 421 | + await uni.setTabBarBadge({ | ||
| 422 | + index: 1, // 订单tab在tabBar中的索引 | ||
| 423 | + text: String(res.data.data.total) | ||
| 424 | + }); | ||
| 425 | + } catch (error) { | ||
| 426 | + console.error('获取订单数量失败:', error); | ||
| 427 | + } | ||
| 428 | +}; | ||
| 429 | + | ||
| 430 | +// 根据订单类型获取订单总数 | ||
| 431 | +const getOrderCountByType = async (type) => { | ||
| 432 | + try { | ||
| 433 | + return await queryOrderList({ | ||
| 434 | + type: type, | ||
| 435 | + pageNo: 1, | ||
| 436 | + pageSize: 1 | ||
| 437 | + }); | ||
| 438 | + } catch (error) { | ||
| 439 | + console.error('获取订单数量失败:', error); | ||
| 440 | + throw error; | ||
| 441 | + } | ||
| 442 | +} | ||
| 443 | + | ||
| 416 | const refreshPage = () => { | 444 | const refreshPage = () => { |
| 417 | initData(); | 445 | initData(); |
| 418 | } | 446 | } |
garbage-removal/src/pages/login/code.vue
| @@ -18,10 +18,16 @@ | @@ -18,10 +18,16 @@ | ||
| 18 | > | 18 | > |
| 19 | 密码登录 | 19 | 密码登录 |
| 20 | </text> | 20 | </text> |
| 21 | + <text | ||
| 22 | + :class="{ active: loginType === 'nickname' }" | ||
| 23 | + @click="switchLoginType('nickname')" | ||
| 24 | + > | ||
| 25 | + 用户名登录 | ||
| 26 | + </text> | ||
| 21 | </view> | 27 | </view> |
| 22 | 28 | ||
| 23 | <!-- 手机号输入 --> | 29 | <!-- 手机号输入 --> |
| 24 | - <view class="input-wrapper"> | 30 | + <view class="input-wrapper" v-if="loginType !== 'nickname'"> |
| 25 | <u-icon name="account" size="36" color="#909399" class="input-icon"></u-icon> | 31 | <u-icon name="account" size="36" color="#909399" class="input-icon"></u-icon> |
| 26 | <input | 32 | <input |
| 27 | class="login-input" | 33 | class="login-input" |
| @@ -50,6 +56,30 @@ | @@ -50,6 +56,30 @@ | ||
| 50 | </view> | 56 | </view> |
| 51 | </view> | 57 | </view> |
| 52 | 58 | ||
| 59 | + <view v-else-if="loginType === 'nickname'"> | ||
| 60 | + <view class="input-wrapper"> | ||
| 61 | + <u-icon name="account" size="36" color="#909399" class="input-icon"></u-icon> | ||
| 62 | + <input | ||
| 63 | + class="login-input" | ||
| 64 | + type="text" | ||
| 65 | + v-model="nickname" | ||
| 66 | + placeholder="请输入用户名" | ||
| 67 | + placeholder-class="placeholder-style" | ||
| 68 | + /> | ||
| 69 | + </view> | ||
| 70 | + <view class="input-wrapper"> | ||
| 71 | + <u-icon name="lock" size="36" color="#909399" class="input-icon"></u-icon> | ||
| 72 | + <input | ||
| 73 | + class="login-input" | ||
| 74 | + type="password" | ||
| 75 | + v-model="password" | ||
| 76 | + placeholder="请输入密码" | ||
| 77 | + placeholder-class="placeholder-style" | ||
| 78 | + /> | ||
| 79 | + </view> | ||
| 80 | + <button @tap="loginWithUsername" class="login-btn">登录</button> | ||
| 81 | + </view> | ||
| 82 | + | ||
| 53 | <!-- 密码登录 --> | 83 | <!-- 密码登录 --> |
| 54 | <view v-else> | 84 | <view v-else> |
| 55 | <view class="input-wrapper"> | 85 | <view class="input-wrapper"> |
| @@ -67,7 +97,7 @@ | @@ -67,7 +97,7 @@ | ||
| 67 | 97 | ||
| 68 | <view class="alternative"> | 98 | <view class="alternative"> |
| 69 | <text class="link" @click="toRegister">立即注册</text> | 99 | <text class="link" @click="toRegister">立即注册</text> |
| 70 | - <text class="link" @click="forgetPassword">忘记密码?</text> | 100 | + <text class="link" @click="toChangePassword">修改密码</text> |
| 71 | </view> | 101 | </view> |
| 72 | </view> | 102 | </view> |
| 73 | </view> | 103 | </view> |
| @@ -93,6 +123,7 @@ const maxlength = ref(4); | @@ -93,6 +123,7 @@ const maxlength = ref(4); | ||
| 93 | const codeValue = ref(""); | 123 | const codeValue = ref(""); |
| 94 | const second = ref(0); | 124 | const second = ref(0); |
| 95 | const show = ref(true); | 125 | const show = ref(true); |
| 126 | +const nickname = ref(""); | ||
| 96 | 127 | ||
| 97 | // 密码登录相关 | 128 | // 密码登录相关 |
| 98 | const password = ref(""); | 129 | const password = ref(""); |
| @@ -102,6 +133,27 @@ const switchLoginType = (type) => { | @@ -102,6 +133,27 @@ const switchLoginType = (type) => { | ||
| 102 | loginType.value = type; | 133 | loginType.value = type; |
| 103 | }; | 134 | }; |
| 104 | 135 | ||
| 136 | +const loginWithUsername = () => { | ||
| 137 | + if (!nickname.value) { | ||
| 138 | + proxy.$u.toast("请输入用户名"); | ||
| 139 | + return; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + if (!password.value) { | ||
| 143 | + proxy.$u.toast("请输入密码"); | ||
| 144 | + return; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + userLogin({ | ||
| 148 | + loginType: 0, | ||
| 149 | + signIn:0, | ||
| 150 | + nickname: nickname.value, | ||
| 151 | + password: password.value | ||
| 152 | + }).then(res => { | ||
| 153 | + handleLoginSuccess(res); | ||
| 154 | + }); | ||
| 155 | +}; | ||
| 156 | + | ||
| 105 | // 获取验证码 | 157 | // 获取验证码 |
| 106 | const getCaptcha = () => { | 158 | const getCaptcha = () => { |
| 107 | if (!proxy.$u.test.mobile(iphoneNumber.value)) { | 159 | if (!proxy.$u.test.mobile(iphoneNumber.value)) { |
| @@ -138,6 +190,13 @@ const finish = (value) => { | @@ -138,6 +190,13 @@ const finish = (value) => { | ||
| 138 | } | 190 | } |
| 139 | }; | 191 | }; |
| 140 | 192 | ||
| 193 | +// 跳转到修改密码页面 | ||
| 194 | +const toChangePassword = () => { | ||
| 195 | + uni.$u.route({ | ||
| 196 | + url: 'pages/change-password/index' | ||
| 197 | + }); | ||
| 198 | +}; | ||
| 199 | + | ||
| 141 | // 验证码登录 | 200 | // 验证码登录 |
| 142 | const checkVerifyNum = (code) => { | 201 | const checkVerifyNum = (code) => { |
| 143 | userLogin({ loginType: 0, tel: iphoneNumber.value, code: code }).then(res => { | 202 | userLogin({ loginType: 0, tel: iphoneNumber.value, code: code }).then(res => { |
| @@ -325,6 +384,18 @@ const handleIphoneNumber = (tel) => { | @@ -325,6 +384,18 @@ const handleIphoneNumber = (tel) => { | ||
| 325 | } | 384 | } |
| 326 | } | 385 | } |
| 327 | 386 | ||
| 387 | +.alternative { | ||
| 388 | + color: $u-tips-color; | ||
| 389 | + display: flex; | ||
| 390 | + justify-content: space-between; | ||
| 391 | + margin-top: 60rpx; | ||
| 392 | + | ||
| 393 | + .link { | ||
| 394 | + color: $u-warning; | ||
| 395 | + cursor: pointer; | ||
| 396 | + } | ||
| 397 | +} | ||
| 398 | + | ||
| 328 | .placeholder-style { | 399 | .placeholder-style { |
| 329 | color: #c0c4cc; | 400 | color: #c0c4cc; |
| 330 | font-size: 26rpx; | 401 | font-size: 26rpx; |
garbage-removal/src/pages/order-info/order-disposal/scan-detail/index.vue
| @@ -247,7 +247,7 @@ | @@ -247,7 +247,7 @@ | ||
| 247 | // 修改提示框,添加跳转到订单页面的选项 | 247 | // 修改提示框,添加跳转到订单页面的选项 |
| 248 | uni.showModal({ | 248 | uni.showModal({ |
| 249 | title: '提示', | 249 | title: '提示', |
| 250 | - content: '当前趟次记录完毕!需要进入订单详情页面点击"完成订单"按钮才是最终完成订单。', | 250 | + content: '当前趟次记录完毕!', |
| 251 | showCancel: true, | 251 | showCancel: true, |
| 252 | cancelText: '稍后处理', | 252 | cancelText: '稍后处理', |
| 253 | confirmText: '立即前往', | 253 | confirmText: '立即前往', |
garbage-removal/src/pages/order-info/order-disposal/transport-detail/index.vue
| @@ -100,11 +100,11 @@ | @@ -100,11 +100,11 @@ | ||
| 100 | <view class="space-box">{{ spaceStr }}</view> | 100 | <view class="space-box">{{ spaceStr }}</view> |
| 101 | </view> | 101 | </view> |
| 102 | <!-- 占位符 --> | 102 | <!-- 占位符 --> |
| 103 | - <view class="order-detail-bottom" v-if="dataGram.garOrderDisposalStatus === 1 && transportWeightCount > 0"> | ||
| 104 | - <view class="order-detail-bottom-box"> | ||
| 105 | - <u-button @click="handlerOrderSuccess(orderId)" shape="square" color="#19a97c" text="完成订单"></u-button> | ||
| 106 | - </view> | ||
| 107 | - </view> | 103 | +<!-- <view class="order-detail-bottom" v-if="dataGram.garOrderDisposalStatus === 1 && transportWeightCount > 0">--> |
| 104 | +<!-- <view class="order-detail-bottom-box">--> | ||
| 105 | +<!-- <u-button @click="handlerOrderSuccess(orderId)" shape="square" color="#19a97c" text="完成订单"></u-button>--> | ||
| 106 | +<!-- </view>--> | ||
| 107 | +<!-- </view>--> | ||
| 108 | </view> | 108 | </view> |
| 109 | </template> | 109 | </template> |
| 110 | 110 |
garbage-removal/src/pages/order-info/order-disposal/transport-detail/tempfile_1760595387127.vue
0 → 100644
| 1 | +<view class="transport-process-item" style="display: flex; width: 100%; margin: 20rpx 0; flex-wrap: nowrap; align-items: center;"> | ||
| 2 | + <view style="width: 80rpx; flex-shrink: 0; margin-right: 10rpx;"> | ||
| 3 | + <up-image :show-loading="true" :src="item.fillImage" width="80rpx" height="80rpx"></up-image> | ||
| 4 | + </view> | ||
| 5 | + <view style="width: 120rpx; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-right: 10rpx;"> | ||
| 6 | + <view style="font-size: 25rpx; white-space: nowrap;"> | ||
| 7 | + 载重: {{ item.garCarryingWeight }}吨 | ||
| 8 | + </view> | ||
| 9 | + </view> | ||
| 10 | + <view style="width: 80rpx; display: flex; align-items: center; justify-content: center; font-size: 25rpx; margin-right: 10rpx;"> | ||
| 11 | + <view style="transform: rotateY(180deg);"> | ||
| 12 | + <up-icon name="car-fill" size="40" color="#19a97c"></up-icon> | ||
| 13 | + </view> | ||
| 14 | + </view> | ||
| 15 | + <view style="width: 80rpx; display: flex; justify-content: center; align-items: center; font-size: 25rpx; margin-right: 10rpx;"> | ||
| 16 | + <view>{{ (index + 1) + '/' + dataGram.garRealCarCount }}</view> | ||
| 17 | + </view> | ||
| 18 | + <view style="flex: 1; display: flex; align-items: center; margin-right: 10rpx; overflow: hidden;"> | ||
| 19 | + <view style="display: flex; justify-content: flex-start; align-items: center; font-size: 25rpx; overflow: hidden;"> | ||
| 20 | + <view style="margin-right: 4rpx; flex-shrink: 0;"> | ||
| 21 | + 车牌: | ||
| 22 | + </view> | ||
| 23 | + <view style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> | ||
| 24 | + {{ item.garHandlerCarCode }} | ||
| 25 | + </view> | ||
| 26 | + </view> | ||
| 27 | + </view> | ||
| 28 | + <view style="width: 100rpx; display: flex; align-items: center; justify-content: flex-end;" | ||
| 29 | + @click="goTransportDetail(item)"> | ||
| 30 | + <text style="font-size: 30rpx; white-space: nowrap; margin-right: 15rpx; color: #19a97c;">详情</text> | ||
| 31 | + <up-icon name="arrow-right" size="30" color="#19a97c"></up-icon> | ||
| 32 | + </view> | ||
| 33 | +</view> |
garbage-removal/src/pages/order-info/order-driver/detail/index.vue
| @@ -226,7 +226,7 @@ | @@ -226,7 +226,7 @@ | ||
| 226 | </template> | 226 | </template> |
| 227 | 227 | ||
| 228 | <script setup> | 228 | <script setup> |
| 229 | -import { createHandlerQrCode, queryOrderDetail, updateOrder } from "@/apis/order.js"; | 229 | +import {createHandlerQrCode, queryGarOrderMatchAsk, queryOrderDetail, updateOrder} from "@/apis/order.js"; |
| 230 | import { createQrCode } from '@/apis/qrcode.js'; | 230 | import { createQrCode } from '@/apis/qrcode.js'; |
| 231 | import uqrcode from '@/components/Sansnn-uQRCode_4.0.6/components/uqrcode/uqrcode.vue'; | 231 | import uqrcode from '@/components/Sansnn-uQRCode_4.0.6/components/uqrcode/uqrcode.vue'; |
| 232 | import zStatic from '@/components/z-paging/js/z-paging-static'; | 232 | import zStatic from '@/components/z-paging/js/z-paging-static'; |
| @@ -456,20 +456,47 @@ const createQrCodeValid = (val) => { | @@ -456,20 +456,47 @@ const createQrCodeValid = (val) => { | ||
| 456 | */ | 456 | */ |
| 457 | 457 | ||
| 458 | const handleUploadImage = (orderId, putType) => { | 458 | const handleUploadImage = (orderId, putType) => { |
| 459 | - const data = dataGram.value; | ||
| 460 | - uni.showActionSheet({ | ||
| 461 | - itemList: ['上传装车图片'], | ||
| 462 | - success: function (res) { | ||
| 463 | - console.log('选中了第' + (res.tapIndex + 1) + '个按钮'); | ||
| 464 | - if(res.tapIndex === 0){ | ||
| 465 | - uni.$u.route(`pages/order-info/order-driver/upload/index?orderId=${orderId}&carPlate=${data.garHandlerCarCode}&driver=${store.userInfo.userName}&putType=putOnImages`) | 459 | + const data = dataGram.value; |
| 460 | + | ||
| 461 | + // 查询运输趟次 | ||
| 462 | + queryGarOrderMatchAsk(orderId).then(res => { | ||
| 463 | + console.log(res.data.success+"sssss") | ||
| 464 | + // 正确处理响应数据 | ||
| 465 | + if (res && res.data) { | ||
| 466 | + if (res.data.success) { | ||
| 467 | + let number = res.data.data; | ||
| 468 | + | ||
| 469 | + // 检查当前要上传的是第几趟 | ||
| 470 | + const currentGroupIndex = putOnImagesGrouped.value.length + 1; | ||
| 471 | + | ||
| 472 | + // 如果当前趟次大于上一趟次+1,说明上一趟次未完成 | ||
| 473 | + if (currentGroupIndex > number) { | ||
| 474 | + uni.$u.toast('上一趟次未扫码'); | ||
| 475 | + return; | ||
| 476 | + } | ||
| 477 | + | ||
| 478 | + uni.showActionSheet({ | ||
| 479 | + itemList: ['上传装车图片'], | ||
| 480 | + success: function (res) { | ||
| 481 | + console.log('选中了第' + (res.tapIndex + 1) + '个按钮'); | ||
| 482 | + if(res.tapIndex === 0){ | ||
| 483 | + uni.$u.route(`pages/order-info/order-driver/upload/index?orderId=${orderId}&carPlate=${data.garHandlerCarCode}&driver=${store.userInfo.userName}&putType=putOnImages`) | ||
| 484 | + } | ||
| 485 | + }, | ||
| 486 | + fail: function (res) { | ||
| 487 | + console.log(res.errMsg); | ||
| 488 | + } | ||
| 489 | + }); | ||
| 490 | + } else { | ||
| 491 | + uni.$u.toast(res.data.msg || '查询运输趟次失败'); | ||
| 466 | } | 492 | } |
| 467 | - }, | ||
| 468 | - fail: function (res) { | ||
| 469 | - console.log(res.errMsg); | 493 | + } else { |
| 494 | + uni.$u.toast('查询运输趟次失败,数据格式错误'); | ||
| 470 | } | 495 | } |
| 496 | + }).catch(error => { | ||
| 497 | + console.error('查询运输趟次失败:', error); | ||
| 498 | + uni.$u.toast('查询运输趟次失败'); | ||
| 471 | }); | 499 | }); |
| 472 | - // uni.$u.route(`pages/order-info/order-driver/upload/index?orderId=${orderId}&carPlate=${data.garHandlerCarCode}&driver=${store.userInfo.userName}`) | ||
| 473 | } | 500 | } |
| 474 | 501 | ||
| 475 | /** | 502 | /** |
garbage-removal/src/pages/order-info/order-other/detail/index.vue
| @@ -229,6 +229,11 @@ | @@ -229,6 +229,11 @@ | ||
| 229 | @click="handleOrderDispatchClick(orderId)" shape="square" color="#19a97c" | 229 | @click="handleOrderDispatchClick(orderId)" shape="square" color="#19a97c" |
| 230 | text="分配驾驶员"></u-button> | 230 | text="分配驾驶员"></u-button> |
| 231 | </view> | 231 | </view> |
| 232 | + | ||
| 233 | + <view class="order-detail-bottom-center" v-if="dataGram.garOrderHandlerStatus === 1 && userType == '运输企业负责人'"> | ||
| 234 | + <u-button @click="handleSubmitSuccess(orderId)" shape="square" color="#19a97c" text="完成订单"></u-button> | ||
| 235 | + </view> | ||
| 236 | + | ||
| 232 | <view class="order-detail-bottom-right"> | 237 | <view class="order-detail-bottom-right"> |
| 233 | <u-button | 238 | <u-button |
| 234 | v-if="dataGram.garOrderHandlerStatus === 0 && userType == '用户' && dataGram.garCancelFlag === 0" | 239 | v-if="dataGram.garOrderHandlerStatus === 0 && userType == '用户' && dataGram.garCancelFlag === 0" |
| @@ -252,6 +257,7 @@ | @@ -252,6 +257,7 @@ | ||
| 252 | @click="handleDisposalDispatchClick(orderId)" shape="square" color="#19a97c" | 257 | @click="handleDisposalDispatchClick(orderId)" shape="square" color="#19a97c" |
| 253 | text="分配处置场所"></u-button> | 258 | text="分配处置场所"></u-button> |
| 254 | </view> | 259 | </view> |
| 260 | + | ||
| 255 | </view> | 261 | </view> |
| 256 | </view> | 262 | </view> |
| 257 | <u-action-sheet :closeOnClickOverlay="true" :closeOnClickAction="false" @actionSheetClose="handleClose" | 263 | <u-action-sheet :closeOnClickOverlay="true" :closeOnClickAction="false" @actionSheetClose="handleClose" |
| @@ -821,6 +827,7 @@ const handleDriverDispatchConfirm = (val) => { | @@ -821,6 +827,7 @@ const handleDriverDispatchConfirm = (val) => { | ||
| 821 | </script> | 827 | </script> |
| 822 | 828 | ||
| 823 | <style lang="scss" scoped> | 829 | <style lang="scss" scoped> |
| 830 | + | ||
| 824 | $custom-marin-bottom: 20rpx; | 831 | $custom-marin-bottom: 20rpx; |
| 825 | $custom-page-padding: 20rpx; | 832 | $custom-page-padding: 20rpx; |
| 826 | $custom-border-radio: 20rpx; | 833 | $custom-border-radio: 20rpx; |
| @@ -834,6 +841,27 @@ const handleDriverDispatchConfirm = (val) => { | @@ -834,6 +841,27 @@ const handleDriverDispatchConfirm = (val) => { | ||
| 834 | margin-bottom: $custom-marin-bottom; | 841 | margin-bottom: $custom-marin-bottom; |
| 835 | } | 842 | } |
| 836 | 843 | ||
| 844 | + .order-detail-bottom-box { | ||
| 845 | + height: $custom-bottom-height; | ||
| 846 | + padding: 50rpx; | ||
| 847 | + box-sizing: border-box; | ||
| 848 | + display: flex; | ||
| 849 | + justify-content: space-between; | ||
| 850 | + align-items: center; | ||
| 851 | + | ||
| 852 | + .order-detail-bottom-left { | ||
| 853 | + min-width: 200rpx; | ||
| 854 | + } | ||
| 855 | + | ||
| 856 | + .order-detail-bottom-center { | ||
| 857 | + min-width: 200rpx; | ||
| 858 | + } | ||
| 859 | + | ||
| 860 | + .order-detail-bottom-right { | ||
| 861 | + min-width: 200rpx; | ||
| 862 | + } | ||
| 863 | + } | ||
| 864 | + | ||
| 837 | .order-detail-container { | 865 | .order-detail-container { |
| 838 | height: 100%; | 866 | height: 100%; |
| 839 | width: 100%; | 867 | width: 100%; |
garbage-removal/src/pages/order/order-disposal/index.vue
| @@ -50,10 +50,12 @@ | @@ -50,10 +50,12 @@ | ||
| 50 | 50 | ||
| 51 | <script setup> | 51 | <script setup> |
| 52 | import QrScannerVue from '../../../components/QrScanner/QrScanner.vue'; | 52 | import QrScannerVue from '../../../components/QrScanner/QrScanner.vue'; |
| 53 | -import { checkCode, queryOrderList } from '@/apis/order.js'; | ||
| 54 | -import { nextTick, onMounted, ref, computed } from 'vue'; | 53 | +import {checkCode, queryOrderList, querySiteByTel} from '@/apis/order.js'; |
| 54 | +import {computed, nextTick, onMounted, ref} from 'vue'; | ||
| 55 | import swiperListItem from './swiper-list-item/index.vue'; | 55 | import swiperListItem from './swiper-list-item/index.vue'; |
| 56 | -import { useMainStore } from '@/stores'; | 56 | +import {useMainStore} from '@/stores'; |
| 57 | +import {onLoad} from "@dcloudio/uni-app"; | ||
| 58 | + | ||
| 57 | const list = ref([{ | 59 | const list = ref([{ |
| 58 | name: '处理中', | 60 | name: '处理中', |
| 59 | count: 0 | 61 | count: 0 |
| @@ -69,6 +71,7 @@ const topMargin = ref(); | @@ -69,6 +71,7 @@ const topMargin = ref(); | ||
| 69 | const lightHeight = ref(); | 71 | const lightHeight = ref(); |
| 70 | const store = useMainStore(); | 72 | const store = useMainStore(); |
| 71 | const showScan = ref(false); | 73 | const showScan = ref(false); |
| 74 | +const location = ref({}); | ||
| 72 | 75 | ||
| 73 | // 创建计算属性用于显示带数量的标题 | 76 | // 创建计算属性用于显示带数量的标题 |
| 74 | const displayList = computed(() => { | 77 | const displayList = computed(() => { |
| @@ -131,54 +134,94 @@ const handleScan = () => { | @@ -131,54 +134,94 @@ const handleScan = () => { | ||
| 131 | } | 134 | } |
| 132 | }); | 135 | }); |
| 133 | } | 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 | + | ||
| 134 | 160 | ||
| 135 | -const handleScanH5 = () => { | 161 | +const handleScanH5 = async () => { |
| 136 | showScan.value = true; | 162 | showScan.value = true; |
| 137 | - // uni.chooseImage({ | ||
| 138 | - // count: 1, | ||
| 139 | - // sizeType: ['original', 'compressed'], | ||
| 140 | - // sourceType: ['camera', 'album'], | ||
| 141 | - // success: (res) => { | ||
| 142 | - // console.log(res.tempFilePaths[0]); | ||
| 143 | - // uni.uploadFile({ | ||
| 144 | - // url: import.meta.env.VITE_BASE_URL + "/QRCode/ocr/pric", | ||
| 145 | - // header: { | ||
| 146 | - // "Authorization": store.token | ||
| 147 | - // }, | ||
| 148 | - // fileType: 'image', | ||
| 149 | - // filePath: res.tempFilePaths[0], | ||
| 150 | - // name: 'file', | ||
| 151 | - // success: (uploadRes) => { | ||
| 152 | - // if (uploadRes.statusCode == 200) { | ||
| 153 | - // if ("" == uploadRes.data || undefined == uploadRes.data || null == | ||
| 154 | - // uploadRes.data) { | ||
| 155 | - // uni.$u.toast("二维码图片识别失败,请检查二维码图片"); | ||
| 156 | - // return; | ||
| 157 | - // } else { | ||
| 158 | - // checkCode(uploadRes.data).then(res => { | ||
| 159 | - // if (res.data && res.data.code == 200) { | ||
| 160 | - // uni.$u.route({ | ||
| 161 | - // url: `pages/order-info/order-disposal/scan-detail/index`, | ||
| 162 | - // params: { | ||
| 163 | - // data: encodeURIComponent(JSON | ||
| 164 | - // .stringify(res.data | ||
| 165 | - // .data)) | ||
| 166 | - // } | ||
| 167 | - // }) | ||
| 168 | - // return | ||
| 169 | - // } | ||
| 170 | - // uni.$u.toast(res.data.msg); | ||
| 171 | - // }) | ||
| 172 | - // } | ||
| 173 | - // } else { | ||
| 174 | - // uni.$u.toast("二维码图片识别失败,请检查二维码图片"); | ||
| 175 | - // } | ||
| 176 | - | ||
| 177 | - // } | ||
| 178 | - // }) | ||
| 179 | - | ||
| 180 | - // } | ||
| 181 | - // }) | 163 | + |
| 164 | + // try { | ||
| 165 | + // const isValidLocation = await validateUnloadingSite(location.value); | ||
| 166 | + // | ||
| 167 | + // if (!isValidLocation) { | ||
| 168 | + // uni.$u.toast("您当前不在有效的卸货地址范围内"); | ||
| 169 | + // return; | ||
| 170 | + // } | ||
| 171 | + // showScan.value = true; | ||
| 172 | + // } catch (error) { | ||
| 173 | + // console.error('位置验证失败:', error); | ||
| 174 | + // if (error.message.includes("用户拒绝")) { | ||
| 175 | + // uni.$u.toast("请允许访问位置信息以验证卸货地址"); | ||
| 176 | + // } else if (error.message.includes("安全来源")) { | ||
| 177 | + // uni.$u.toast("当前环境不支持位置验证,请使用HTTPS访问"); | ||
| 178 | + // } else { | ||
| 179 | + // uni.$u.toast("位置验证失败: " + error.message); | ||
| 180 | + // } | ||
| 181 | + // } | ||
| 182 | +} | ||
| 183 | + | ||
| 184 | + | ||
| 185 | +const validateUnloadingSite = async (location) => { | ||
| 186 | + try { | ||
| 187 | + const res = await querySiteByTel(); | ||
| 188 | + const siteData = res.data.data; // 获取 SiteInfoDTO 对象 | ||
| 189 | + | ||
| 190 | + // 确保 siteData 是数组,如果不是则包装成数组 | ||
| 191 | + const sites = Array.isArray(siteData) ? siteData : [siteData]; | ||
| 192 | + | ||
| 193 | + return sites.some(site => { | ||
| 194 | + // 注意:SiteInfoDTO 的字段名是 garLongitude 和 garLatitude | ||
| 195 | + const distance = calculateDistance( | ||
| 196 | + location.latitude, | ||
| 197 | + location.longitude, | ||
| 198 | + site.garLatitude, // 使用 garLatitude | ||
| 199 | + site.garLongitude // 使用 garLongitude | ||
| 200 | + ); | ||
| 201 | + console.log(distance) | ||
| 202 | + return distance <= 200; // 200米范围内 | ||
| 203 | + }); | ||
| 204 | + } catch (error) { | ||
| 205 | + console.error('验证卸货地址失败:', error); | ||
| 206 | + return false; | ||
| 207 | + } | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +// 计算两点间距离(单位:米) | ||
| 211 | +const calculateDistance = (lat1, lng1, lat2, lng2) => { | ||
| 212 | + const radLat1 = (lat1 * Math.PI) / 180; | ||
| 213 | + const radLat2 = (lat2 * Math.PI) / 180; | ||
| 214 | + const deltaRadLat = radLat1 - radLat2; | ||
| 215 | + const deltaRadLng = (lng1 * Math.PI) / 180 - (lng2 * Math.PI) / 180; | ||
| 216 | + | ||
| 217 | + const distance = 2 * Math.asin( | ||
| 218 | + Math.sqrt( | ||
| 219 | + Math.pow(Math.sin(deltaRadLat / 2), 2) + | ||
| 220 | + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(deltaRadLng / 2), 2) | ||
| 221 | + ) | ||
| 222 | + ); | ||
| 223 | + | ||
| 224 | + return distance * 6371000; // 地球半径(米) | ||
| 182 | } | 225 | } |
| 183 | 226 | ||
| 184 | const onDecodeHandler = (data) => { | 227 | const onDecodeHandler = (data) => { |
garbage-removal/src/pages/sign-up/index.vue
| @@ -162,7 +162,7 @@ export default { | @@ -162,7 +162,7 @@ export default { | ||
| 162 | loginType: 0, | 162 | loginType: 0, |
| 163 | signin: 1, | 163 | signin: 1, |
| 164 | tel: this.tel, | 164 | tel: this.tel, |
| 165 | - nikename: this.nickname, | 165 | + nickname: this.nickname, |
| 166 | password: this.password | 166 | password: this.password |
| 167 | }).then(res => { | 167 | }).then(res => { |
| 168 | console.log('注册成功', res); | 168 | console.log('注册成功', res); |
garbage-removal/src/stores/main.js
| 1 | import { defineStore } from 'pinia'; | 1 | import { defineStore } from 'pinia'; |
| 2 | import { ref } from 'vue'; | 2 | import { ref } from 'vue'; |
| 3 | +import {queryOrderList} from "@/apis/order"; | ||
| 3 | export const useMainStore = defineStore( | 4 | export const useMainStore = defineStore( |
| 4 | "main", | 5 | "main", |
| 5 | () => { | 6 | () => { |
| @@ -10,8 +11,39 @@ export const useMainStore = defineStore( | @@ -10,8 +11,39 @@ export const useMainStore = defineStore( | ||
| 10 | // 或者保留初始对象定义,添加数据验证 | 11 | // 或者保留初始对象定义,添加数据验证 |
| 11 | const userPhone = ref(""); | 12 | const userPhone = ref(""); |
| 12 | const userName = ref(""); | 13 | const userName = ref(""); |
| 14 | + const unreadOrderCount = ref(0); | ||
| 15 | + const setUnreadOrderCount = (count) => { | ||
| 16 | + unreadOrderCount.value = count; | ||
| 17 | + }; | ||
| 18 | + const updateUnreadOrderCount = async () => { | ||
| 19 | + try { | ||
| 20 | + const res = await queryOrderList({ type: 0, pageNo: 1, pageSize: 1 }); | ||
| 21 | + const count = res.data.data.total || 0; | ||
| 13 | 22 | ||
| 14 | - return { token,tempToken,userType,userInfo,userPhone,userName }; | 23 | + // 更新状态 |
| 24 | + setUnreadOrderCount(count); | ||
| 25 | + | ||
| 26 | + // 更新 tabBar 角标 | ||
| 27 | + await uni.setTabBarBadge({ | ||
| 28 | + index: 1, | ||
| 29 | + text: String(count) | ||
| 30 | + }); | ||
| 31 | + | ||
| 32 | + return count; | ||
| 33 | + } catch (error) { | ||
| 34 | + console.error('更新未读订单数量失败:', error); | ||
| 35 | + return 0; | ||
| 36 | + } | ||
| 37 | + }; | ||
| 38 | + // 清除订单角标 | ||
| 39 | + const clearOrderBadge = () => { | ||
| 40 | + uni.removeTabBarBadge({ | ||
| 41 | + index: 1 | ||
| 42 | + }); | ||
| 43 | + setUnreadOrderCount(0); | ||
| 44 | + }; | ||
| 45 | + | ||
| 46 | + return { token,tempToken,userType,userInfo,userPhone,userName,unreadOrderCount,setUnreadOrderCount,updateUnreadOrderCount }; | ||
| 15 | }, | 47 | }, |
| 16 | { | 48 | { |
| 17 | persist: { | 49 | persist: { |