Commit f0ec74d652d5a10dab291978081b2791c4210886
1 parent
3d474e84
大区经理派单
Showing
9 changed files
with
1091 additions
and
32 deletions
api/work-order-manage/work-order-manage.js
| ... | ... | @@ -113,15 +113,15 @@ export const workorderCreate = (data) => { |
| 113 | 113 | |
| 114 | 114 | |
| 115 | 115 | /** |
| 116 | - * 大区经理问题工单创建 | |
| 116 | + * 问题工单创建 大区经理 全域巡查员 ai经理 督查员 | |
| 117 | 117 | * @returns {Promise} |
| 118 | 118 | */ |
| 119 | -export const regionmgrWorkorderCreat = (data) => { | |
| 120 | - return post('/app-api/bpm/regionmgr/workorder',data); | |
| 119 | +export const regionmgrWorkorderCreate = (data) => { | |
| 120 | + return post('/app-api/bpm/regionmgr/workorder/create',data); | |
| 121 | 121 | }; |
| 122 | 122 | |
| 123 | 123 | /** |
| 124 | - * app端统一审批入口 -- 大区经理 | |
| 124 | + * app端统一审批入口 -- 大区经理 全域巡查员 ai经理 督查员 | |
| 125 | 125 | * @returns {Promise} |
| 126 | 126 | */ |
| 127 | 127 | export const regionmgrUniversalApproval = (params) => { | ... | ... |
common/utils/common.js
| ... | ... | @@ -44,17 +44,17 @@ export const nextStepMap = { |
| 44 | 44 | |
| 45 | 45 | |
| 46 | 46 | export const buzStatusMap = { |
| 47 | - '000' :'巡查员发起', | |
| 48 | - "210" : '养护组长退回', | |
| 49 | - "110" : '养护组长分配', | |
| 50 | - "200" : '巡查员结束工单', | |
| 51 | - "100" : '巡查员重新发起', | |
| 52 | - "220" : '养护员退回', | |
| 53 | - "120" : '养护员实施', | |
| 54 | - "130" : '养护组长验收通过', | |
| 55 | - "230" : '养护组长验收不通过', | |
| 56 | - "140" : '巡查员验收通过', | |
| 57 | - "240" : '巡查员验收不通过', | |
| 47 | + '000' :'发起', | |
| 48 | + "210" : '退回', | |
| 49 | + "110" : '分配', | |
| 50 | + "200" : '结束工单', | |
| 51 | + "100" : '重新发起', | |
| 52 | + "220" : '退回', | |
| 53 | + "120" : '实施', | |
| 54 | + "130" : '验收通过', | |
| 55 | + "230" : '验收不通过', | |
| 56 | + "140" : '验收通过', | |
| 57 | + "240" : '验收不通过', | |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | ... | ... |
pages-sub/problem/regional-order-manage/add-order.vue
| 1 | -<script lang="ts"> | |
| 2 | -import {defineComponent} from 'vue' | |
| 1 | +<template> | |
| 2 | + <view class="page-container"> | |
| 3 | + <view class="work-order-form-content commonPageLRpadding"> | |
| 4 | + <up-form | |
| 5 | + label-position="left" | |
| 6 | + :model="workOrderForm" | |
| 7 | + ref="workOrderFormRef" | |
| 8 | + labelWidth="200rpx" | |
| 9 | + > | |
| 10 | + <!-- 1. 工单位置(地图选择) --> | |
| 11 | + <up-form-item | |
| 12 | + label="工单位置" | |
| 13 | + prop="workLocation" | |
| 14 | + border-bottom | |
| 15 | + required | |
| 16 | + @click="chooseWorkLocation(); hideKeyboard()" | |
| 17 | + > | |
| 18 | + <up-input | |
| 19 | + v-model="workOrderForm.workLocation" | |
| 20 | + border="none" | |
| 21 | + readonly | |
| 22 | + suffix-icon="map-fill" | |
| 23 | + placeholder="点击选择工单位置" | |
| 24 | + ></up-input> | |
| 25 | + </up-form-item> | |
| 26 | + | |
| 27 | + <!-- 2. 工单名称(下拉框) --> | |
| 28 | + <up-form-item | |
| 29 | + label="工单名称" | |
| 30 | + prop="orderName" | |
| 31 | + border-bottom | |
| 32 | + required | |
| 33 | + @click="handleActionSheetOpen('orderName'); hideKeyboard()" | |
| 34 | + > | |
| 35 | + <up-input | |
| 36 | + v-model="workOrderForm.orderName" | |
| 37 | + disabled | |
| 38 | + disabled-color="#ffffff" | |
| 39 | + placeholder="请选择工单名称" | |
| 40 | + border="none" | |
| 41 | + ></up-input> | |
| 42 | + <template #right> | |
| 43 | + <up-icon name="arrow-right" size="16"></up-icon> | |
| 44 | + </template> | |
| 45 | + </up-form-item> | |
| 46 | + | |
| 47 | + <!-- 3. 情况描述(文本域) --> | |
| 48 | + <up-form-item | |
| 49 | + label="情况描述" | |
| 50 | + prop="problemDesc" | |
| 51 | + required | |
| 52 | + > | |
| 53 | + <up-textarea | |
| 54 | + placeholder="请输入情况描述(最多200字)" | |
| 55 | + v-model.trim="workOrderForm.problemDesc" | |
| 56 | + count | |
| 57 | + maxlength="200" | |
| 58 | + rows="4" | |
| 59 | + @blur="() => workOrderFormRef.validateField('problemDesc')" | |
| 60 | + ></up-textarea> | |
| 61 | + </up-form-item> | |
| 62 | + | |
| 63 | + <!-- 4. 问题照片 --> | |
| 64 | + <up-form-item label="问题照片" prop="problemImgs" required> | |
| 65 | + <up-upload | |
| 66 | + :file-list="problemImgs.imgList.value||[]" | |
| 67 | + @after-read="problemImgs.uploadImgs" | |
| 68 | + @delete="problemImgs.deleteImg" | |
| 69 | + multiple | |
| 70 | + :width="70" | |
| 71 | + :height="70" | |
| 72 | + :max-count="problemImgs.uploadConfig.maxCount" | |
| 73 | + :upload-text="problemImgs.uploadConfig.uploadText" | |
| 74 | + :size-type="problemImgs.uploadConfig.sizeType" | |
| 75 | + ></up-upload> | |
| 76 | + </up-form-item> | |
| 77 | + | |
| 78 | + <!-- 派单情况分组(放在问题照片下方,增加间距) --> | |
| 79 | +<!-- <up-gap height="20" bgColor="#bbb"></up-gap>--> | |
| 80 | + <view class="dispatch-group"> | |
| 81 | + <view class="dispatch-title">派单情况</view> | |
| 82 | + | |
| 83 | + <!-- 业务线单选框 --> | |
| 84 | + <up-form-item | |
| 85 | + label="业务线" | |
| 86 | + prop="busiLineCn" | |
| 87 | + border-bottom | |
| 88 | + required | |
| 89 | + > | |
| 90 | + <up-radio-group | |
| 91 | + v-model="workOrderForm.busiLineCn" | |
| 92 | + placement="row" | |
| 93 | + @change="handleBusiLineChange" | |
| 94 | + > | |
| 95 | + <up-radio | |
| 96 | + v-for="item in busiLineOptions" | |
| 97 | + :key="item.name" | |
| 98 | + :label="item.name" | |
| 99 | + :name="item.name" | |
| 100 | + ></up-radio> | |
| 101 | + </up-radio-group> | |
| 102 | + </up-form-item> | |
| 103 | + | |
| 104 | + <!-- 道路名称(下拉框) --> | |
| 105 | + <up-form-item | |
| 106 | + label="道路名称" | |
| 107 | + prop="roadName" | |
| 108 | + border-bottom | |
| 109 | + required | |
| 110 | + @click="handleActionSheetOpen('roadName'); hideKeyboard()" | |
| 111 | + > | |
| 112 | + <up-input | |
| 113 | + v-model="workOrderForm.roadName" | |
| 114 | + readonly | |
| 115 | + disabled-color="#ffffff" | |
| 116 | + placeholder="请先选择工单位置" | |
| 117 | + border="none" | |
| 118 | + ></up-input> | |
| 119 | + <template #right> | |
| 120 | + <up-icon name="arrow-right" size="16" ></up-icon> | |
| 121 | + </template> | |
| 122 | + </up-form-item> | |
| 123 | + | |
| 124 | + <!-- 紧急程度选择 --> | |
| 125 | + <up-form-item | |
| 126 | + label="紧急程度" | |
| 127 | + prop="pressingTypeName" | |
| 128 | + border-bottom | |
| 129 | + required | |
| 130 | + @click="handleActionSheetOpen('pressingType'); hideKeyboard()" | |
| 131 | + > | |
| 132 | + <up-input | |
| 133 | + v-model="workOrderForm.pressingTypeName" | |
| 134 | + disabled | |
| 135 | + disabled-color="#ffffff" | |
| 136 | + placeholder="请选择紧急程度" | |
| 137 | + border="none" | |
| 138 | + ></up-input> | |
| 139 | + <template #right> | |
| 140 | + <up-icon name="arrow-right" size="16"></up-icon> | |
| 141 | + </template> | |
| 142 | + </up-form-item> | |
| 143 | + </view> | |
| 144 | + | |
| 145 | + <!-- 5. 完成时间 --> | |
| 146 | + <up-form-item | |
| 147 | + label="希望完成时间" | |
| 148 | + prop="expectedFinishDate" | |
| 149 | + @click="show=true;hideKeyboard()" | |
| 150 | + > | |
| 151 | + <up-input | |
| 152 | + v-model="workOrderForm.expectedFinishDate" | |
| 153 | + border="none" | |
| 154 | + readonly | |
| 155 | + placeholder="点击选择时间" | |
| 156 | + ></up-input> | |
| 157 | + <template #right> | |
| 158 | + <view v-if="workOrderForm.expectedFinishDate" @click.stop> | |
| 159 | + <up-icon | |
| 160 | + name="close" | |
| 161 | + size="16" | |
| 162 | + @click.stop="clearExpectedFinishDate" | |
| 163 | + ></up-icon> | |
| 164 | + </view> | |
| 165 | + <up-icon name="arrow-right" size="16" v-else></up-icon> | |
| 166 | + </template> | |
| 167 | + </up-form-item> | |
| 168 | + </up-form> | |
| 169 | + </view> | |
| 170 | + | |
| 171 | + <!-- 底部提交按钮 --> | |
| 172 | + <view class="fixed-bottom-btn-wrap"> | |
| 173 | + <up-button | |
| 174 | + type="primary" | |
| 175 | + text="提交工单" | |
| 176 | + @click="submitWorkOrder" | |
| 177 | + ></up-button> | |
| 178 | + </view> | |
| 179 | + | |
| 180 | + <!-- 合并后的通用下拉弹窗 --> | |
| 181 | + <up-action-sheet | |
| 182 | + :show="showActionSheet" | |
| 183 | + :actions="currentActionSheetData.list" | |
| 184 | + :title="currentActionSheetData.title" | |
| 185 | + @close="handleActionSheetClose" | |
| 186 | + @select="handleActionSheetSelect" | |
| 187 | + ></up-action-sheet> | |
| 188 | + | |
| 189 | + <!-- 完成时间选择器 --> | |
| 190 | + <up-datetime-picker | |
| 191 | + :show="show" | |
| 192 | + v-model="expectedFinishDate" | |
| 193 | + mode="datetime" | |
| 194 | + :min-date="new Date()" | |
| 195 | + @cancel="show = false" | |
| 196 | + @confirm="expectedFinishDateConfirm" | |
| 197 | + ></up-datetime-picker> | |
| 198 | + </view> | |
| 199 | +</template> | |
| 200 | + | |
| 201 | +<script setup> | |
| 202 | +import { ref, reactive } from 'vue' | |
| 203 | +import { onReady, onShow, onLoad } from '@dcloudio/uni-app'; | |
| 204 | +import { useUploadImgs } from '@/common/utils/useUploadImgs' | |
| 205 | +import { getRoadListByLatLng } from '@/api/common' | |
| 206 | +import { regionmgrUniversalApproval, regionmgrWorkorderCreate } from '@/api/work-order-manage/work-order-manage' | |
| 207 | +import { timeFormat } from '@/uni_modules/uview-plus' | |
| 208 | +import { nextStepMap } from '@/common/utils/common' | |
| 209 | +import { useUserStore } from '@/pinia/user'; | |
| 210 | + | |
| 211 | +// ========== 状态管理 ========== | |
| 212 | +const userStore = useUserStore(); | |
| 213 | + | |
| 214 | +// ========== 业务线相关状态 ========== | |
| 215 | +// 业务线映射表 | |
| 216 | +const busiLineMap = ref({ | |
| 217 | + 'yl': '园林', | |
| 218 | + 'sz': '市政', | |
| 219 | + 'wy': '物业', | |
| 220 | + '园林': 'yl', | |
| 221 | + '市政': 'sz', | |
| 222 | + '物业': 'wy' | |
| 223 | +}); | |
| 224 | + | |
| 225 | +// 业务线选项列表 | |
| 226 | +const busiLineOptions = ref([]); | |
| 227 | +const formatBusiLineOptions = () => { | |
| 228 | + if (!userStore.userInfo?.user?.busiLine) { | |
| 229 | + busiLineOptions.value = []; | |
| 230 | + return; | |
| 231 | + } | |
| 232 | + const rawBusiLines = userStore.userInfo.user.busiLine.split(','); | |
| 233 | + busiLineOptions.value = rawBusiLines.map(item => ({ | |
| 234 | + name: busiLineMap.value[item.trim()] | |
| 235 | + })); | |
| 236 | +}; | |
| 3 | 237 | |
| 4 | -export default defineComponent({ | |
| 5 | - name: "add-order" | |
| 238 | +// 工具方法:通过中文名称获取对应的英文标识 | |
| 239 | +const getBusiLineEnByCn = (cnName) => { | |
| 240 | + return busiLineMap.value[cnName] || ''; | |
| 241 | +}; | |
| 242 | + | |
| 243 | +// ========== 表单Ref ========== | |
| 244 | +const workOrderFormRef = ref(null) | |
| 245 | + | |
| 246 | +// ========== 公共上传逻辑复用 ========== | |
| 247 | +const problemImgs = useUploadImgs({ | |
| 248 | + maxCount: 3, | |
| 249 | + uploadText: '选择问题照片', | |
| 250 | + sizeType: ['compressed'], | |
| 251 | + formRef: workOrderFormRef, | |
| 252 | + fieldName: 'problemImgs' | |
| 253 | +}) | |
| 254 | + | |
| 255 | +if (!Array.isArray(problemImgs.rawImgList.value)) { | |
| 256 | + problemImgs.rawImgList.value = []; | |
| 257 | +} | |
| 258 | + | |
| 259 | +// ========== 页面状态 ========== | |
| 260 | +const showActionSheet = ref(false) | |
| 261 | +const currentActionSheetData = reactive({ | |
| 262 | + type: '', | |
| 263 | + list: [], | |
| 264 | + title: '' | |
| 265 | +}) | |
| 266 | +const show = ref(false) | |
| 267 | +const expectedFinishDate = ref(Date.now()) | |
| 268 | + | |
| 269 | +// ========== 重新提交相关状态 ========== | |
| 270 | +const isRenew = ref(false); | |
| 271 | +const renewOrderData = ref(null); | |
| 272 | + | |
| 273 | +// ========== 下拉列表数据 ========== | |
| 274 | +const roadNameList = ref([]) | |
| 275 | +const orderNameList = ref([]) | |
| 276 | +const pressingTypeList = ref([]) | |
| 277 | + | |
| 278 | +// ========== 工单表单数据 ========== | |
| 279 | +const workOrderForm = reactive({ | |
| 280 | + busiLineCn: '', | |
| 281 | + roadId: 0, | |
| 282 | + roadName: '', | |
| 283 | + workLocation: '', | |
| 284 | + orderName: '', | |
| 285 | + pressingType: '', | |
| 286 | + pressingTypeName: '', | |
| 287 | + problemDesc: '', | |
| 288 | + lat: 0, | |
| 289 | + lon: 0, | |
| 290 | + expectedFinishDate: '', | |
| 6 | 291 | }) |
| 292 | + | |
| 293 | +// ========== 表单校验规则 ========== | |
| 294 | +const workOrderFormRules = reactive({ | |
| 295 | + busiLineCn: [ | |
| 296 | + { type: 'string', required: true, message: '请选择业务线', trigger: ['change', 'blur'] } | |
| 297 | + ], | |
| 298 | + workLocation: [ | |
| 299 | + { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] } | |
| 300 | + ], | |
| 301 | + roadName: [ | |
| 302 | + { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] } | |
| 303 | + ], | |
| 304 | + orderName: [ | |
| 305 | + { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] } | |
| 306 | + ], | |
| 307 | + pressingTypeName: [ | |
| 308 | + { type: 'string', required: true, message: '请选择紧急程度', trigger: ['change'] } | |
| 309 | + ], | |
| 310 | + problemDesc: [ | |
| 311 | + { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, | |
| 312 | + { type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur'] } | |
| 313 | + ], | |
| 314 | + problemImgs: [problemImgs.imgValidateRule] | |
| 315 | +}) | |
| 316 | + | |
| 317 | +// ========== 生命周期 ========== | |
| 318 | +onLoad((options) => { | |
| 319 | + // 初始化业务线选项 | |
| 320 | + formatBusiLineOptions(); | |
| 321 | + // 默认选中第一个业务线 | |
| 322 | + if (busiLineOptions.value.length > 0) { | |
| 323 | + workOrderForm.busiLineCn = busiLineOptions.value[0].name; | |
| 324 | + } | |
| 325 | + | |
| 326 | + // 判断是否为重新提交状态 | |
| 327 | + if (options.isRenew == 1 && options.tempKey) { | |
| 328 | + isRenew.value = true; | |
| 329 | + const tempKey = options.tempKey; | |
| 330 | + | |
| 331 | + try { | |
| 332 | + const orderData = uni.getStorageSync(tempKey); | |
| 333 | + if (orderData && typeof orderData === 'object') { | |
| 334 | + renewOrderData.value = orderData; | |
| 335 | + echoOrderData(renewOrderData.value); | |
| 336 | + } else { | |
| 337 | + uni.showToast({ title: '工单数据不存在,无法重新提交', icon: 'none' }); | |
| 338 | + setTimeout(() => uni.navigateBack(), 1000); | |
| 339 | + return; | |
| 340 | + } | |
| 341 | + } catch (error) { | |
| 342 | + console.error('读取工单数据失败:', error); | |
| 343 | + uni.showToast({ title: '数据读取异常,无法重新提交', icon: 'none' }); | |
| 344 | + setTimeout(() => uni.navigateBack(), 1000); | |
| 345 | + return; | |
| 346 | + } finally { | |
| 347 | + uni.removeStorageSync(tempKey); | |
| 348 | + } | |
| 349 | + } | |
| 350 | +}); | |
| 351 | + | |
| 352 | +onReady(() => { | |
| 353 | + if (workOrderFormRef.value) { | |
| 354 | + workOrderFormRef.value.setRules(workOrderFormRules) | |
| 355 | + } | |
| 356 | + console.log('工单表单规则初始化完成') | |
| 357 | +}) | |
| 358 | + | |
| 359 | +onShow(() => { | |
| 360 | + // 初始化工单名称列表 | |
| 361 | + orderNameList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')) | |
| 362 | + // 初始化紧急程度列表 | |
| 363 | + pressingTypeList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('workorder_pressing_type')) | |
| 364 | +}) | |
| 365 | + | |
| 366 | +// ========== 核心方法 ========== | |
| 367 | +const echoOrderData = (orderItem) => { | |
| 368 | + // 回显业务线 | |
| 369 | + if (orderItem.busiLine) { | |
| 370 | + workOrderForm.busiLineCn = busiLineMap.value[orderItem.busiLine]; | |
| 371 | + } | |
| 372 | + | |
| 373 | + // 回显基础字段 | |
| 374 | + workOrderForm.roadId = orderItem.roadId || 0; | |
| 375 | + workOrderForm.roadName = orderItem.roadName || ''; | |
| 376 | + workOrderForm.workLocation = orderItem.lonLatAddress || orderItem.roadName || ''; | |
| 377 | + workOrderForm.orderName = orderItem.orderName || ''; | |
| 378 | + workOrderForm.pressingType = orderItem.pressingType || ''; | |
| 379 | + workOrderForm.pressingTypeName = uni.$dict.getDictLabel('workorder_pressing_type', orderItem.pressingType) || ''; | |
| 380 | + workOrderForm.problemDesc = orderItem.remark || ''; | |
| 381 | + workOrderForm.lat = orderItem.lat || 0; | |
| 382 | + workOrderForm.lon = orderItem.lon || 0; | |
| 383 | + workOrderForm.expectedFinishDate = timeFormat(orderItem.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss') || timeFormat(new Date(), 'yyyy-mm-dd hh:MM:ss'); | |
| 384 | + | |
| 385 | + // 回显图片 | |
| 386 | + if (orderItem.problemsImgs && Array.isArray(orderItem.problemsImgs) && orderItem.problemsImgs.length > 0) { | |
| 387 | + const imgList = orderItem.problemsImgs.map((imgUrl, index) => ({ | |
| 388 | + url: imgUrl, | |
| 389 | + name: `renew_img_${index}`, | |
| 390 | + status: 'success' | |
| 391 | + })); | |
| 392 | + problemImgs.imgList.value = imgList; | |
| 393 | + problemImgs.rawImgList.value = imgList; | |
| 394 | + } | |
| 395 | + | |
| 396 | + // 自动获取道路列表 | |
| 397 | + if (orderItem.lat && orderItem.lon) { | |
| 398 | + getRoadListByBusiLine(); | |
| 399 | + } | |
| 400 | +}; | |
| 401 | + | |
| 402 | +// 业务线切换事件 | |
| 403 | +const handleBusiLineChange = () => { | |
| 404 | + workOrderForm.roadName = ''; | |
| 405 | + workOrderForm.roadId = 0; | |
| 406 | + roadNameList.value = []; | |
| 407 | + if (workOrderForm.workLocation) { | |
| 408 | + getRoadListByBusiLine(); | |
| 409 | + } | |
| 410 | +}; | |
| 411 | + | |
| 412 | +// 获取道路列表(带业务线) | |
| 413 | +const getRoadListByBusiLine = async () => { | |
| 414 | + if (!workOrderForm.lat || !workOrderForm.lon) { | |
| 415 | + return; | |
| 416 | + } | |
| 417 | + const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn); | |
| 418 | + if (!busiLineEn) { | |
| 419 | + uni.showToast({ title: '业务线标识异常', icon: 'none' }); | |
| 420 | + return; | |
| 421 | + } | |
| 422 | + | |
| 423 | + try { | |
| 424 | + uni.showLoading({ title: '获取道路名称中...' }); | |
| 425 | + const roadRes = await getRoadListByLatLng({ | |
| 426 | + busiLine: busiLineEn, | |
| 427 | + latitude: workOrderForm.lat, | |
| 428 | + longitude: workOrderForm.lon | |
| 429 | + }); | |
| 430 | + uni.hideLoading(); | |
| 431 | + if (Array.isArray(roadRes)) { | |
| 432 | + roadNameList.value = roadRes.map((item) => ({ | |
| 433 | + name: item.roadName || '', | |
| 434 | + code: item.roadCode || '', | |
| 435 | + id: item.roadId || 0 | |
| 436 | + })); | |
| 437 | + } else { | |
| 438 | + roadNameList.value = [{ name: '未查询到道路名称', code: '', id: 0 }]; | |
| 439 | + uni.showToast({ title: '未查询到该位置的道路信息', icon: 'none' }); | |
| 440 | + } | |
| 441 | + } catch (err) { | |
| 442 | + uni.hideLoading(); | |
| 443 | + console.error('获取道路名称失败:', err); | |
| 444 | + uni.showToast({ title: '获取道路名称失败,请重试', icon: 'none' }); | |
| 445 | + roadNameList.value = [{ name: '获取失败,请重新选择位置', code: '', id: 0 }]; | |
| 446 | + } | |
| 447 | +}; | |
| 448 | + | |
| 449 | +// ========== 通用弹窗方法 ========== | |
| 450 | +const handleActionSheetOpen = (type) => { | |
| 451 | + if (type === 'roadName' && !workOrderForm.workLocation) { | |
| 452 | + uni.showToast({ title: '请先选择工单位置', icon: 'none' }) | |
| 453 | + return | |
| 454 | + } | |
| 455 | + | |
| 456 | + const configMap = { | |
| 457 | + roadName: { | |
| 458 | + title: '请选择道路名称', | |
| 459 | + list: roadNameList.value | |
| 460 | + }, | |
| 461 | + orderName: { | |
| 462 | + title: '请选择工单名称', | |
| 463 | + list: orderNameList.value | |
| 464 | + }, | |
| 465 | + pressingType: { | |
| 466 | + title: '请选择紧急程度', | |
| 467 | + list: pressingTypeList.value | |
| 468 | + } | |
| 469 | + } | |
| 470 | + | |
| 471 | + currentActionSheetData.type = type | |
| 472 | + currentActionSheetData.title = configMap[type].title | |
| 473 | + currentActionSheetData.list = configMap[type].list | |
| 474 | + showActionSheet.value = true | |
| 475 | +} | |
| 476 | + | |
| 477 | +const handleActionSheetClose = () => { | |
| 478 | + showActionSheet.value = false | |
| 479 | + currentActionSheetData.type = '' | |
| 480 | + currentActionSheetData.list = [] | |
| 481 | + currentActionSheetData.title = '' | |
| 482 | +} | |
| 483 | + | |
| 484 | +const handleActionSheetSelect = (e) => { | |
| 485 | + const { type } = currentActionSheetData | |
| 486 | + switch (type) { | |
| 487 | + case 'roadName': | |
| 488 | + workOrderForm.roadName = e.name | |
| 489 | + workOrderForm.roadId = e.code | |
| 490 | + workOrderFormRef.value?.validateField('roadName') | |
| 491 | + break | |
| 492 | + case 'orderName': | |
| 493 | + workOrderForm.orderName = e.name | |
| 494 | + workOrderFormRef.value?.validateField('orderName') | |
| 495 | + break | |
| 496 | + case 'pressingType': | |
| 497 | + workOrderForm.pressingType = e.value | |
| 498 | + workOrderForm.pressingTypeName = e.name | |
| 499 | + workOrderFormRef.value?.validateField('pressingTypeName') | |
| 500 | + break | |
| 501 | + } | |
| 502 | + showActionSheet.value = false | |
| 503 | +} | |
| 504 | + | |
| 505 | +const navigateBack = () => { | |
| 506 | + uni.reLaunch({ | |
| 507 | + url: '/pages-sub/problem/work-order-manage/index', | |
| 508 | + fail: () => { | |
| 509 | + uni.navigateBack({ delta: 2 }); | |
| 510 | + } | |
| 511 | + }); | |
| 512 | +} | |
| 513 | + | |
| 514 | +// 清除希望完成时间 | |
| 515 | +const clearExpectedFinishDate = ()=> { | |
| 516 | + workOrderForm.expectedFinishDate = '' | |
| 517 | +} | |
| 518 | + | |
| 519 | +// 选择工单位置 | |
| 520 | +const chooseWorkLocation = () => { | |
| 521 | + uni.chooseLocation({ | |
| 522 | + success: async (res) => { | |
| 523 | + workOrderForm.roadName = '' | |
| 524 | + workOrderForm.roadId = 0 | |
| 525 | + roadNameList.value = [] | |
| 526 | + | |
| 527 | + workOrderForm.workLocation = res.name | |
| 528 | + workOrderForm.lat = res.latitude | |
| 529 | + workOrderForm.lon = res.longitude | |
| 530 | + | |
| 531 | + workOrderFormRef.value?.validateField('workLocation') | |
| 532 | + workOrderFormRef.value?.validateField('roadName') | |
| 533 | + | |
| 534 | + await getRoadListByBusiLine(); | |
| 535 | + }, | |
| 536 | + fail: (err) => { | |
| 537 | + console.error('选择位置失败:', err) | |
| 538 | + uni.showToast({ title: '选择位置失败:' + err.errMsg, icon: 'none' }) | |
| 539 | + } | |
| 540 | + }) | |
| 541 | +} | |
| 542 | + | |
| 543 | +// 完成时间确认 | |
| 544 | +const expectedFinishDateConfirm = (e) => { | |
| 545 | + workOrderForm.expectedFinishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 546 | + show.value = false | |
| 547 | +} | |
| 548 | + | |
| 549 | +// 隐藏键盘 | |
| 550 | +const hideKeyboard = () => { | |
| 551 | + uni.hideKeyboard() | |
| 552 | +} | |
| 553 | + | |
| 554 | +// 提交工单 | |
| 555 | +const submitWorkOrder = async () => { | |
| 556 | + try { | |
| 557 | + await workOrderFormRef.value.validate() | |
| 558 | + | |
| 559 | + const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn); | |
| 560 | + if (!busiLineEn) { | |
| 561 | + uni.showToast({ title: '业务线选择异常,请重新选择', icon: 'none' }); | |
| 562 | + return; | |
| 563 | + } | |
| 564 | + | |
| 565 | + const commonSubmitData = { | |
| 566 | + roadId: workOrderForm.roadId, | |
| 567 | + roadName: workOrderForm.roadName, | |
| 568 | + problemsImgs: problemImgs.getSuccessImgUrls(), | |
| 569 | + remark: workOrderForm.problemDesc.trim(), | |
| 570 | + latLonType: 2, | |
| 571 | + lat: workOrderForm.lat, | |
| 572 | + lon: workOrderForm.lon, | |
| 573 | + lonLatAddress: workOrderForm.workLocation, | |
| 574 | + pressingType: workOrderForm.pressingType, | |
| 575 | + orderName: workOrderForm.orderName, | |
| 576 | + expectedFinishDate: new Date(workOrderForm.expectedFinishDate).getTime(), | |
| 577 | + sourceId: 1, | |
| 578 | + sourceName: workOrderForm.busiLineCn, | |
| 579 | + busiLine: busiLineEn | |
| 580 | + } | |
| 581 | + | |
| 582 | + uni.showLoading({ title: '提交中...' }) | |
| 583 | + let res | |
| 584 | + | |
| 585 | + if (isRenew.value) { | |
| 586 | + const renewSubmitData = { | |
| 587 | + workerDataId: renewOrderData.value.id, | |
| 588 | + taskKey: renewOrderData.value.taskKey, | |
| 589 | + taskId: renewOrderData.value.taskId, | |
| 590 | + operateType: nextStepMap[renewOrderData.value.taskKey]?.operateTypeRenew || '', | |
| 591 | + agree: 0, | |
| 592 | + reason: '重新提交工单', | |
| 593 | + ...commonSubmitData | |
| 594 | + } | |
| 595 | + res = await regionmgrUniversalApproval(renewSubmitData) | |
| 596 | + } else { | |
| 597 | + res = await regionmgrWorkorderCreate(commonSubmitData) | |
| 598 | + } | |
| 599 | + | |
| 600 | + uni.hideLoading() | |
| 601 | + uni.showToast({ | |
| 602 | + title: isRenew.value ? '重新提交成功' : '工单提交成功', | |
| 603 | + icon: 'success', | |
| 604 | + duration: 1000 | |
| 605 | + }) | |
| 606 | + | |
| 607 | + setTimeout(() => { | |
| 608 | + uni.reLaunch({ | |
| 609 | + url: '/pages-sub/problem/regional-order-manage/index' | |
| 610 | + }) | |
| 611 | + }, 1000) | |
| 612 | + } catch (error) { | |
| 613 | + uni.hideLoading() | |
| 614 | + | |
| 615 | + if (!Array.isArray(error)) { | |
| 616 | + console.error(isRenew.value ? '工单重新提交失败:' : '工单提交失败:', error) | |
| 617 | + uni.showToast({ | |
| 618 | + title: isRenew.value ? error.msg : error.msg, | |
| 619 | + icon: 'none', | |
| 620 | + duration: 2000 | |
| 621 | + }) | |
| 622 | + } | |
| 623 | + } | |
| 624 | +} | |
| 7 | 625 | </script> |
| 8 | 626 | |
| 9 | -<template> | |
| 627 | +<style lang="scss" scoped> | |
| 628 | +// 全局页面样式 | |
| 629 | +.page-container { | |
| 630 | + min-height: 100vh; | |
| 631 | + padding-bottom: 100rpx; // 给底部按钮留空间 | |
| 632 | +} | |
| 10 | 633 | |
| 11 | -</template> | |
| 634 | +// 工单表单内容容器 | |
| 635 | +.work-order-form-content { | |
| 636 | + background: #fff; | |
| 637 | +} | |
| 638 | + | |
| 639 | +// 派单情况分组样式(核心:增加顶部间距) | |
| 640 | +.dispatch-group { | |
| 641 | + | |
| 642 | + padding-top: 20rpx; // 分组内顶部内边距,增强视觉区分 | |
| 12 | 643 | |
| 13 | -<style scoped lang="scss"> | |
| 644 | +} | |
| 14 | 645 | |
| 646 | +// 派单情况标题样式 | |
| 647 | +.dispatch-title { | |
| 648 | + font-size: 32rpx; | |
| 649 | + font-weight: 600; | |
| 650 | + color:$u-primary; | |
| 651 | + margin-bottom: 20rpx; | |
| 652 | + padding-left: 10rpx; | |
| 653 | +} | |
| 15 | 654 | </style> |
| 16 | 655 | \ No newline at end of file | ... | ... |
pages-sub/problem/regional-order-manage/add-patrol-order.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="page-container"> | |
| 3 | + <view class="work-order-form-content commonPageLRpadding"> | |
| 4 | + <up-form | |
| 5 | + label-position="left" | |
| 6 | + :model="workOrderForm" | |
| 7 | + ref="workOrderFormRef" | |
| 8 | + labelWidth="200rpx" | |
| 9 | + > | |
| 10 | + <!-- 1. 工单位置(地图选择) --> | |
| 11 | + <up-form-item | |
| 12 | + label="工单位置1" | |
| 13 | + prop="workLocation" | |
| 14 | + border-bottom | |
| 15 | + required | |
| 16 | + @click="chooseWorkLocation(); hideKeyboard()" | |
| 17 | + > | |
| 18 | + <up-input | |
| 19 | + v-model="workOrderForm.workLocation" | |
| 20 | + border="none" | |
| 21 | + readonly | |
| 22 | + suffix-icon="map-fill" | |
| 23 | + placeholder="点击选择工单位置" | |
| 24 | + ></up-input> | |
| 25 | + </up-form-item> | |
| 26 | + | |
| 27 | + <!-- 2. 工单名称(下拉框) --> | |
| 28 | + <up-form-item | |
| 29 | + label="工单名称" | |
| 30 | + prop="orderName" | |
| 31 | + border-bottom | |
| 32 | + required | |
| 33 | + @click="handleActionSheetOpen('orderName'); hideKeyboard()" | |
| 34 | + > | |
| 35 | + <up-input | |
| 36 | + v-model="workOrderForm.orderName" | |
| 37 | + disabled | |
| 38 | + disabled-color="#ffffff" | |
| 39 | + placeholder="请选择工单名称" | |
| 40 | + border="none" | |
| 41 | + ></up-input> | |
| 42 | + <template #right> | |
| 43 | + <up-icon name="arrow-right" size="16"></up-icon> | |
| 44 | + </template> | |
| 45 | + </up-form-item> | |
| 46 | + | |
| 47 | + <!-- 3. 情况描述(文本域) --> | |
| 48 | + <up-form-item | |
| 49 | + label="情况描述" | |
| 50 | + prop="problemDesc" | |
| 51 | + required | |
| 52 | + > | |
| 53 | + <up-textarea | |
| 54 | + placeholder="请输入情况描述(最多200字)" | |
| 55 | + v-model.trim="workOrderForm.problemDesc" | |
| 56 | + count | |
| 57 | + maxlength="200" | |
| 58 | + rows="4" | |
| 59 | + @blur="() => workOrderFormRef.validateField('problemDesc')" | |
| 60 | + ></up-textarea> | |
| 61 | + </up-form-item> | |
| 62 | + | |
| 63 | + <!-- 4. 问题照片 --> | |
| 64 | + <up-form-item label="问题照片" prop="problemImgs" required> | |
| 65 | + <up-upload | |
| 66 | + :file-list="problemImgs.imgList.value||[]" | |
| 67 | + @after-read="problemImgs.uploadImgs" | |
| 68 | + @delete="problemImgs.deleteImg" | |
| 69 | + multiple | |
| 70 | + :width="70" | |
| 71 | + :height="70" | |
| 72 | + :max-count="problemImgs.uploadConfig.maxCount" | |
| 73 | + :upload-text="problemImgs.uploadConfig.uploadText" | |
| 74 | + :size-type="problemImgs.uploadConfig.sizeType" | |
| 75 | + ></up-upload> | |
| 76 | + </up-form-item> | |
| 77 | + | |
| 78 | + </up-form> | |
| 79 | + </view> | |
| 80 | + | |
| 81 | + <!-- 底部提交按钮 --> | |
| 82 | + <view class="fixed-bottom-btn-wrap"> | |
| 83 | + <up-button | |
| 84 | + type="primary" | |
| 85 | + text="提交工单" | |
| 86 | + @click="submitWorkOrder" | |
| 87 | + ></up-button> | |
| 88 | + </view> | |
| 89 | + | |
| 90 | + <!-- 合并后的通用下拉弹窗 --> | |
| 91 | + <up-action-sheet | |
| 92 | + :show="showActionSheet" | |
| 93 | + :actions="currentActionSheetData.list" | |
| 94 | + :title="currentActionSheetData.title" | |
| 95 | + @close="handleActionSheetClose" | |
| 96 | + @select="handleActionSheetSelect" | |
| 97 | + ></up-action-sheet> | |
| 98 | + | |
| 99 | + </view> | |
| 100 | +</template> | |
| 101 | + | |
| 102 | +<script setup> | |
| 103 | +import { ref, reactive } from 'vue' | |
| 104 | +import { onReady, onShow, onLoad } from '@dcloudio/uni-app'; | |
| 105 | +import { useUploadImgs } from '@/common/utils/useUploadImgs' | |
| 106 | +import { regionmgrUniversalApproval, regionmgrWorkorderCreate } from '@/api/work-order-manage/work-order-manage' | |
| 107 | +import { timeFormat } from '@/uni_modules/uview-plus' | |
| 108 | +import { nextStepMap } from '@/common/utils/common' | |
| 109 | +import { useUserStore } from '@/pinia/user'; | |
| 110 | + | |
| 111 | +// ========== 状态管理 ========== | |
| 112 | +const userStore = useUserStore(); | |
| 113 | + | |
| 114 | +// ========== 业务线相关状态 ========== | |
| 115 | +// 业务线映射表 | |
| 116 | +const busiLineMap = ref({ | |
| 117 | + 'yl': '园林', | |
| 118 | + 'sz': '市政', | |
| 119 | + 'wy': '物业', | |
| 120 | + '园林': 'yl', | |
| 121 | + '市政': 'sz', | |
| 122 | + '物业': 'wy' | |
| 123 | +}); | |
| 124 | + | |
| 125 | +// 业务线选项列表 | |
| 126 | +const busiLineOptions = ref([]); | |
| 127 | +const formatBusiLineOptions = () => { | |
| 128 | + if (!userStore.userInfo?.user?.busiLine) { | |
| 129 | + busiLineOptions.value = []; | |
| 130 | + return; | |
| 131 | + } | |
| 132 | + const rawBusiLines = userStore.userInfo.user.busiLine.split(','); | |
| 133 | + busiLineOptions.value = rawBusiLines.map(item => ({ | |
| 134 | + name: busiLineMap.value[item.trim()] | |
| 135 | + })); | |
| 136 | +}; | |
| 137 | + | |
| 138 | +// 工具方法:通过中文名称获取对应的英文标识 | |
| 139 | +const getBusiLineEnByCn = (cnName) => { | |
| 140 | + return busiLineMap.value[cnName] || ''; | |
| 141 | +}; | |
| 142 | + | |
| 143 | +// ========== 表单Ref ========== | |
| 144 | +const workOrderFormRef = ref(null) | |
| 145 | + | |
| 146 | +// ========== 公共上传逻辑复用 ========== | |
| 147 | +const problemImgs = useUploadImgs({ | |
| 148 | + maxCount: 3, | |
| 149 | + uploadText: '选择问题照片', | |
| 150 | + sizeType: ['compressed'], | |
| 151 | + formRef: workOrderFormRef, | |
| 152 | + fieldName: 'problemImgs' | |
| 153 | +}) | |
| 154 | + | |
| 155 | +if (!Array.isArray(problemImgs.rawImgList.value)) { | |
| 156 | + problemImgs.rawImgList.value = []; | |
| 157 | +} | |
| 158 | + | |
| 159 | +// ========== 页面状态 ========== | |
| 160 | +const showActionSheet = ref(false) | |
| 161 | +const currentActionSheetData = reactive({ | |
| 162 | + type: '', | |
| 163 | + list: [], | |
| 164 | + title: '' | |
| 165 | +}) | |
| 166 | + | |
| 167 | +// ========== 重新提交相关状态 ========== | |
| 168 | +const isRenew = ref(false); | |
| 169 | +const renewOrderData = ref(null); | |
| 170 | + | |
| 171 | +// ========== 下拉列表数据 ========== | |
| 172 | +const orderNameList = ref([]) | |
| 173 | + | |
| 174 | +// ========== 工单表单数据 ========== | |
| 175 | +const workOrderForm = reactive({ | |
| 176 | + orderName: '', | |
| 177 | + problemDesc: '', | |
| 178 | + lat: 0, | |
| 179 | + lon: 0, | |
| 180 | + workLocation: '', | |
| 181 | +}) | |
| 182 | + | |
| 183 | +// ========== 表单校验规则 ========== | |
| 184 | +const workOrderFormRules = reactive({ | |
| 185 | + workLocation: [ | |
| 186 | + { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] } | |
| 187 | + ], | |
| 188 | + orderName: [ | |
| 189 | + { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] } | |
| 190 | + ], | |
| 191 | + problemDesc: [ | |
| 192 | + { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, | |
| 193 | + { type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur'] } | |
| 194 | + ], | |
| 195 | + problemImgs: [problemImgs.imgValidateRule] | |
| 196 | +}) | |
| 197 | + | |
| 198 | +// ========== 生命周期 ========== | |
| 199 | +onLoad((options) => { | |
| 200 | + // 初始化业务线选项 | |
| 201 | + formatBusiLineOptions(); | |
| 202 | + | |
| 203 | + // 判断是否为重新提交状态 | |
| 204 | + if (options.isRenew == 1 && options.tempKey) { | |
| 205 | + isRenew.value = true; | |
| 206 | + const tempKey = options.tempKey; | |
| 207 | + | |
| 208 | + try { | |
| 209 | + const orderData = uni.getStorageSync(tempKey); | |
| 210 | + if (orderData && typeof orderData === 'object') { | |
| 211 | + renewOrderData.value = orderData; | |
| 212 | + echoOrderData(renewOrderData.value); | |
| 213 | + } else { | |
| 214 | + uni.showToast({ title: '工单数据不存在,无法重新提交', icon: 'none' }); | |
| 215 | + setTimeout(() => uni.navigateBack(), 1000); | |
| 216 | + return; | |
| 217 | + } | |
| 218 | + } catch (error) { | |
| 219 | + console.error('读取工单数据失败:', error); | |
| 220 | + uni.showToast({ title: '数据读取异常,无法重新提交', icon: 'none' }); | |
| 221 | + setTimeout(() => uni.navigateBack(), 1000); | |
| 222 | + return; | |
| 223 | + } finally { | |
| 224 | + uni.removeStorageSync(tempKey); | |
| 225 | + } | |
| 226 | + } | |
| 227 | +}); | |
| 228 | + | |
| 229 | +onReady(() => { | |
| 230 | + if (workOrderFormRef.value) { | |
| 231 | + workOrderFormRef.value.setRules(workOrderFormRules) | |
| 232 | + } | |
| 233 | + console.log('工单表单规则初始化完成') | |
| 234 | +}) | |
| 235 | + | |
| 236 | +onShow(() => { | |
| 237 | + // 初始化工单名称列表 | |
| 238 | + orderNameList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')) | |
| 239 | +}) | |
| 240 | + | |
| 241 | +// ========== 核心方法 ========== | |
| 242 | +const echoOrderData = (orderItem) => { | |
| 243 | + // 回显基础字段 | |
| 244 | + workOrderForm.workLocation = orderItem.lonLatAddress || orderItem.roadName || ''; | |
| 245 | + workOrderForm.orderName = orderItem.orderName || ''; | |
| 246 | + workOrderForm.problemDesc = orderItem.remark || ''; | |
| 247 | + workOrderForm.lat = orderItem.lat || 0; | |
| 248 | + workOrderForm.lon = orderItem.lon || 0; | |
| 249 | + | |
| 250 | + // 回显图片 | |
| 251 | + if (orderItem.problemsImgs && Array.isArray(orderItem.problemsImgs) && orderItem.problemsImgs.length > 0) { | |
| 252 | + const imgList = orderItem.problemsImgs.map((imgUrl, index) => ({ | |
| 253 | + url: imgUrl, | |
| 254 | + name: `renew_img_${index}`, | |
| 255 | + status: 'success' | |
| 256 | + })); | |
| 257 | + problemImgs.imgList.value = imgList; | |
| 258 | + problemImgs.rawImgList.value = imgList; | |
| 259 | + } | |
| 260 | +}; | |
| 261 | + | |
| 262 | +// ========== 通用弹窗方法 ========== | |
| 263 | +const handleActionSheetOpen = (type) => { | |
| 264 | + const configMap = { | |
| 265 | + orderName: { | |
| 266 | + title: '请选择工单名称', | |
| 267 | + list: orderNameList.value | |
| 268 | + } | |
| 269 | + } | |
| 270 | + | |
| 271 | + currentActionSheetData.type = type | |
| 272 | + currentActionSheetData.title = configMap[type].title | |
| 273 | + currentActionSheetData.list = configMap[type].list | |
| 274 | + showActionSheet.value = true | |
| 275 | +} | |
| 276 | + | |
| 277 | +const handleActionSheetClose = () => { | |
| 278 | + showActionSheet.value = false | |
| 279 | + currentActionSheetData.type = '' | |
| 280 | + currentActionSheetData.list = [] | |
| 281 | + currentActionSheetData.title = '' | |
| 282 | +} | |
| 283 | + | |
| 284 | +const handleActionSheetSelect = (e) => { | |
| 285 | + const { type } = currentActionSheetData | |
| 286 | + switch (type) { | |
| 287 | + case 'orderName': | |
| 288 | + workOrderForm.orderName = e.name | |
| 289 | + workOrderFormRef.value?.validateField('orderName') | |
| 290 | + break | |
| 291 | + } | |
| 292 | + showActionSheet.value = false | |
| 293 | +} | |
| 294 | + | |
| 295 | +const navigateBack = () => { | |
| 296 | + uni.reLaunch({ | |
| 297 | + url: '/pages-sub/problem/work-order-manage/index', | |
| 298 | + fail: () => { | |
| 299 | + uni.navigateBack({ delta: 2 }); | |
| 300 | + } | |
| 301 | + }); | |
| 302 | +} | |
| 303 | + | |
| 304 | +// 选择工单位置 | |
| 305 | +const chooseWorkLocation = () => { | |
| 306 | + uni.chooseLocation({ | |
| 307 | + success: async (res) => { | |
| 308 | + workOrderForm.workLocation = res.name | |
| 309 | + workOrderForm.lat = res.latitude | |
| 310 | + workOrderForm.lon = res.longitude | |
| 311 | + | |
| 312 | + workOrderFormRef.value?.validateField('workLocation') | |
| 313 | + }, | |
| 314 | + fail: (err) => { | |
| 315 | + console.error('选择位置失败:', err) | |
| 316 | + uni.showToast({ title: '选择位置失败:' + err.errMsg, icon: 'none' }) | |
| 317 | + } | |
| 318 | + }) | |
| 319 | +} | |
| 320 | + | |
| 321 | +// 隐藏键盘 | |
| 322 | +const hideKeyboard = () => { | |
| 323 | + uni.hideKeyboard() | |
| 324 | +} | |
| 325 | + | |
| 326 | +// 提交工单 | |
| 327 | +const submitWorkOrder = async () => { | |
| 328 | + try { | |
| 329 | + await workOrderFormRef.value.validate() | |
| 330 | + | |
| 331 | + const commonSubmitData = { | |
| 332 | + problemsImgs: problemImgs.getSuccessImgUrls(), | |
| 333 | + remark: workOrderForm.problemDesc.trim(), | |
| 334 | + latLonType: 2, | |
| 335 | + lat: workOrderForm.lat, | |
| 336 | + lon: workOrderForm.lon, | |
| 337 | + lonLatAddress: workOrderForm.workLocation, | |
| 338 | + orderName: workOrderForm.orderName, | |
| 339 | + sourceId: 1 | |
| 340 | + } | |
| 341 | + | |
| 342 | + uni.showLoading({ title: '提交中...' }) | |
| 343 | + let res | |
| 344 | + | |
| 345 | + if (isRenew.value) { | |
| 346 | + const renewSubmitData = { | |
| 347 | + workerDataId: renewOrderData.value.id, | |
| 348 | + taskKey: renewOrderData.value.taskKey, | |
| 349 | + taskId: renewOrderData.value.taskId, | |
| 350 | + operateType: nextStepMap[renewOrderData.value.taskKey]?.operateTypeRenew || '', | |
| 351 | + agree: 0, | |
| 352 | + reason: '重新提交工单', | |
| 353 | + ...commonSubmitData | |
| 354 | + } | |
| 355 | + res = await regionmgrUniversalApproval(renewSubmitData) | |
| 356 | + } else { | |
| 357 | + res = await regionmgrWorkorderCreate(commonSubmitData) | |
| 358 | + } | |
| 359 | + | |
| 360 | + uni.hideLoading() | |
| 361 | + uni.showToast({ | |
| 362 | + title: isRenew.value ? '重新提交成功' : '工单提交成功', | |
| 363 | + icon: 'success', | |
| 364 | + duration: 1000 | |
| 365 | + }) | |
| 366 | + | |
| 367 | + setTimeout(() => { | |
| 368 | + uni.reLaunch({ | |
| 369 | + url: '/pages-sub/problem/regional-order-manage/index' | |
| 370 | + }) | |
| 371 | + }, 1000) | |
| 372 | + } catch (error) { | |
| 373 | + uni.hideLoading() | |
| 374 | + | |
| 375 | + if (!Array.isArray(error)) { | |
| 376 | + console.error(isRenew.value ? '工单重新提交失败:' : '工单提交失败:', error) | |
| 377 | + uni.showToast({ | |
| 378 | + title: isRenew.value ? error.msg : error.msg, | |
| 379 | + icon: 'none', | |
| 380 | + duration: 2000 | |
| 381 | + }) | |
| 382 | + } | |
| 383 | + } | |
| 384 | +} | |
| 385 | +</script> | |
| 386 | + | |
| 387 | +<style lang="scss" scoped> | |
| 388 | +// 全局页面样式 | |
| 389 | +.page-container { | |
| 390 | + min-height: 100vh; | |
| 391 | +} | |
| 392 | + | |
| 393 | +// 工单表单内容容器 | |
| 394 | +.work-order-form-content { | |
| 395 | + background: #fff; | |
| 396 | +} | |
| 397 | + | |
| 398 | + | |
| 399 | +</style> | |
| 0 | 400 | \ No newline at end of file | ... | ... |
pages-sub/problem/regional-order-manage/index.vue
| ... | ... | @@ -178,7 +178,7 @@ |
| 178 | 178 | <!-- </up-button>--> |
| 179 | 179 | <!-- </view>--> |
| 180 | 180 | |
| 181 | - <view class="fixed-bottom-btn-wrap"> | |
| 181 | + <view class="fixed-bottom-btn-wrap" v-if="isInspector"> | |
| 182 | 182 | <up-button type="primary" size="large" @click="handleAddOrder"> |
| 183 | 183 | 新增工单 |
| 184 | 184 | </up-button> |
| ... | ... | @@ -315,8 +315,11 @@ const paging = ref(null); |
| 315 | 315 | const orderList = ref([]); |
| 316 | 316 | // 角色控制(巡查员显示新增按钮) |
| 317 | 317 | const isInspector = computed(() => { |
| 318 | + // patrol_global 全域巡查员 | |
| 319 | + // regional_manager 大区经理 | |
| 318 | 320 | // 增加可选链,避免用户信息不存在报错 |
| 319 | - return userStore.userInfo?.roles?.includes('yl_inspector') || false; | |
| 321 | + // return userStore.userInfo?.roles?.includes('yl_inspector') || false; | |
| 322 | + return true | |
| 320 | 323 | }); |
| 321 | 324 | // 回退弹窗相关 |
| 322 | 325 | const rejectModalShow = ref(false); // 回退modal显示开关 |
| ... | ... | @@ -586,9 +589,19 @@ const confirmReject = async () => { |
| 586 | 589 | |
| 587 | 590 | // 新增工单 |
| 588 | 591 | const handleAddOrder = () => { |
| 589 | - uni.navigateTo({ | |
| 590 | - url: '/pages-sub/problem/regional-order-manage/add-order' | |
| 591 | - }); | |
| 592 | + // patrol_global 全域巡查员 | |
| 593 | + // regional_manager 大区经理 | |
| 594 | + console.log(userStore.userInfo?.roles.includes('patrol_global')) | |
| 595 | + if(userStore.userInfo?.roles.includes('patrol_global')){ | |
| 596 | + uni.navigateTo({ | |
| 597 | + url: '/pages-sub/problem/regional-order-manage/add-patrol-order' | |
| 598 | + }); | |
| 599 | + } | |
| 600 | + if(userStore.userInfo?.roles.includes('regional_manager')){ | |
| 601 | + uni.navigateTo({ | |
| 602 | + url: '/pages-sub/problem/wregional-order-manage/add-order' | |
| 603 | + }); | |
| 604 | + } | |
| 592 | 605 | }; |
| 593 | 606 | |
| 594 | 607 | // 验收弹窗 - 取消按钮(清空状态) | ... | ... |
pages-sub/problem/regional-order-manage/order-detail.vue
| ... | ... | @@ -364,7 +364,8 @@ import { |
| 364 | 364 | getDoneTaskDetail, |
| 365 | 365 | getTodoTaskDetail, |
| 366 | 366 | getApprovalDetail, |
| 367 | - universalApproval | |
| 367 | + regionmgrUniversalApproval | |
| 368 | + | |
| 368 | 369 | } from '@/api/work-order-manage/work-order-manage'; |
| 369 | 370 | import {nextStepMap, buzStatusMap, calculateFormatTimeDiff} from '@/common/utils/common' |
| 370 | 371 | // 引入图片上传组合式函数 |
| ... | ... | @@ -669,7 +670,7 @@ const confirmReject = async () => { |
| 669 | 670 | "reason": rejectReasonTrim |
| 670 | 671 | }; |
| 671 | 672 | // 调用回退工单接口 |
| 672 | - const res = await universalApproval(requestData); | |
| 673 | + const res = await regionmgrUniversalApproval(requestData); | |
| 673 | 674 | uni.showToast({title: '回退成功', icon: 'success', duration: 1000}); |
| 674 | 675 | |
| 675 | 676 | rejectModalShow.value = false; |
| ... | ... | @@ -750,7 +751,7 @@ const handleProcess = async (item: any) => { |
| 750 | 751 | "reason": '结束工单' |
| 751 | 752 | }; |
| 752 | 753 | // 调用回退工单接口 |
| 753 | - const res = await universalApproval(requestData); | |
| 754 | + const res = await regionmgrUniversalApproval(requestData); | |
| 754 | 755 | uni.showToast({title: '结束成功', icon: 'success', duration: 1000}); |
| 755 | 756 | // 重新获取工单详情,刷新页面 |
| 756 | 757 | await DetailQuery(taskId.value); |
| ... | ... | @@ -811,7 +812,7 @@ const handleAcceptModalConfirm = async () => { |
| 811 | 812 | "agree": acceptRadioValue.value |
| 812 | 813 | } |
| 813 | 814 | } |
| 814 | - const acceptRes = await universalApproval(postData); | |
| 815 | + const acceptRes = await regionmgrUniversalApproval(postData); | |
| 815 | 816 | // 4. 操作成功处理 |
| 816 | 817 | |
| 817 | 818 | handleAcceptModalCancel(); // 清空状态 | ... | ... |
pages-sub/problem/work-order-manage/add-order.vue
pages-sub/problem/work-order-manage/index.vue
| ... | ... | @@ -309,6 +309,9 @@ const orderList = ref([]); |
| 309 | 309 | // 角色控制(巡查员显示新增按钮) |
| 310 | 310 | const isInspector = computed(() => { |
| 311 | 311 | // 增加可选链,避免用户信息不存在报错 |
| 312 | + // patrol_global 全域巡查员 | |
| 313 | + // regional_manager 大区经理 | |
| 314 | + | |
| 312 | 315 | return userStore.userInfo?.roles?.includes('yl_inspector') || false; |
| 313 | 316 | }); |
| 314 | 317 | // 回退弹窗相关 | ... | ... |
pages.json
| ... | ... | @@ -160,6 +160,11 @@ |
| 160 | 160 | }, |
| 161 | 161 | |
| 162 | 162 | { |
| 163 | + "path": "regional-order-manage/add-patrol-order", | |
| 164 | + "style": { "navigationBarTitleText": "待派单" } | |
| 165 | + }, | |
| 166 | + | |
| 167 | + { | |
| 163 | 168 | "path": "regional-order-manage/order-detail", |
| 164 | 169 | "style": { "navigationBarTitleText": "工单详情" } |
| 165 | 170 | } | ... | ... |