Commit 3d474e84d54ca77493cf71019fc199efbff8e661
1 parent
6c3b6516
快速工单 加上业务线
Showing
14 changed files
with
2067 additions
and
205 deletions
App.vue
api/work-order-manage/work-order-manage.js
| @@ -110,3 +110,24 @@ export const todoBuzSimplePage = (params) => { | @@ -110,3 +110,24 @@ export const todoBuzSimplePage = (params) => { | ||
| 110 | export const workorderCreate = (data) => { | 110 | export const workorderCreate = (data) => { |
| 111 | return post('/app-api/bpm/garden/workorder/create',data); | 111 | return post('/app-api/bpm/garden/workorder/create',data); |
| 112 | }; | 112 | }; |
| 113 | + | ||
| 114 | + | ||
| 115 | +/** | ||
| 116 | + * 大区经理问题工单创建 | ||
| 117 | + * @returns {Promise} | ||
| 118 | + */ | ||
| 119 | +export const regionmgrWorkorderCreat = (data) => { | ||
| 120 | + return post('/app-api/bpm/regionmgr/workorder',data); | ||
| 121 | +}; | ||
| 122 | + | ||
| 123 | +/** | ||
| 124 | + * app端统一审批入口 -- 大区经理 | ||
| 125 | + * @returns {Promise} | ||
| 126 | + */ | ||
| 127 | +export const regionmgrUniversalApproval = (params) => { | ||
| 128 | + return post('/app-api/bpm/regionmgr/workorder/universalApproval',params); | ||
| 129 | +}; | ||
| 130 | + | ||
| 131 | + | ||
| 132 | + | ||
| 133 | + |
pages-sub/daily/maintain-manage/index.vue
| @@ -83,7 +83,7 @@ | @@ -83,7 +83,7 @@ | ||
| 83 | 83 | ||
| 84 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 84 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 85 | <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view> | 85 | <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view> |
| 86 | - <view class="u-line-1"> | 86 | + <view class=""> |
| 87 | <up-button | 87 | <up-button |
| 88 | type="primary" | 88 | type="primary" |
| 89 | size="mini" | 89 | size="mini" |
| @@ -95,12 +95,12 @@ | @@ -95,12 +95,12 @@ | ||
| 95 | </view> | 95 | </view> |
| 96 | </view> | 96 | </view> |
| 97 | 97 | ||
| 98 | - <view class="u-body-item u-flex"> | ||
| 99 | - <view class="u-body-item-title">计划时间:</view> | ||
| 100 | - <view class="u-line-1 u-body-value">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') || '-' }} 至 | ||
| 101 | - {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }} | ||
| 102 | - </view> | ||
| 103 | - </view> | 98 | +<!-- <view class="u-body-item u-flex">--> |
| 99 | +<!-- <view class="u-body-item-title">计划时间:</view>--> | ||
| 100 | +<!-- <view class="u-line-1 u-body-value">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') || '-' }} 至--> | ||
| 101 | +<!-- {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}--> | ||
| 102 | +<!-- </view>--> | ||
| 103 | +<!-- </view>--> | ||
| 104 | </view> | 104 | </view> |
| 105 | </template> | 105 | </template> |
| 106 | </up-card> | 106 | </up-card> |
| @@ -138,7 +138,7 @@ | @@ -138,7 +138,7 @@ | ||
| 138 | 138 | ||
| 139 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 139 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 140 | <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view> | 140 | <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view> |
| 141 | - <view class="u-line-1" v-if="item.finishState!==3"> | 141 | + <view class="" v-if="item.finishState!==3"> |
| 142 | <up-button | 142 | <up-button |
| 143 | type="primary" | 143 | type="primary" |
| 144 | size="mini" | 144 | size="mini" |
pages-sub/daily/maintain-manage/pending-plan-detail.vue
| @@ -41,13 +41,13 @@ | @@ -41,13 +41,13 @@ | ||
| 41 | <!-- 已完成次数 + 查看记录按钮 --> | 41 | <!-- 已完成次数 + 查看记录按钮 --> |
| 42 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 42 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 43 | <view class="u-body-item-title">已完成次数: {{ i.planFinishNum || 0 }} 次</view> | 43 | <view class="u-body-item-title">已完成次数: {{ i.planFinishNum || 0 }} 次</view> |
| 44 | - <view class="u-line-1"> | 44 | + <view class=""> |
| 45 | <up-button | 45 | <up-button |
| 46 | type="primary" | 46 | type="primary" |
| 47 | size="mini" | 47 | size="mini" |
| 48 | @click="gotoFinishPlanDetail(i)" | 48 | @click="gotoFinishPlanDetail(i)" |
| 49 | class="submit-record-btn" | 49 | class="submit-record-btn" |
| 50 | - :style="{ width: '80px', height: '28px', fontSize: '14px', borderRadius: 4 }" | 50 | + |
| 51 | > | 51 | > |
| 52 | 查看记录 | 52 | 查看记录 |
| 53 | </up-button> | 53 | </up-button> |
pages-sub/daily/maintain-manage/road-detail-list.vue
| @@ -76,7 +76,7 @@ | @@ -76,7 +76,7 @@ | ||
| 76 | 76 | ||
| 77 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 77 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 78 | <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view> | 78 | <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view> |
| 79 | - <view class="u-line-1"> | 79 | + <view class=""> |
| 80 | <up-button | 80 | <up-button |
| 81 | type="primary" | 81 | type="primary" |
| 82 | size="mini" | 82 | size="mini" |
pages-sub/daily/patrol-manage/index.vue
| @@ -71,7 +71,7 @@ | @@ -71,7 +71,7 @@ | ||
| 71 | 71 | ||
| 72 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 72 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 73 | <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view> | 73 | <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view> |
| 74 | - <view class="u-line-1"> | 74 | + <view class=""> |
| 75 | <up-button | 75 | <up-button |
| 76 | type="primary" | 76 | type="primary" |
| 77 | size="mini" | 77 | size="mini" |
pages-sub/daily/patrol-manage/pending-plan-detail.vue
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | 36 | ||
| 37 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 37 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 38 | <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view> | 38 | <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view> |
| 39 | - <view class="u-line-1"> | 39 | + <view class=""> |
| 40 | <up-button | 40 | <up-button |
| 41 | v-if="item.finishState ==3" | 41 | v-if="item.finishState ==3" |
| 42 | type="primary" | 42 | type="primary" |
pages-sub/daily/quick-order/add-order.vue
| @@ -8,6 +8,27 @@ | @@ -8,6 +8,27 @@ | ||
| 8 | ref="workOrderFormRef" | 8 | ref="workOrderFormRef" |
| 9 | labelWidth="160rpx" | 9 | labelWidth="160rpx" |
| 10 | > | 10 | > |
| 11 | + | ||
| 12 | + <up-form-item | ||
| 13 | + label="业务线" | ||
| 14 | + prop="busiLineCn" | ||
| 15 | + border-bottom | ||
| 16 | + required | ||
| 17 | + > | ||
| 18 | + <up-radio-group | ||
| 19 | + v-model="workOrderForm.busiLineCn" | ||
| 20 | + placement="row" | ||
| 21 | + @change="handleBusiLineChange" | ||
| 22 | + > | ||
| 23 | + <up-radio | ||
| 24 | + v-for="item in busiLineOptions" | ||
| 25 | + :key="item.name" | ||
| 26 | + :label="item.name" | ||
| 27 | + :name="item.name" | ||
| 28 | + ></up-radio> | ||
| 29 | + </up-radio-group> | ||
| 30 | + | ||
| 31 | + </up-form-item> | ||
| 11 | <!-- 1. 工单位置(地图选择) --> | 32 | <!-- 1. 工单位置(地图选择) --> |
| 12 | <up-form-item | 33 | <up-form-item |
| 13 | label="工单位置" | 34 | label="工单位置" |
| @@ -39,7 +60,6 @@ | @@ -39,7 +60,6 @@ | ||
| 39 | disabled-color="#ffffff" | 60 | disabled-color="#ffffff" |
| 40 | placeholder="请先选择工单位置" | 61 | placeholder="请先选择工单位置" |
| 41 | border="none" | 62 | border="none" |
| 42 | - | ||
| 43 | ></up-input> | 63 | ></up-input> |
| 44 | <template #right> | 64 | <template #right> |
| 45 | <up-icon name="arrow-right" size="16" ></up-icon> | 65 | <up-icon name="arrow-right" size="16" ></up-icon> |
| @@ -154,24 +174,25 @@ | @@ -154,24 +174,25 @@ | ||
| 154 | </view> | 174 | </view> |
| 155 | </template> | 175 | </template> |
| 156 | 176 | ||
| 157 | -<script setup lang="ts"> | ||
| 158 | -import {ref} from 'vue' | ||
| 159 | - | ||
| 160 | -import type {UniFormRef} from '@/uni_modules/uview-plus/types' | ||
| 161 | -// 定义ref供选项式API使用 | ||
| 162 | -const workOrderFormRef = ref<UniFormRef>(null) | ||
| 163 | - | ||
| 164 | -</script> | ||
| 165 | - | ||
| 166 | <script lang="ts"> | 177 | <script lang="ts"> |
| 167 | -import {getRoadListByLatLng} from '@/api/common' | ||
| 168 | -import {uploadImages} from '@/common/utils/upload'; | ||
| 169 | -import {createQuick} from '@/api/quick-order/quick-order' | ||
| 170 | - | 178 | +import { getRoadListByLatLng } from '@/api/common' |
| 179 | +import { uploadImages } from '@/common/utils/upload'; | ||
| 180 | +import { createQuick } from '@/api/quick-order/quick-order' | ||
| 181 | +import { useUserStore } from '@/pinia/user'; | ||
| 171 | 182 | ||
| 172 | export default { | 183 | export default { |
| 173 | data() { | 184 | data() { |
| 174 | return { | 185 | return { |
| 186 | + // 业务线相关 | ||
| 187 | + busiLineMap: { | ||
| 188 | + 'yl': '园林', | ||
| 189 | + 'sz': '市政', | ||
| 190 | + 'wy': '物业', | ||
| 191 | + '园林': 'yl', | ||
| 192 | + '市政': 'sz', | ||
| 193 | + '物业': 'wy' | ||
| 194 | + }, | ||
| 195 | + busiLineOptions: [], // 业务线选项列表 | ||
| 175 | // 问题照片列表 | 196 | // 问题照片列表 |
| 176 | problemImgsList: [], | 197 | problemImgsList: [], |
| 177 | // 完成照片列表 | 198 | // 完成照片列表 |
| @@ -181,36 +202,36 @@ export default { | @@ -181,36 +202,36 @@ export default { | ||
| 181 | showOrderName: false, | 202 | showOrderName: false, |
| 182 | // 下拉列表数据 | 203 | // 下拉列表数据 |
| 183 | roadNameList: [], | 204 | roadNameList: [], |
| 184 | - orderNameList: [ | ||
| 185 | - // {name: '绿地卫生', code: 'ORDER001'}, | ||
| 186 | - // {name: '设施维修', code: 'ORDER002'}, | ||
| 187 | - // {name: '垃圾清理', code: 'ORDER003'} | ||
| 188 | - ], | 205 | + orderNameList: [], |
| 189 | // 工单表单数据 | 206 | // 工单表单数据 |
| 190 | workOrderForm: { | 207 | workOrderForm: { |
| 208 | + busiLineCn: '', // 业务线中文名称 | ||
| 191 | roadId: 0, // 道路ID | 209 | roadId: 0, // 道路ID |
| 192 | roadName: '', // 道路名称 | 210 | roadName: '', // 道路名称 |
| 193 | workLocation: '', // 工单位置 | 211 | workLocation: '', // 工单位置 |
| 194 | orderName: '', // 工单名称 | 212 | orderName: '', // 工单名称 |
| 195 | problemDesc: '', // 情况描述 | 213 | problemDesc: '', // 情况描述 |
| 196 | - handleResult: '', // 处理结果描述(不必填) | 214 | + handleResult: '', // 处理结果描述(不必填) |
| 197 | lat: 0, // 纬度 | 215 | lat: 0, // 纬度 |
| 198 | lon: 0 // 经度 | 216 | lon: 0 // 经度 |
| 199 | }, | 217 | }, |
| 200 | // 表单校验规则 | 218 | // 表单校验规则 |
| 201 | workOrderFormRules: { | 219 | workOrderFormRules: { |
| 220 | + busiLineCn: [ // 业务线必选校验 | ||
| 221 | + { type: 'string', required: true, message: '请选择业务线', trigger: ['change', 'blur'] } | ||
| 222 | + ], | ||
| 202 | workLocation: [ | 223 | workLocation: [ |
| 203 | - {type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur']} | 224 | + { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] } |
| 204 | ], | 225 | ], |
| 205 | roadName: [ | 226 | roadName: [ |
| 206 | - {type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur']} | 227 | + { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] } |
| 207 | ], | 228 | ], |
| 208 | orderName: [ | 229 | orderName: [ |
| 209 | - {type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur']} | 230 | + { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] } |
| 210 | ], | 231 | ], |
| 211 | problemDesc: [ | 232 | problemDesc: [ |
| 212 | - {type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur']}, | ||
| 213 | - {type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur']} | 233 | + { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, |
| 234 | + { type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur'] } | ||
| 214 | ], | 235 | ], |
| 215 | problemImgs: [ | 236 | problemImgs: [ |
| 216 | { | 237 | { |
| @@ -218,7 +239,6 @@ export default { | @@ -218,7 +239,6 @@ export default { | ||
| 218 | message: '请上传问题照片', | 239 | message: '请上传问题照片', |
| 219 | trigger: 'change', | 240 | trigger: 'change', |
| 220 | validator: (rule, value, callback) => { | 241 | validator: (rule, value, callback) => { |
| 221 | - // 自定义校验规则:检查是否有成功上传的图片 | ||
| 222 | const hasSuccessImg = this.problemImgsList.some(item => item.status === 'success') | 242 | const hasSuccessImg = this.problemImgsList.some(item => item.status === 'success') |
| 223 | hasSuccessImg ? callback() : callback(new Error('请上传至少1张问题照片')) | 243 | hasSuccessImg ? callback() : callback(new Error('请上传至少1张问题照片')) |
| 224 | } | 244 | } |
| @@ -230,75 +250,145 @@ export default { | @@ -230,75 +250,145 @@ export default { | ||
| 230 | message: '请上传完成照片', | 250 | message: '请上传完成照片', |
| 231 | trigger: 'change', | 251 | trigger: 'change', |
| 232 | validator: (rule, value, callback) => { | 252 | validator: (rule, value, callback) => { |
| 233 | - // 自定义校验规则:检查是否有成功上传的图片 | ||
| 234 | const hasSuccessImg = this.completeImgsList.some(item => item.status === 'success') | 253 | const hasSuccessImg = this.completeImgsList.some(item => item.status === 'success') |
| 235 | hasSuccessImg ? callback() : callback(new Error('请上传至少1张完成照片')) | 254 | hasSuccessImg ? callback() : callback(new Error('请上传至少1张完成照片')) |
| 236 | } | 255 | } |
| 237 | } | 256 | } |
| 238 | - ], | ||
| 239 | - | 257 | + ] |
| 240 | } | 258 | } |
| 241 | } | 259 | } |
| 242 | }, | 260 | }, |
| 261 | + onLoad() { | ||
| 262 | + // 初始化业务线选项 | ||
| 263 | + this.initBusiLineOptions(); | ||
| 264 | + // 默认选中第一个业务线 | ||
| 265 | + if (this.busiLineOptions && this.busiLineOptions.length > 0) { | ||
| 266 | + this.workOrderForm.busiLineCn = this.busiLineOptions[0].name; | ||
| 267 | + console.log('默认选中业务线:', this.workOrderForm.busiLineCn); | ||
| 268 | + } | ||
| 269 | + }, | ||
| 243 | onReady() { | 270 | onReady() { |
| 244 | - // 兼容微信小程序,通过setRules设置校验规则 | ||
| 245 | - this.$refs.workOrderFormRef.setRules(this.workOrderFormRules) | ||
| 246 | - console.log('工单表单规则初始化完成') | 271 | + // 设置表单校验规则 |
| 272 | + this.$refs.workOrderFormRef.setRules(this.workOrderFormRules); | ||
| 273 | + console.log('工单表单规则初始化完成'); | ||
| 247 | }, | 274 | }, |
| 248 | - onShow(){ | ||
| 249 | - console.log(uni.$dict.getDictLabel('ai_image_status', 20)) | ||
| 250 | - console.log(uni.$dict.getDictSimpleList('work_name')) | ||
| 251 | - this.orderNameList = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')) | ||
| 252 | - console.log(this.orderNameList) | 275 | + onShow() { |
| 276 | + this.orderNameList = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')); | ||
| 277 | + console.log('工单名称列表:', this.orderNameList); | ||
| 253 | }, | 278 | }, |
| 254 | methods: { | 279 | methods: { |
| 280 | + // 初始化业务线选项 | ||
| 281 | + initBusiLineOptions() { | ||
| 282 | + // 获取pinia中的用户信息 | ||
| 283 | + const userStore = useUserStore(); | ||
| 284 | + if (userStore.userInfo?.user?.busiLine) { | ||
| 285 | + const rawBusiLines = userStore.userInfo.user.busiLine.split(','); | ||
| 286 | + // 生成中文名称列表 | ||
| 287 | + this.busiLineOptions = rawBusiLines.map(item => ({ | ||
| 288 | + name: this.busiLineMap[item.trim()] // name=中文名称(园林/市政/物业) | ||
| 289 | + })); | ||
| 290 | + } | ||
| 291 | + console.log('业务线选项:', this.busiLineOptions); | ||
| 292 | + }, | ||
| 293 | + // 工具方法:通过中文名称获取对应的英文标识 | ||
| 294 | + getBusiLineEnByCn(cnName) { | ||
| 295 | + return this.busiLineMap[cnName] || ''; | ||
| 296 | + }, | ||
| 297 | + // 业务线切换事件 | ||
| 298 | + handleBusiLineChange() { | ||
| 299 | + // 清空道路信息 | ||
| 300 | + this.workOrderForm.roadName = ''; | ||
| 301 | + this.workOrderForm.roadId = 0; | ||
| 302 | + this.roadNameList = []; | ||
| 303 | + // 若已选择位置,重新请求对应业务线的道路列表 | ||
| 304 | + if (this.workOrderForm.workLocation) { | ||
| 305 | + this.getRoadListByBusiLine(); | ||
| 306 | + } | ||
| 307 | + }, | ||
| 308 | + // 根据选中业务线请求道路列表 | ||
| 309 | + async getRoadListByBusiLine() { | ||
| 310 | + if (!this.workOrderForm.lat || !this.workOrderForm.lon) { | ||
| 311 | + return; | ||
| 312 | + } | ||
| 313 | + // 中文转英文标识 | ||
| 314 | + const busiLineEn = this.getBusiLineEnByCn(this.workOrderForm.busiLineCn); | ||
| 315 | + if (!busiLineEn) { | ||
| 316 | + uni.showToast({ title: '业务线标识异常', icon: 'none' }); | ||
| 317 | + return; | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + try { | ||
| 321 | + uni.showLoading({ title: '获取道路名称中...' }); | ||
| 322 | + const roadRes = await getRoadListByLatLng({ | ||
| 323 | + busiLine: busiLineEn, // 传递业务线英文标识 | ||
| 324 | + latitude: this.workOrderForm.lat, | ||
| 325 | + longitude: this.workOrderForm.lon | ||
| 326 | + }); | ||
| 327 | + uni.hideLoading(); | ||
| 328 | + if (Array.isArray(roadRes)) { | ||
| 329 | + this.roadNameList = roadRes.map((item) => ({ | ||
| 330 | + name: item.roadName || '', | ||
| 331 | + code: item.roadCode || '', | ||
| 332 | + id: item.roadId || 0 | ||
| 333 | + })); | ||
| 334 | + } else { | ||
| 335 | + this.roadNameList = [{ name: '未查询到道路名称', code: '', id: 0 }]; | ||
| 336 | + uni.showToast({ title: '未查询到该位置的道路信息', icon: 'none' }); | ||
| 337 | + } | ||
| 338 | + } catch (err) { | ||
| 339 | + uni.hideLoading(); | ||
| 340 | + console.error('获取道路名称失败:', err); | ||
| 341 | + uni.showToast({ title: '获取道路名称失败,请重试', icon: 'none' }); | ||
| 342 | + this.roadNameList = [{ name: '获取失败,请重新选择位置', code: '', id: 0 }]; | ||
| 343 | + } | ||
| 344 | + }, | ||
| 255 | /** | 345 | /** |
| 256 | * 返回上一页 | 346 | * 返回上一页 |
| 257 | */ | 347 | */ |
| 258 | navigateBack() { | 348 | navigateBack() { |
| 259 | - uni.navigateBack() | 349 | + uni.navigateBack(); |
| 260 | }, | 350 | }, |
| 261 | /** | 351 | /** |
| 262 | * 删除图片 | 352 | * 删除图片 |
| 263 | */ | 353 | */ |
| 264 | deleteImg(event, type) { | 354 | deleteImg(event, type) { |
| 265 | - console.log('删除图片事件:', event, '类型:', type) | 355 | + console.log('删除图片事件:', event, '类型:', type); |
| 266 | if (type === 'problemImgsList') { | 356 | if (type === 'problemImgsList') { |
| 267 | - this.problemImgsList.splice(event.index, 1) | 357 | + this.problemImgsList.splice(event.index, 1); |
| 268 | } else if (type === 'completeImgsList') { | 358 | } else if (type === 'completeImgsList') { |
| 269 | - this.completeImgsList.splice(event.index, 1) | 359 | + this.completeImgsList.splice(event.index, 1); |
| 270 | } | 360 | } |
| 271 | // 删除图片后重新校验图片字段 | 361 | // 删除图片后重新校验图片字段 |
| 272 | if (type === 'problemImgsList') { | 362 | if (type === 'problemImgsList') { |
| 273 | - this.$refs.workOrderFormRef.validateField('problemImgs') | 363 | + this.$refs.workOrderFormRef.validateField('problemImgs'); |
| 274 | } else if (type === 'completeImgsList') { | 364 | } else if (type === 'completeImgsList') { |
| 275 | - this.$refs.workOrderFormRef.validateField('completeImgs') | 365 | + this.$refs.workOrderFormRef.validateField('completeImgs'); |
| 276 | } | 366 | } |
| 277 | - uni.showToast({title: '图片删除成功', icon: 'success'}) | 367 | + uni.showToast({ title: '图片删除成功', icon: 'success' }); |
| 278 | }, | 368 | }, |
| 279 | /** | 369 | /** |
| 280 | * 上传图片 | 370 | * 上传图片 |
| 281 | */ | 371 | */ |
| 282 | async uploadImgs(event, type) { | 372 | async uploadImgs(event, type) { |
| 283 | - console.log('上传图片事件:', event, '类型:', type) | ||
| 284 | - const fileList = Array.isArray(event.file) ? event.file : [event.file] | ||
| 285 | - const targetImgList = type === 'problemImgsList' ? this.problemImgsList : this.completeImgsList | 373 | + console.log('上传图片事件:', event, '类型:', type); |
| 374 | + const fileList = Array.isArray(event.file) ? event.file : [event.file]; | ||
| 375 | + const targetImgList = type === 'problemImgsList' ? this.problemImgsList : this.completeImgsList; | ||
| 286 | 376 | ||
| 287 | - const filePaths = fileList.map(item => item.url) | 377 | + const filePaths = fileList.map(item => item.url); |
| 288 | const tempItems = fileList.map(item => ({ | 378 | const tempItems = fileList.map(item => ({ |
| 289 | ...item, | 379 | ...item, |
| 290 | status: 'uploading', | 380 | status: 'uploading', |
| 291 | message: '上传中' | 381 | message: '上传中' |
| 292 | - })) | ||
| 293 | - const startIndex = targetImgList.length | ||
| 294 | - targetImgList.push(...tempItems) | 382 | + })); |
| 383 | + const startIndex = targetImgList.length; | ||
| 384 | + targetImgList.push(...tempItems); | ||
| 295 | 385 | ||
| 296 | try { | 386 | try { |
| 297 | const uploadResultUrls = await uploadImages({ | 387 | const uploadResultUrls = await uploadImages({ |
| 298 | filePaths: filePaths, | 388 | filePaths: filePaths, |
| 299 | ignoreError: true | 389 | ignoreError: true |
| 300 | - }) | ||
| 301 | - console.log('上传成功的URL列表:', uploadResultUrls) | 390 | + }); |
| 391 | + console.log('上传成功的URL列表:', uploadResultUrls); | ||
| 302 | 392 | ||
| 303 | uploadResultUrls.forEach((url, index) => { | 393 | uploadResultUrls.forEach((url, index) => { |
| 304 | if (targetImgList[startIndex + index]) { | 394 | if (targetImgList[startIndex + index]) { |
| @@ -307,150 +397,131 @@ export default { | @@ -307,150 +397,131 @@ export default { | ||
| 307 | status: 'success', | 397 | status: 'success', |
| 308 | message: '', | 398 | message: '', |
| 309 | url: url | 399 | url: url |
| 310 | - }) | 400 | + }); |
| 311 | } | 401 | } |
| 312 | - }) | 402 | + }); |
| 313 | 403 | ||
| 314 | if (uploadResultUrls.length < fileList.length) { | 404 | if (uploadResultUrls.length < fileList.length) { |
| 315 | - const failCount = fileList.length - uploadResultUrls.length | 405 | + const failCount = fileList.length - uploadResultUrls.length; |
| 316 | for (let i = uploadResultUrls.length; i < fileList.length; i++) { | 406 | for (let i = uploadResultUrls.length; i < fileList.length; i++) { |
| 317 | if (targetImgList[startIndex + i]) { | 407 | if (targetImgList[startIndex + i]) { |
| 318 | targetImgList.splice(startIndex + i, 1, { | 408 | targetImgList.splice(startIndex + i, 1, { |
| 319 | ...fileList[i], | 409 | ...fileList[i], |
| 320 | status: 'failed', | 410 | status: 'failed', |
| 321 | message: '上传失败' | 411 | message: '上传失败' |
| 322 | - }) | 412 | + }); |
| 323 | } | 413 | } |
| 324 | } | 414 | } |
| 325 | - uni.showToast({title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none'}) | 415 | + uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' }); |
| 326 | } else { | 416 | } else { |
| 327 | - uni.showToast({title: `成功上传${fileList.length}张图片`, icon: 'success'}) | 417 | + uni.showToast({ title: `成功上传${fileList.length}张图片`, icon: 'success' }); |
| 328 | } | 418 | } |
| 329 | 419 | ||
| 330 | // 上传完成后重新校验图片字段 | 420 | // 上传完成后重新校验图片字段 |
| 331 | if (type === 'problemImgsList') { | 421 | if (type === 'problemImgsList') { |
| 332 | - this.$refs.workOrderFormRef.validateField('problemImgs') | 422 | + this.$refs.workOrderFormRef.validateField('problemImgs'); |
| 333 | } else if (type === 'completeImgsList') { | 423 | } else if (type === 'completeImgsList') { |
| 334 | - this.$refs.workOrderFormRef.validateField('completeImgs') | 424 | + this.$refs.workOrderFormRef.validateField('completeImgs'); |
| 335 | } | 425 | } |
| 336 | } catch (err) { | 426 | } catch (err) { |
| 337 | - console.error('图片上传失败:', err) | 427 | + console.error('图片上传失败:', err); |
| 338 | for (let i = 0; i < fileList.length; i++) { | 428 | for (let i = 0; i < fileList.length; i++) { |
| 339 | if (targetImgList[startIndex + i]) { | 429 | if (targetImgList[startIndex + i]) { |
| 340 | targetImgList.splice(startIndex + i, 1, { | 430 | targetImgList.splice(startIndex + i, 1, { |
| 341 | ...fileList[i], | 431 | ...fileList[i], |
| 342 | status: 'failed', | 432 | status: 'failed', |
| 343 | message: '上传失败' | 433 | message: '上传失败' |
| 344 | - }) | 434 | + }); |
| 345 | } | 435 | } |
| 346 | } | 436 | } |
| 347 | - uni.showToast({title: '图片上传失败,请重试', icon: 'none'}) | 437 | + uni.showToast({ title: '图片上传失败,请重试', icon: 'none' }); |
| 348 | 438 | ||
| 349 | // 上传失败后重新校验图片字段 | 439 | // 上传失败后重新校验图片字段 |
| 350 | if (type === 'problemImgsList') { | 440 | if (type === 'problemImgsList') { |
| 351 | - this.$refs.workOrderFormRef.validateField('problemImgs') | 441 | + this.$refs.workOrderFormRef.validateField('problemImgs'); |
| 352 | } else if (type === 'completeImgsList') { | 442 | } else if (type === 'completeImgsList') { |
| 353 | - this.$refs.workOrderFormRef.validateField('completeImgs') | 443 | + this.$refs.workOrderFormRef.validateField('completeImgs'); |
| 354 | } | 444 | } |
| 355 | } | 445 | } |
| 356 | }, | 446 | }, |
| 357 | /** | 447 | /** |
| 358 | - * 选择工单位置(移除isSubmitting判断) | 448 | + * 选择工单位置 |
| 359 | */ | 449 | */ |
| 360 | chooseWorkLocation() { | 450 | chooseWorkLocation() { |
| 361 | - let that = this | 451 | + let that = this; |
| 362 | uni.chooseLocation({ | 452 | uni.chooseLocation({ |
| 363 | success: async (res) => { | 453 | success: async (res) => { |
| 364 | - that.workOrderForm.roadName = '' | ||
| 365 | - that.workOrderForm.roadId = 0 | ||
| 366 | - that.roadNameList = [] | ||
| 367 | - | ||
| 368 | - that.workOrderForm.workLocation = res.name | ||
| 369 | - that.workOrderForm.lat = res.latitude | ||
| 370 | - that.workOrderForm.lon = res.longitude | ||
| 371 | - | ||
| 372 | - that.$refs.workOrderFormRef.validateField('workLocation') | ||
| 373 | - that.$refs.workOrderFormRef.validateField('roadName') | ||
| 374 | - | ||
| 375 | - try { | ||
| 376 | - uni.showLoading({title: '获取道路名称中...'}) | ||
| 377 | - const roadRes = await getRoadListByLatLng({ | ||
| 378 | - companyCode: 'sls', | ||
| 379 | - latitude: res.latitude, | ||
| 380 | - longitude: res.longitude | ||
| 381 | - }) | ||
| 382 | - uni.hideLoading() | ||
| 383 | - | ||
| 384 | - if (Array.isArray(roadRes)) { | ||
| 385 | - that.roadNameList = roadRes.map((item) => ({ | ||
| 386 | - name: item.roadName || '', | ||
| 387 | - code: item.roadCode || '', | ||
| 388 | - id: item.roadId || 0 | ||
| 389 | - })) | ||
| 390 | - } else { | ||
| 391 | - that.roadNameList = [{name: '未查询到道路名称', code: '', id: 0}] | ||
| 392 | - uni.showToast({title: '未查询到该位置的道路信息', icon: 'none'}) | ||
| 393 | - } | ||
| 394 | - } catch (err) { | ||
| 395 | - uni.hideLoading() | ||
| 396 | - console.error('获取道路名称失败:', err) | ||
| 397 | - uni.showToast({title: '获取道路名称失败,请重试', icon: 'none'}) | ||
| 398 | - that.roadNameList = [{name: '获取失败,请重新选择位置', code: '', id: 0}] | ||
| 399 | - } | 454 | + that.workOrderForm.roadName = ''; |
| 455 | + that.workOrderForm.roadId = 0; | ||
| 456 | + that.roadNameList = []; | ||
| 457 | + | ||
| 458 | + that.workOrderForm.workLocation = res.name; | ||
| 459 | + that.workOrderForm.lat = res.latitude; | ||
| 460 | + that.workOrderForm.lon = res.longitude; | ||
| 461 | + | ||
| 462 | + that.$refs.workOrderFormRef.validateField('workLocation'); | ||
| 463 | + that.$refs.workOrderFormRef.validateField('roadName'); | ||
| 464 | + | ||
| 465 | + // 调用封装的方法,自动携带业务线 | ||
| 466 | + await that.getRoadListByBusiLine(); | ||
| 400 | }, | 467 | }, |
| 401 | fail: (err) => { | 468 | fail: (err) => { |
| 402 | - console.error('选择位置失败:', err) | ||
| 403 | - uni.showToast({title: '选择位置失败:' + err.errMsg, icon: 'none'}) | 469 | + console.error('选择位置失败:', err); |
| 470 | + uni.showToast({ title: '选择位置失败:' + err.errMsg, icon: 'none' }); | ||
| 404 | } | 471 | } |
| 405 | - }) | 472 | + }); |
| 406 | }, | 473 | }, |
| 407 | /** | 474 | /** |
| 408 | * 选择道路名称 | 475 | * 选择道路名称 |
| 409 | */ | 476 | */ |
| 410 | handleRoadNameSelect(e) { | 477 | handleRoadNameSelect(e) { |
| 411 | - console.log('选择道路名称:', e) | ||
| 412 | - this.workOrderForm.roadName = e.name | ||
| 413 | - this.workOrderForm.roadId = e.code | ||
| 414 | - this.showRoadName = false | ||
| 415 | - this.$refs.workOrderFormRef.validateField('roadName') | 478 | + console.log('选择道路名称:', e); |
| 479 | + this.workOrderForm.roadName = e.name; | ||
| 480 | + this.workOrderForm.roadId = e.code; | ||
| 481 | + this.showRoadName = false; | ||
| 482 | + this.$refs.workOrderFormRef.validateField('roadName'); | ||
| 416 | }, | 483 | }, |
| 417 | /** | 484 | /** |
| 418 | * 选择工单名称 | 485 | * 选择工单名称 |
| 419 | */ | 486 | */ |
| 420 | handleOrderNameSelect(e) { | 487 | handleOrderNameSelect(e) { |
| 421 | - console.log(e) | ||
| 422 | - this.workOrderForm.orderName = e.name | ||
| 423 | - this.showOrderName = false | ||
| 424 | - this.$refs.workOrderFormRef.validateField('orderName') | 488 | + console.log(e); |
| 489 | + this.workOrderForm.orderName = e.name; | ||
| 490 | + this.showOrderName = false; | ||
| 491 | + this.$refs.workOrderFormRef.validateField('orderName'); | ||
| 425 | }, | 492 | }, |
| 426 | /** | 493 | /** |
| 427 | * 隐藏键盘 | 494 | * 隐藏键盘 |
| 428 | */ | 495 | */ |
| 429 | hideKeyboard() { | 496 | hideKeyboard() { |
| 430 | - uni.hideKeyboard() | 497 | + uni.hideKeyboard(); |
| 431 | }, | 498 | }, |
| 432 | /** | 499 | /** |
| 433 | * 提取图片URL数组 | 500 | * 提取图片URL数组 |
| 434 | */ | 501 | */ |
| 435 | getImgUrlList(imgList) { | 502 | getImgUrlList(imgList) { |
| 436 | - return imgList.filter(item => item.status === 'success').map(item => item.url) | 503 | + return imgList.filter(item => item.status === 'success').map(item => item.url); |
| 437 | }, | 504 | }, |
| 438 | /** | 505 | /** |
| 439 | - * 提交工单(添加成功跳转逻辑) | ||
| 440 | - */ | ||
| 441 | - /** | ||
| 442 | - * 提交工单(添加成功跳转逻辑) | 506 | + * 提交工单 |
| 443 | */ | 507 | */ |
| 444 | async submitWorkOrder() { | 508 | async submitWorkOrder() { |
| 445 | try { | 509 | try { |
| 446 | - // 先执行表单校验(改用async/await写法,更易维护) | ||
| 447 | - await this.$refs.workOrderFormRef.validate() | 510 | + // 先执行表单校验 |
| 511 | + await this.$refs.workOrderFormRef.validate(); | ||
| 512 | + | ||
| 513 | + // 中文转英文标识 | ||
| 514 | + const busiLineEn = this.getBusiLineEnByCn(this.workOrderForm.busiLineCn); | ||
| 515 | + if (!busiLineEn) { | ||
| 516 | + uni.showToast({ title: '业务线选择异常,请重新选择', icon: 'none' }); | ||
| 517 | + return; | ||
| 518 | + } | ||
| 448 | 519 | ||
| 449 | const submitData = { | 520 | const submitData = { |
| 450 | roadId: this.workOrderForm.roadId, | 521 | roadId: this.workOrderForm.roadId, |
| 451 | roadName: this.workOrderForm.roadName, | 522 | roadName: this.workOrderForm.roadName, |
| 452 | problemsImgs: this.getImgUrlList(this.problemImgsList), | 523 | problemsImgs: this.getImgUrlList(this.problemImgsList), |
| 453 | - endImgs : this.getImgUrlList(this.completeImgsList), | 524 | + endImgs: this.getImgUrlList(this.completeImgsList), |
| 454 | remark: this.workOrderForm.problemDesc.trim(), | 525 | remark: this.workOrderForm.problemDesc.trim(), |
| 455 | handleResult: this.workOrderForm.handleResult.trim(), | 526 | handleResult: this.workOrderForm.handleResult.trim(), |
| 456 | latLonType: 2, | 527 | latLonType: 2, |
| @@ -460,50 +531,43 @@ export default { | @@ -460,50 +531,43 @@ export default { | ||
| 460 | pressingType: 2, | 531 | pressingType: 2, |
| 461 | orderName: this.workOrderForm.orderName, | 532 | orderName: this.workOrderForm.orderName, |
| 462 | sourceId: 1, | 533 | sourceId: 1, |
| 463 | - sourceName: '园林', | 534 | + sourceName: this.workOrderForm.busiLineCn, // 业务线中文名称 |
| 464 | thirdWorkNo: '', | 535 | thirdWorkNo: '', |
| 465 | - busiLine:'yl' | ||
| 466 | - } | 536 | + busiLine: busiLineEn // 业务线英文标识(yl/sz/wy) |
| 537 | + }; | ||
| 467 | 538 | ||
| 468 | // 显示加载中 | 539 | // 显示加载中 |
| 469 | - uni.showLoading({title: '提交中...'}) | 540 | + uni.showLoading({ title: '提交中...' }); |
| 470 | 541 | ||
| 471 | - // 调用提交接口(await需要async函数支持) | ||
| 472 | - const res = await createQuick(submitData) | 542 | + // 调用提交接口 |
| 543 | + const res = await createQuick(submitData); | ||
| 473 | 544 | ||
| 474 | - uni.hideLoading() | 545 | + uni.hideLoading(); |
| 475 | uni.showToast({ | 546 | uni.showToast({ |
| 476 | title: '工单提交成功', | 547 | title: '工单提交成功', |
| 477 | icon: 'success', | 548 | icon: 'success', |
| 478 | duration: 1000 | 549 | duration: 1000 |
| 479 | - }) | 550 | + }); |
| 480 | 551 | ||
| 481 | - // 延迟跳转(等待提示框显示完成) | 552 | + // 延迟跳转 |
| 482 | setTimeout(() => { | 553 | setTimeout(() => { |
| 483 | uni.reLaunch({ | 554 | uni.reLaunch({ |
| 484 | url: '/pages-sub/daily/quick-order/index' | 555 | url: '/pages-sub/daily/quick-order/index' |
| 485 | - }) | ||
| 486 | - }, 1000) | 556 | + }); |
| 557 | + }, 1000); | ||
| 487 | } catch (error) { | 558 | } catch (error) { |
| 488 | // 隐藏加载框 | 559 | // 隐藏加载框 |
| 489 | - uni.hideLoading() | 560 | + uni.hideLoading(); |
| 490 | 561 | ||
| 491 | // 区分是表单校验失败还是接口调用失败 | 562 | // 区分是表单校验失败还是接口调用失败 |
| 492 | - if (Array.isArray(error)) { | ||
| 493 | - // 表单校验失败 | ||
| 494 | - // uni.showToast({ | ||
| 495 | - // title: '表单填写不完整,请检查', | ||
| 496 | - // icon: 'none', | ||
| 497 | - // duration: 2000 | ||
| 498 | - // }) | ||
| 499 | - } else { | 563 | + if (!Array.isArray(error)) { |
| 500 | // 接口调用失败 | 564 | // 接口调用失败 |
| 501 | - console.error('工单提交失败:', error) | 565 | + console.error('工单提交失败:', error); |
| 502 | uni.showToast({ | 566 | uni.showToast({ |
| 503 | title: '提交失败,请重试', | 567 | title: '提交失败,请重试', |
| 504 | icon: 'none', | 568 | icon: 'none', |
| 505 | duration: 2000 | 569 | duration: 2000 |
| 506 | - }) | 570 | + }); |
| 507 | } | 571 | } |
| 508 | } | 572 | } |
| 509 | } | 573 | } |
| @@ -522,6 +586,4 @@ export default { | @@ -522,6 +586,4 @@ export default { | ||
| 522 | background: #fff; | 586 | background: #fff; |
| 523 | margin-bottom: 100rpx; | 587 | margin-bottom: 100rpx; |
| 524 | } | 588 | } |
| 525 | - | ||
| 526 | - | ||
| 527 | </style> | 589 | </style> |
| 528 | \ No newline at end of file | 590 | \ No newline at end of file |
pages-sub/problem/regional-order-manage/index.vue
| 1 | -<script lang="ts"> | ||
| 2 | -import {defineComponent} from 'vue' | 1 | +<template> |
| 2 | + <view class="page-container"> | ||
| 3 | + <!-- 顶部固定区域 --> | ||
| 4 | + <up-sticky> | ||
| 5 | + <view class="header-wrap"> | ||
| 6 | + <!-- 第一行:u-tabs 待办/已办切换 :scrollable="false"--> | ||
| 7 | + <up-tabs | ||
| 8 | + v-model="activeTab" | ||
| 9 | + :list="tabList" | ||
| 10 | + active-color="#1989fa" | ||
| 11 | + inactive-color="#666" | ||
| 12 | + font-size="30rpx" | ||
| 13 | + @click="handleTabChange" | ||
| 14 | + /> | ||
| 3 | 15 | ||
| 4 | -export default defineComponent({ | ||
| 5 | - name: "index" | ||
| 6 | -}) | ||
| 7 | -</script> | 16 | + <!-- 第二行:下拉框 + 搜索框 --> |
| 17 | + <view class="search-header"> | ||
| 18 | + <!-- 左侧下拉框 --> | ||
| 19 | + <view class="select-wrap common-text-color"> | ||
| 20 | + <up-select | ||
| 21 | + v-model:current="selectedSortValue" | ||
| 22 | + :options="sortOptions" | ||
| 23 | + :showOptionsLabel="true" | ||
| 24 | + @select="handleSortChange" | ||
| 25 | + border="surround" | ||
| 26 | + :style="{ flex: 1 }" | ||
| 27 | + /> | ||
| 28 | + </view> | ||
| 8 | 29 | ||
| 9 | -<template> | 30 | + <!-- 右侧搜索框 --> |
| 31 | + <view class="search-input-wrap"> | ||
| 32 | + <up-search | ||
| 33 | + v-model="searchValue" | ||
| 34 | + placeholder="请输入关键字" | ||
| 35 | + @search="handleSearch" | ||
| 36 | + bg-color="#f5f5f5" | ||
| 37 | + :clearabled="false" | ||
| 38 | + :show-action="true" | ||
| 39 | + actionText="搜索" | ||
| 40 | + :animation="true" | ||
| 41 | + @custom="handleSearch" | ||
| 42 | + /> | ||
| 43 | + </view> | ||
| 44 | + </view> | ||
| 45 | + </view> | ||
| 46 | + </up-sticky> | ||
| 47 | + | ||
| 48 | + <!-- 列表容器 --> | ||
| 49 | + <z-paging | ||
| 50 | + ref="paging" | ||
| 51 | + v-model="orderList" | ||
| 52 | + @query="queryList" | ||
| 53 | + :auto-show-system-loading="true" | ||
| 54 | + | ||
| 55 | + > | ||
| 56 | + <template #empty> | ||
| 57 | + <empty-view/> | ||
| 58 | + </template> | ||
| 59 | + | ||
| 60 | + <view class="common-card-list" style="padding-top: 200rpx;padding-bottom: 30rpx"> | ||
| 61 | + <!-- 待办工单卡片 --> | ||
| 62 | + <up-card | ||
| 63 | + v-if="activeTab == 0" | ||
| 64 | + :border="false" | ||
| 65 | + :foot-border-top="false" | ||
| 66 | + v-for="(item, index) in orderList" | ||
| 67 | + :key="`todo_${item.orderNo}_${index}`" | ||
| 68 | + :show-head="false" | ||
| 69 | + class="order-card" | ||
| 70 | + > | ||
| 71 | + <template #body> | ||
| 72 | + <view class="card-body"> | ||
| 73 | + <view class="u-body-item u-flex"> | ||
| 74 | + <view class="u-body-item-title">工单编号:</view> | ||
| 75 | + <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view> | ||
| 76 | + </view> | ||
| 77 | + <view class="u-body-item u-flex"> | ||
| 78 | + <view class="u-body-item-title">工单位置:</view> | ||
| 79 | + <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view> | ||
| 80 | + </view> | ||
| 81 | + <view class="u-body-item u-flex"> | ||
| 82 | + <view class="u-body-item-title">工单名称:</view> | ||
| 83 | + <view class="u-line-1 u-body-value">{{ item.orderName || '未填写' }}</view> | ||
| 84 | + </view> | ||
| 85 | + <view class="u-body-item u-flex"> | ||
| 86 | + <view class="u-body-item-title">情况描述:</view> | ||
| 87 | + <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view> | ||
| 88 | + </view> | ||
| 89 | + <view class="u-body-item u-flex common-item-center common-justify-between"> | ||
| 90 | + <view class="u-body-item-title">紧急程度:</view> | ||
| 91 | + <view class="u-line-1 u-body-value"> | ||
| 92 | + {{ uni.$dict.getDictLabel('workorder_pressing_type', item.pressingType) }} | ||
| 93 | + </view> | ||
| 94 | + </view> | ||
| 95 | + <view class="u-body-item u-flex"> | ||
| 96 | + <view class="u-body-item-title">工单状态:</view> | ||
| 97 | + <view class="u-line-1 u-body-value">{{buzStatusMap[item.buzStatus] }}</view> | ||
| 98 | + </view> | ||
| 99 | + <view class="u-body-item u-flex"> | ||
| 100 | + <view class="u-body-item-title">提交时间:</view> | ||
| 101 | + <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view> | ||
| 102 | + </view> | ||
| 103 | + <!-- 操作按钮行 --> | ||
| 104 | + <view class="u-body-item u-flex common-justify-between common-item-center mt-20"> | ||
| 105 | + <up-button type="warning" size="mini" @click="handleReject(item)" | ||
| 106 | + v-show="nextStepMap[item.taskKey].backShow">回退 | ||
| 107 | + </up-button> | ||
| 108 | + | ||
| 109 | + <up-button type="success" size="mini" @click="handleRenew(item)" | ||
| 110 | + v-show="nextStepMap[item.taskKey].renewShow">重新提交 | ||
| 111 | + </up-button> | ||
| 112 | + | ||
| 113 | + <up-button type="primary" size="mini" @click="handleProcess(item)">{{ | ||
| 114 | + nextStepMap[item.taskKey].btnText | ||
| 115 | + }} | ||
| 116 | + </up-button> | ||
| 117 | + <up-button type="info" size="mini" @click="handleDetail(item)">详情</up-button> | ||
| 118 | + </view> | ||
| 119 | + </view> | ||
| 120 | + </template> | ||
| 121 | + </up-card> | ||
| 122 | + | ||
| 123 | + <!-- 已办工单卡片和我发起的 --> | ||
| 124 | + <up-card | ||
| 125 | + v-if="activeTab == 2||activeTab == 1" | ||
| 126 | + :border="false" | ||
| 127 | + :foot-border-top="false" | ||
| 128 | + v-for="(item, index) in orderList" | ||
| 129 | + :key="`done_${item.orderNo}_${index}`" | ||
| 130 | + :show-head="false" | ||
| 131 | + class="order-card" | ||
| 132 | + > | ||
| 133 | + <template #body> | ||
| 134 | + <view class="card-body"> | ||
| 135 | + <view class="u-body-item u-flex"> | ||
| 136 | + <view class="u-body-item-title">工单编号:</view> | ||
| 137 | + <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view> | ||
| 138 | + </view> | ||
| 139 | + <view class="u-body-item u-flex"> | ||
| 140 | + <view class="u-body-item-title">工单位置:</view> | ||
| 141 | + <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view> | ||
| 142 | + </view> | ||
| 143 | + <view class="u-body-item u-flex"> | ||
| 144 | + <view class="u-body-item-title">工单名称:</view> | ||
| 145 | + <view class="u-line-1 u-body-value">{{ item.orderName || '未填写' }}</view> | ||
| 146 | + </view> | ||
| 147 | + <view class="u-body-item u-flex"> | ||
| 148 | + <view class="u-body-item-title">情况描述:</view> | ||
| 149 | + <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view> | ||
| 150 | + </view> | ||
| 151 | + | ||
| 152 | + <view class="u-body-item u-flex common-justify-between common-item-center"> | ||
| 153 | + <view class="u-body-item-title">紧急程度: | ||
| 154 | + {{ uni.$dict.getDictLabel('workorder_pressing_type', item.pressingType) }} | ||
| 155 | + </view> | ||
| 156 | + <view class=" "> | ||
| 157 | + <up-button type="primary" size="mini" @click="handleDetail(item)">工单详情</up-button> | ||
| 158 | + </view> | ||
| 159 | + </view> | ||
| 160 | + <view class="u-body-item u-flex"> | ||
| 161 | + <view class="u-body-item-title">工单状态:</view> | ||
| 162 | + <view class="u-line-1 u-body-value">{{buzStatusMap[item.buzStatus] }}</view> | ||
| 163 | + </view> | ||
| 164 | + <view class="u-body-item u-flex"> | ||
| 165 | + <view class="u-body-item-title">提交时间:</view> | ||
| 166 | + <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view> | ||
| 167 | + </view> | ||
| 168 | + </view> | ||
| 169 | + </template> | ||
| 170 | + </up-card> | ||
| 171 | + </view> | ||
| 172 | + </z-paging> | ||
| 173 | + | ||
| 174 | + <!-- 底部新增工单按钮(仅巡查员显示) --> | ||
| 175 | +<!-- <view v-if="isInspector" class="fixed-bottom-btn-wrap">--> | ||
| 176 | +<!-- <up-button type="primary" size="large" @click="handleAddOrder">--> | ||
| 177 | +<!-- 新增工单--> | ||
| 178 | +<!-- </up-button>--> | ||
| 179 | +<!-- </view>--> | ||
| 180 | + | ||
| 181 | + <view class="fixed-bottom-btn-wrap"> | ||
| 182 | + <up-button type="primary" size="large" @click="handleAddOrder"> | ||
| 183 | + 新增工单 | ||
| 184 | + </up-button> | ||
| 185 | + </view> | ||
| 186 | + | ||
| 187 | + | ||
| 188 | + <!-- 回退原因弹窗:替换为up-modal(核心修改) --> | ||
| 189 | + <up-modal | ||
| 190 | + :show="rejectModalShow" | ||
| 191 | + title="回退原因" | ||
| 192 | + :closeOnClickOverlay="false" | ||
| 193 | + :showConfirmButton="true" | ||
| 194 | + :showCancelButton="true" | ||
| 195 | + @cancel="handleRejectModalCancel" | ||
| 196 | + @confirm="confirmReject" | ||
| 197 | + > | ||
| 198 | + <view class="reject-modal-content"> | ||
| 199 | + <!-- 回退原因 必填textarea --> | ||
| 200 | + <up-textarea | ||
| 201 | + v-model.trim="rejectReason" | ||
| 202 | + placeholder="请输入回退原因(必填)" | ||
| 203 | + rows="6" | ||
| 204 | + :count="200" | ||
| 205 | + maxlength="200" | ||
| 206 | + class="reject-textarea" | ||
| 207 | + /> | ||
| 208 | + <!-- 上传图片(选填)- 按照参考页面改造 --> | ||
| 209 | + <view class="upload-wrap mt-20"> | ||
| 210 | + <view class="upload-title">上传图片(选填)</view> | ||
| 211 | + <up-upload | ||
| 212 | + :file-list="rejectImgs.rawImgList.value|| []" | ||
| 213 | + @after-read="rejectImgs.uploadImgs" | ||
| 214 | + @delete="rejectImgs.deleteImg" | ||
| 215 | + multiple | ||
| 216 | + width="70" | ||
| 217 | + height="70" | ||
| 218 | + :max-count="rejectImgs.uploadConfig.maxCount" | ||
| 219 | + :upload-text="rejectImgs.uploadConfig.uploadText" | ||
| 220 | + :size-type="rejectImgs.uploadConfig.sizeType" | ||
| 221 | + /> | ||
| 222 | + </view> | ||
| 223 | + </view> | ||
| 224 | + </up-modal> | ||
| 225 | + | ||
| 226 | + <!-- 验收弹窗 up-modal(含图片上传) --> | ||
| 227 | + <up-modal | ||
| 228 | + :show="acceptModalShow" | ||
| 229 | + title="验收" | ||
| 230 | + :closeOnClickOverlay="false" | ||
| 231 | + :showConfirmButton="true" | ||
| 232 | + :showCancelButton="true" | ||
| 233 | + @cancel="handleAcceptModalCancel" | ||
| 234 | + @confirm="handleAcceptModalConfirm" | ||
| 235 | + > | ||
| 236 | + <view class="accept-modal-content"> | ||
| 237 | + <!-- 第一行:单选框(通过/不通过,默认通过) --> | ||
| 238 | + <view class="radio-group-wrap"> | ||
| 239 | + <up-radio-group v-model="acceptRadioValue"> | ||
| 240 | + <up-radio name="0" label="通过"></up-radio> | ||
| 241 | + <up-radio name="1" label="不通过"></up-radio> | ||
| 242 | + </up-radio-group> | ||
| 243 | + </view> | ||
| 244 | + | ||
| 245 | + <!-- 第二行:必填textarea,最多200字 --> | ||
| 246 | + <view class="textarea-wrap mt-30"> | ||
| 247 | + <up-textarea | ||
| 248 | + v-model.trim="acceptReason" | ||
| 249 | + placeholder="请输入验收原因(必填,最多200字)" | ||
| 250 | + :required="true" | ||
| 251 | + maxlength="200" | ||
| 252 | + rows="5" | ||
| 253 | + count | ||
| 254 | + /> | ||
| 255 | + </view> | ||
| 10 | 256 | ||
| 257 | + <!-- 验收图片上传(选填,参考回退弹窗样式) --> | ||
| 258 | + <view class="upload-wrap mt-20"> | ||
| 259 | + <view class="upload-title">上传验收图片(选填)</view> | ||
| 260 | + <up-upload | ||
| 261 | + :file-list="acceptImgs.rawImgList.value || []" | ||
| 262 | + @after-read="acceptImgs.uploadImgs" | ||
| 263 | + @delete="acceptImgs.deleteImg" | ||
| 264 | + | ||
| 265 | + multiple | ||
| 266 | + width="70" | ||
| 267 | + height="70" | ||
| 268 | + :max-count="acceptImgs.uploadConfig.maxCount" | ||
| 269 | + :upload-text="acceptImgs.uploadConfig.uploadText" | ||
| 270 | + :size-type="acceptImgs.uploadConfig.sizeType" | ||
| 271 | + /> | ||
| 272 | + </view> | ||
| 273 | + </view> | ||
| 274 | + </up-modal> | ||
| 275 | + </view> | ||
| 11 | </template> | 276 | </template> |
| 12 | 277 | ||
| 278 | +<script setup> | ||
| 279 | +import { ref, computed, watch } from 'vue'; | ||
| 280 | +import { onShow, onLoad } from '@dcloudio/uni-app'; | ||
| 281 | +import { timeFormat } from '@/uni_modules/uview-plus'; | ||
| 282 | +import { | ||
| 283 | + myBuzSimplePage, | ||
| 284 | + todoBuzSimplePage, | ||
| 285 | + doneBuzSimplePage, | ||
| 286 | + universalApproval | ||
| 287 | +} from '@/api/work-order-manage/work-order-manage' | ||
| 288 | +// 从用户store获取角色信息 | ||
| 289 | +import { useUserStore } from '@/pinia/user'; | ||
| 290 | +import { nextStepMap, buzStatusMap } from '@/common/utils/common' | ||
| 291 | +// 引入图片上传组合式函数(与参考页面一致) | ||
| 292 | +import { useUploadImgs } from '@/common/utils/useUploadImgs' | ||
| 293 | + | ||
| 294 | +// ========== 状态管理 ========== | ||
| 295 | +const userStore = useUserStore(); | ||
| 296 | +// 标签页切换 | ||
| 297 | +const activeTab = ref(0); // 0-待办 1-我发起的 2-已办 | ||
| 298 | +const tabList = ref([ | ||
| 299 | + {name: '待办'}, | ||
| 300 | + {name: '我发起的任务'}, | ||
| 301 | + {name: '已办'} | ||
| 302 | +]); | ||
| 303 | +// 排序下拉框 | ||
| 304 | +const selectedSortValue = ref(1); | ||
| 305 | +const sortOptions = ref([ | ||
| 306 | + {name: '位置', id: 1}, | ||
| 307 | + {name: '名称', id: 2}, | ||
| 308 | + {name: '描述', id: 3}, | ||
| 309 | + {name: '编号', id: 4}, | ||
| 310 | +]); | ||
| 311 | +// 搜索 | ||
| 312 | +const searchValue = ref(''); | ||
| 313 | +// 分页 | ||
| 314 | +const paging = ref(null); | ||
| 315 | +const orderList = ref([]); | ||
| 316 | +// 角色控制(巡查员显示新增按钮) | ||
| 317 | +const isInspector = computed(() => { | ||
| 318 | + // 增加可选链,避免用户信息不存在报错 | ||
| 319 | + return userStore.userInfo?.roles?.includes('yl_inspector') || false; | ||
| 320 | +}); | ||
| 321 | +// 回退弹窗相关 | ||
| 322 | +const rejectModalShow = ref(false); // 回退modal显示开关 | ||
| 323 | +const rejectReason = ref(''); // 回退原因 | ||
| 324 | +const currentRejectItem = ref(null); // 当前回退工单 | ||
| 325 | + | ||
| 326 | +// 回退图片上传配置(与参考页面风格一致) | ||
| 327 | +const rejectImgs = useUploadImgs({ | ||
| 328 | + maxCount: 3, // 最多上传3张 | ||
| 329 | + uploadText: '选择回退图片', // 自定义上传提示文字 | ||
| 330 | + sizeType: ['compressed'], // 仅上传压缩图 | ||
| 331 | + formRef: null, // 该弹窗无表单校验 | ||
| 332 | + fieldName: 'rejectImgs' // 自定义字段名 | ||
| 333 | +}) | ||
| 334 | + | ||
| 335 | + | ||
| 336 | +// ========== 验收弹窗相关状态(含图片上传) ========== | ||
| 337 | +const acceptModalShow = ref(false); // 验收弹窗显示开关 | ||
| 338 | +const acceptRadioValue = ref('0'); // 单选框值,默认0(通过) | ||
| 339 | +const acceptReason = ref(''); // 验收原因 | ||
| 340 | +const currentAcceptItem = ref(null); // 当前验收的工单项 | ||
| 341 | + | ||
| 342 | +// 验收图片上传配置(独立实例,参考回退弹窗) | ||
| 343 | +const acceptImgs = useUploadImgs({ | ||
| 344 | + maxCount: 3, // 最多上传3张,与回退弹窗一致 | ||
| 345 | + uploadText: '选择验收图片', // 自定义上传提示文字 | ||
| 346 | + sizeType: ['compressed'], // 仅上传压缩图,优化性能 | ||
| 347 | + formRef: null, // 验收弹窗无表单校验 | ||
| 348 | + fieldName: 'acceptImgs' // 自定义字段名,区分回退图片 | ||
| 349 | +}) | ||
| 350 | + | ||
| 351 | +// 分页查询列表 | ||
| 352 | +const queryList = async (pageNo, pageSize) => { | ||
| 353 | + try { | ||
| 354 | + const apiParams = { | ||
| 355 | + searchContent: searchValue.value.trim() || '', | ||
| 356 | + pageNo, | ||
| 357 | + pageSize, | ||
| 358 | + type: selectedSortValue.value // 1-位置 2-工单名称 3-情况描述 4-工单编号 | ||
| 359 | + }; | ||
| 360 | + let res; | ||
| 361 | + if (activeTab.value == 0) { | ||
| 362 | + // 待办工单 | ||
| 363 | + res = await todoBuzSimplePage(apiParams); | ||
| 364 | + } else if (activeTab.value == 1) { | ||
| 365 | + // 我发起的任务 | ||
| 366 | + res = await myBuzSimplePage(apiParams); | ||
| 367 | + } else { | ||
| 368 | + // 已办工单 | ||
| 369 | + res = await doneBuzSimplePage(apiParams); | ||
| 370 | + } | ||
| 371 | + // 适配z-paging分页 | ||
| 372 | + paging.value.complete(res.list, res.total); | ||
| 373 | + } catch (error) { | ||
| 374 | + console.error('加载工单失败:', error); | ||
| 375 | + paging.value?.complete(false); | ||
| 376 | + uni.showToast({title: '加载失败,请重试', icon: 'none'}); | ||
| 377 | + } | ||
| 378 | +}; | ||
| 379 | + | ||
| 380 | +// ========== 事件处理 ========== | ||
| 381 | +// 标签页切换 | ||
| 382 | +const handleTabChange = (item) => { | ||
| 383 | + console.log(item) | ||
| 384 | + activeTab.value = item.index; | ||
| 385 | + paging.value?.reload(); // 切换标签页刷新列表 | ||
| 386 | +}; | ||
| 387 | +// 排序变更 | ||
| 388 | +const handleSortChange = (val) => { | ||
| 389 | + selectedSortValue.value = val.id; | ||
| 390 | + searchValue.value = ''; | ||
| 391 | + paging.value?.reload(); // 排序变更刷新列表 | ||
| 392 | +}; | ||
| 393 | +// 搜索 | ||
| 394 | +const handleSearch = (val) => { | ||
| 395 | + searchValue.value = val; | ||
| 396 | + paging.value?.reload(); // 搜索刷新列表 | ||
| 397 | +}; | ||
| 398 | +// 工单详情 | ||
| 399 | +const handleDetail = (item) => { | ||
| 400 | + // 0-待办 1我发起的- 2-已办 | ||
| 401 | + uni.navigateTo({ | ||
| 402 | + url: `/pages-sub/problem/regional-order-manage/order-detail?taskId=${item.taskId}&activeTab=${activeTab.value}&processInstanceId=${item.processInstanceId}`, | ||
| 403 | + events: { | ||
| 404 | + // 自定义事件名:needRefresh(与详情页保持一致) | ||
| 405 | + needRefresh: () => { | ||
| 406 | + console.log('详情页返回,触发工单列表刷新'); | ||
| 407 | + if (paging.value) { | ||
| 408 | + paging.value.reload(); // 刷新z-paging列表 | ||
| 409 | + } | ||
| 410 | + } | ||
| 411 | + } | ||
| 412 | + }); | ||
| 413 | +}; | ||
| 414 | + | ||
| 415 | +// 生成临时key | ||
| 416 | +const generateTempKey = () => { | ||
| 417 | + return 'renew_order_' + Date.now() + '_' + Math.floor(Math.random() * 10000); | ||
| 418 | +}; | ||
| 419 | + | ||
| 420 | +// 待办-重新提交工单(改造后:大数据存本地,仅传唯一标识) | ||
| 421 | +const handleRenew = (item) => { | ||
| 422 | + // 校验工单有效性 | ||
| 423 | + if (!item || !item.id) { | ||
| 424 | + uni.showToast({title: '工单信息异常,无法重新提交', icon: 'none'}); | ||
| 425 | + return; | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + // 1. 生成唯一临时标识 | ||
| 429 | + const tempKey = generateTempKey(); | ||
| 430 | + | ||
| 431 | + // 2. 将完整工单数据存入本地临时存储(同步存储,确保数据立即生效) | ||
| 432 | + try { | ||
| 433 | + uni.setStorageSync(tempKey, item); | ||
| 434 | + } catch (error) { | ||
| 435 | + console.error('存储工单数据失败:', error); | ||
| 436 | + uni.showToast({title: '数据存储异常,无法重新提交', icon: 'none'}); | ||
| 437 | + return; | ||
| 438 | + } | ||
| 439 | + | ||
| 440 | + // 3. URL 仅传递「唯一标识」和「重新提交标记」(数据量极小,无长度问题) | ||
| 441 | + uni.navigateTo({ | ||
| 442 | + url: `/pages-sub/problem/work-order-manage/add-order?isRenew=1&tempKey=${tempKey}` | ||
| 443 | + }); | ||
| 444 | +}; | ||
| 445 | + | ||
| 446 | +// 待办-处理工单 | ||
| 447 | +const handleProcess = async (item) => { | ||
| 448 | + console.log(nextStepMap[item.taskKey].name) | ||
| 449 | + try { | ||
| 450 | + if (nextStepMap[item.taskKey]?.name == '养护组长分配') { | ||
| 451 | + uni.navigateTo({ | ||
| 452 | + url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}&id=${item.id}&busiLine=${item.busiLine}` | ||
| 453 | + }) | ||
| 454 | + } | ||
| 455 | + if (nextStepMap[item.taskKey]?.name == '养护员待实施') { | ||
| 456 | + | ||
| 457 | + // ① 生成唯一临时key(和重新提交工单逻辑一致,避免冲突) | ||
| 458 | + const tempKey = `maintain_order_${Date.now()}_${Math.floor(Math.random() * 10000)}`; | ||
| 459 | + | ||
| 460 | + // ② 存储完整item到本地缓存(同步存储,确保立即生效) | ||
| 461 | + try { | ||
| 462 | + uni.setStorageSync(tempKey, item); | ||
| 463 | + } catch (error) { | ||
| 464 | + console.error('存储养护工单数据失败:', error); | ||
| 465 | + uni.showToast({title: '数据存储异常,无法跳转', icon: 'none'}); | ||
| 466 | + return; | ||
| 467 | + } | ||
| 468 | + | ||
| 469 | + // ③ URL仅传递临时key(可选:携带必要简单参数,方便目标页面快速使用) | ||
| 470 | + uni.navigateTo({ | ||
| 471 | + url: `/pages-sub/problem/regional-order-manage/add-maintain-order?tempKey=${tempKey}` | ||
| 472 | + }) | ||
| 473 | + } | ||
| 474 | + // 养护组长验收 - 打开弹窗 | ||
| 475 | + if (nextStepMap[item.taskKey]?.name == '养护组长验收') { | ||
| 476 | + currentAcceptItem.value = item; // 存储当前工单信息 | ||
| 477 | + acceptReason.value = ''; // 清空上次的验收原因 | ||
| 478 | + acceptRadioValue.value = '0'; // 重置默认选中“通过” | ||
| 479 | + acceptModalShow.value = true; // 显示验收弹窗 | ||
| 480 | + } | ||
| 481 | + // 巡查员验收 - 打开弹窗 | ||
| 482 | + if (nextStepMap[item.taskKey]?.name == '巡查员验收') { | ||
| 483 | + currentAcceptItem.value = item; // 存储当前工单信息 | ||
| 484 | + acceptReason.value = ''; // 清空上次的验收原因 | ||
| 485 | + acceptRadioValue.value = '0'; // 重置默认选中“通过” | ||
| 486 | + acceptModalShow.value = true; // 显示验收弹窗 | ||
| 487 | + } | ||
| 488 | + | ||
| 489 | + // 发起人确认 | ||
| 490 | + if (nextStepMap[item.taskKey]?.name == '发起人确认') { | ||
| 491 | + console.log(item) | ||
| 492 | + uni.showModal({ | ||
| 493 | + title: "结束工单", | ||
| 494 | + content: "请确定是否结束工单?", | ||
| 495 | + success: async function (res) { | ||
| 496 | + if (res.confirm) { | ||
| 497 | + // 构建请求参数 | ||
| 498 | + const requestData = { | ||
| 499 | + "returnImgs": rejectImgs.getSuccessImgUrls(), // 改造后:获取上传成功的图片URL | ||
| 500 | + "workerDataId": item.id, | ||
| 501 | + "taskKey":'ylInspectorStart', | ||
| 502 | + "taskId": item.taskId, | ||
| 503 | + "operateType": 200, | ||
| 504 | + "agree": 1, | ||
| 505 | + "reason": '结束工单' | ||
| 506 | + }; | ||
| 507 | + // 调用回退工单接口 | ||
| 508 | + const res = await universalApproval(requestData); | ||
| 509 | + uni.showToast({title: '结束成功', icon: 'success', duration: 1000}); | ||
| 510 | + rejectModalShow.value = false; | ||
| 511 | + paging.value?.reload(); // 刷新列表 | ||
| 512 | + } else if (res.cancel) { | ||
| 513 | + console.log("用户点击取消"); | ||
| 514 | + } | ||
| 515 | + }, | ||
| 516 | + }); | ||
| 517 | + } | ||
| 518 | + } catch (error) { | ||
| 519 | + console.error('处理工单失败:', error); | ||
| 520 | + uni.showToast({title: '处理失败,请重试', icon: 'none'}); | ||
| 521 | + } | ||
| 522 | +}; | ||
| 523 | + | ||
| 524 | +// 待办-回退工单(打开回退modal) | ||
| 525 | +const handleReject = (item) => { | ||
| 526 | + console.log('123213') | ||
| 527 | + // 校验工单有效性 | ||
| 528 | + if (!item || !item.id) { | ||
| 529 | + uni.showToast({title: '工单信息异常,无法回退', icon: 'none'}); | ||
| 530 | + return; | ||
| 531 | + } | ||
| 532 | + currentRejectItem.value = item; | ||
| 533 | + rejectReason.value = ''; // 清空上次输入 | ||
| 534 | + rejectImgs.clearImgs(); // 改造后:使用组合式函数的清空方法 | ||
| 535 | + rejectModalShow.value = true; // 显示回退modal | ||
| 536 | +}; | ||
| 537 | + | ||
| 538 | +// 回退modal - 取消按钮 | ||
| 539 | +const handleRejectModalCancel = () => { | ||
| 540 | + rejectModalShow.value = false; | ||
| 541 | + rejectReason.value = ''; | ||
| 542 | + rejectImgs.clearImgs(); // 改造后:使用组合式函数的清空方法 | ||
| 543 | +}; | ||
| 544 | + | ||
| 545 | +// 确认回退工单 | ||
| 546 | +const confirmReject = async () => { | ||
| 547 | + // 严格校验回退原因(去除首尾空格) | ||
| 548 | + const rejectReasonTrim = rejectReason.value.trim(); | ||
| 549 | + if (!rejectReasonTrim) { | ||
| 550 | + uni.showToast({title: '请填写回退原因', icon: 'none', duration: 1000}); | ||
| 551 | + return; | ||
| 552 | + } | ||
| 553 | + // 校验当前工单有效性 | ||
| 554 | + if (!currentRejectItem.value || !currentRejectItem.value.id) { | ||
| 555 | + uni.showToast({title: '工单信息异常,无法提交', icon: 'none', duration:1000}); | ||
| 556 | + rejectModalShow.value = false; | ||
| 557 | + return; | ||
| 558 | + } | ||
| 559 | + try { | ||
| 560 | + // 显示加载中,防止重复提交 | ||
| 561 | + uni.showLoading({title: '提交中...', mask: true}); | ||
| 562 | + | ||
| 563 | + // 构建请求参数 | ||
| 564 | + const requestData = { | ||
| 565 | + "returnImgs": rejectImgs.getSuccessImgUrls(), // 改造后:获取上传成功的图片URL数组 | ||
| 566 | + "workerDataId": currentRejectItem.value.id, | ||
| 567 | + "taskKey": currentRejectItem.value.taskKey, | ||
| 568 | + "taskId": currentRejectItem.value.taskId, | ||
| 569 | + "operateType": nextStepMap[currentRejectItem.value.taskKey].operateTypeNoPass, | ||
| 570 | + "agree": 1, | ||
| 571 | + "reason": rejectReasonTrim | ||
| 572 | + }; | ||
| 573 | + // 调用回退工单接口 | ||
| 574 | + const res = await universalApproval(requestData); | ||
| 575 | + uni.showToast({title: '回退成功', icon: 'success', duration: 1000}); | ||
| 576 | + rejectModalShow.value = false; | ||
| 577 | + paging.value?.reload(); // 刷新列表 | ||
| 578 | + } catch (error) { | ||
| 579 | + console.error('回退工单失败:', error); | ||
| 580 | + uni.showToast({title: '网络异常,回退失败', icon: 'none', duration: 1000}); | ||
| 581 | + } finally { | ||
| 582 | + // 隐藏加载中 | ||
| 583 | + uni.hideLoading(); | ||
| 584 | + } | ||
| 585 | +}; | ||
| 586 | + | ||
| 587 | +// 新增工单 | ||
| 588 | +const handleAddOrder = () => { | ||
| 589 | + uni.navigateTo({ | ||
| 590 | + url: '/pages-sub/problem/regional-order-manage/add-order' | ||
| 591 | + }); | ||
| 592 | +}; | ||
| 593 | + | ||
| 594 | +// 验收弹窗 - 取消按钮(清空状态) | ||
| 595 | +const handleAcceptModalCancel = () => { | ||
| 596 | + acceptModalShow.value = false; | ||
| 597 | + acceptReason.value = ''; // 清空验收原因 | ||
| 598 | + acceptRadioValue.value = '0'; // 重置单选框为“通过” | ||
| 599 | + acceptImgs.clearImgs(); // 清空验收图片 | ||
| 600 | +}; | ||
| 601 | + | ||
| 602 | +// 验收弹窗 - 确定按钮(含returnImgs传参) | ||
| 603 | +const handleAcceptModalConfirm = async () => { | ||
| 604 | + // 1. 校验验收原因是否为空 | ||
| 605 | + if (!acceptReason.value.trim()) { | ||
| 606 | + uni.showToast({title: '请填写验收原因', icon: 'none', duration: 1000}); | ||
| 607 | + return; | ||
| 608 | + } | ||
| 609 | + // 2. 校验验收原因长度 | ||
| 610 | + if (acceptReason.value.length > 200) { | ||
| 611 | + uni.showToast({title: '验收原因最多200字', icon: 'none', duration: 1000}); | ||
| 612 | + return; | ||
| 613 | + } | ||
| 614 | + try { | ||
| 615 | + // 3. 构建请求参数(含returnImgs) | ||
| 616 | + console.log(currentAcceptItem.value) | ||
| 617 | + let postData = {} | ||
| 618 | + if (currentAcceptItem.value?.taskKey == 'ylTeamLeaderConfirm') { // 养护组长验收 | ||
| 619 | + postData = { | ||
| 620 | + "returnImgs": acceptImgs.getSuccessImgUrls(), // 验收图片URL数组 | ||
| 621 | + "taskKey": currentAcceptItem.value.taskKey, | ||
| 622 | + "workerDataId": currentAcceptItem.value.id, | ||
| 623 | + "taskId": currentAcceptItem.value.taskId, | ||
| 624 | + "operateType": acceptRadioValue.value == 0 ? nextStepMap[currentAcceptItem.value.taskKey].operateTypePass : nextStepMap[currentAcceptItem.value.taskKey].operateTypeNoPass, | ||
| 625 | + "reason": acceptReason.value.trim() | ||
| 626 | + } | ||
| 627 | + } | ||
| 628 | + if (currentAcceptItem.value?.taskKey == 'ylInspector') { // 巡查员验收 | ||
| 629 | + postData = { | ||
| 630 | + "returnImgs": acceptImgs.getSuccessImgUrls(), // 验收图片URL数组 | ||
| 631 | + "taskKey": currentAcceptItem.value.taskKey, | ||
| 632 | + "taskId": currentAcceptItem.value.taskId, | ||
| 633 | + "workerDataId": currentAcceptItem.value.id, | ||
| 634 | + "operateType": acceptRadioValue.value == 0 ? nextStepMap[currentAcceptItem.value.taskKey].operateTypePass : nextStepMap[currentAcceptItem.value.taskKey].operateTypeNoPass, | ||
| 635 | + "reason": acceptReason.value.trim(), | ||
| 636 | + "agree": acceptRadioValue.value | ||
| 637 | + } | ||
| 638 | + } | ||
| 639 | + const acceptRes = await universalApproval(postData); | ||
| 640 | + // 4. 操作成功处理 | ||
| 641 | + uni.showToast({title: '提交成功', icon: 'success', duration: 1000}); | ||
| 642 | + handleAcceptModalCancel(); // 清空状态 | ||
| 643 | + paging.value?.reload(); // 刷新工单列表 | ||
| 644 | + } catch (error) { | ||
| 645 | + // 5. 操作失败处理 | ||
| 646 | + console.error('验收失败:', error); | ||
| 647 | + uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 1000}); | ||
| 648 | + } | ||
| 649 | +}; | ||
| 650 | + | ||
| 651 | +// 页面初始化 | ||
| 652 | +onLoad(() => { | ||
| 653 | + // 初始化加载列表 | ||
| 654 | + paging.value?.reload(); | ||
| 655 | +}); | ||
| 656 | +</script> | ||
| 657 | + | ||
| 13 | <style scoped lang="scss"> | 658 | <style scoped lang="scss"> |
| 659 | +.page-container { | ||
| 660 | + min-height: 100vh; | ||
| 661 | + background-color: #fafafa; | ||
| 662 | +} | ||
| 663 | + | ||
| 664 | +// 顶部固定区域 | ||
| 665 | +.header-wrap { | ||
| 666 | + background-color: #fff; | ||
| 667 | +} | ||
| 668 | + | ||
| 669 | +// 搜索栏样式 | ||
| 670 | +.search-header { | ||
| 671 | + display: flex; | ||
| 672 | + align-items: center; | ||
| 673 | + padding: 20rpx; | ||
| 674 | + box-sizing: border-box; | ||
| 675 | + | ||
| 676 | + .select-wrap { | ||
| 677 | + width: 120rpx; | ||
| 678 | + margin-right: 20rpx; | ||
| 679 | + | ||
| 680 | + :deep(.u-select) { | ||
| 681 | + width: 100%; | ||
| 682 | + font-size: 28rpx; | ||
| 683 | + } | ||
| 684 | + | ||
| 685 | + :deep(.u-input__placeholder) { | ||
| 686 | + font-size: 28rpx; | ||
| 687 | + } | ||
| 688 | + } | ||
| 689 | + | ||
| 690 | + .search-input-wrap { | ||
| 691 | + flex: 1; | ||
| 692 | + } | ||
| 693 | +} | ||
| 694 | + | ||
| 695 | +// 工单卡片样式 | ||
| 696 | +.order-card { | ||
| 697 | + margin: 0 20rpx 20rpx; | ||
| 698 | + background: #fff; | ||
| 699 | + border-radius: 12rpx; | ||
| 700 | + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04); | ||
| 701 | +} | ||
| 702 | + | ||
| 703 | +.card-body { | ||
| 704 | + | ||
| 705 | +} | ||
| 706 | + | ||
| 707 | +// 回退modal样式 | ||
| 708 | +.reject-modal-content { | ||
| 709 | + width: 100%; | ||
| 710 | + box-sizing: border-box; | ||
| 711 | + padding: 10rpx 0; | ||
| 712 | +} | ||
| 713 | + | ||
| 714 | +.textarea-label { | ||
| 715 | + font-size: 28rpx; | ||
| 716 | + color: #333; | ||
| 717 | + margin-bottom: 10rpx; | ||
| 718 | + | ||
| 719 | + .required-mark { | ||
| 720 | + color: #f56c6c; | ||
| 721 | + margin-left: 4rpx; | ||
| 722 | + } | ||
| 723 | +} | ||
| 724 | + | ||
| 725 | +.upload-wrap { | ||
| 726 | + margin-top: 20rpx; | ||
| 727 | + | ||
| 728 | + .upload-title { | ||
| 729 | + font-size: 28rpx; | ||
| 730 | + color: #333; | ||
| 731 | + margin-bottom: 10rpx; | ||
| 732 | + } | ||
| 733 | +} | ||
| 734 | + | ||
| 735 | +.mt-20 { | ||
| 736 | + margin-top: 20rpx; | ||
| 737 | +} | ||
| 738 | + | ||
| 739 | +.mt-30 { | ||
| 740 | + margin-top: 30rpx; | ||
| 741 | +} | ||
| 742 | + | ||
| 743 | +// 养护组长验收弹窗样式 | ||
| 744 | +.accept-modal-content { | ||
| 745 | + width: 100%; | ||
| 746 | + box-sizing: border-box; | ||
| 747 | +} | ||
| 748 | + | ||
| 749 | +.radio-group-wrap { | ||
| 750 | + display: flex; | ||
| 751 | + align-items: center; | ||
| 752 | + gap: 40rpx; // 单选框之间的间距 | ||
| 753 | + font-size: 28rpx; | ||
| 754 | + margin-bottom: 20rpx; | ||
| 755 | +} | ||
| 756 | + | ||
| 757 | +.textarea-wrap { | ||
| 758 | + width: 100%; | ||
| 759 | + margin-top: 30rpx; | ||
| 760 | +} | ||
| 14 | 761 | ||
| 762 | +.modal-btn-wrap { | ||
| 763 | + display: flex; | ||
| 764 | + align-items: center; | ||
| 765 | + justify-content: flex-end; | ||
| 766 | + padding-right: 10rpx; | ||
| 767 | +} | ||
| 15 | </style> | 768 | </style> |
| 16 | \ No newline at end of file | 769 | \ No newline at end of file |
pages-sub/problem/regional-order-manage/order-detail.vue
| 1 | -<script lang="ts"> | ||
| 2 | -import {defineComponent} from 'vue' | 1 | +<template> |
| 2 | + <view class="page-container"> | ||
| 3 | + <!-- 页面级加载组件 --> | ||
| 4 | + <up-loading-page | ||
| 5 | + v-if="loading" | ||
| 6 | + :loading="true" | ||
| 7 | + title="加载中..." | ||
| 8 | + color="#3c9cff" | ||
| 9 | + ></up-loading-page> | ||
| 3 | 10 | ||
| 4 | -export default defineComponent({ | ||
| 5 | - name: "order-detail" | ||
| 6 | -}) | ||
| 7 | -</script> | 11 | + <!-- 主内容容器 --> |
| 12 | + <view v-else class="main-content"> | ||
| 13 | + <!-- 顶部固定Tabs --> | ||
| 14 | + <up-sticky :bgColor="'#fff'"> | ||
| 15 | + <up-tabs | ||
| 16 | + v-model="activeTopTab" | ||
| 17 | + :list="topTabList" | ||
| 18 | + :scrollable="false" | ||
| 19 | + sticky | ||
| 20 | + active-color="#3c9cff" | ||
| 21 | + inactive-color="#666" | ||
| 22 | + class="top-tabs" | ||
| 23 | + @click="activeTopTabClick" | ||
| 24 | + ></up-tabs> | ||
| 25 | + </up-sticky> | ||
| 8 | 26 | ||
| 9 | -<template> | 27 | + <!-- 顶部Tab内容区 --> |
| 28 | + <view class="tab-content"> | ||
| 29 | + <!-- 1. 工单详情Tab --> | ||
| 30 | + <view v-show="activeTopTab == 0" class="detail-content"> | ||
| 31 | + <up-cell-group :border="false" class="detail-cell-group"> | ||
| 32 | + <!-- 工单编号 --> | ||
| 33 | + <up-cell title="工单编号" :value="orderDetail.orderNo || '--'" align="middle"></up-cell> | ||
| 34 | + | ||
| 35 | + <!-- 工单位置 --> | ||
| 36 | + <up-cell align="middle"> | ||
| 37 | + <template #title> | ||
| 38 | + <view style="min-width: 200rpx">工单位置</view> | ||
| 39 | + </template> | ||
| 40 | + <template #value> | ||
| 41 | + <view class="common-text-color up-line-1">{{ orderDetail.lonLatAddress || '--' }}</view> | ||
| 42 | + </template> | ||
| 43 | + </up-cell> | ||
| 44 | + | ||
| 45 | + <!-- 工单名称 --> | ||
| 46 | + <up-cell align="middle"> | ||
| 47 | + <template #title> | ||
| 48 | + <view style="min-width: 200rpx">工单名称</view> | ||
| 49 | + </template> | ||
| 50 | + <template #value> | ||
| 51 | + <view class="common-text-color up-line-1">{{ orderDetail.orderName || '--' }}</view> | ||
| 52 | + </template> | ||
| 53 | + </up-cell> | ||
| 54 | + | ||
| 55 | + <!-- 情况描述 --> | ||
| 56 | + <up-cell> | ||
| 57 | + <template #title> | ||
| 58 | + <view style="min-width: 200rpx">情况描述</view> | ||
| 59 | + </template> | ||
| 60 | + <template #value> | ||
| 61 | + <view class="common-text-color up-line-1">{{ orderDetail.remark || '--' }}</view> | ||
| 62 | + </template> | ||
| 63 | + </up-cell> | ||
| 64 | + | ||
| 65 | + <!-- 紧急程度 --> | ||
| 66 | + <up-cell | ||
| 67 | + title="紧急程度" | ||
| 68 | + :value="uni.$dict.getDictLabel('workorder_pressing_type', orderDetail.pressingType) || '--'" | ||
| 69 | + align="middle" | ||
| 70 | + ></up-cell> | ||
| 71 | + | ||
| 72 | + <!-- 提交人 --> | ||
| 73 | + <up-cell title="提交人" :value="orderDetail.userName || '--'" align="middle"></up-cell> | ||
| 74 | + | ||
| 75 | + <!-- 提交时间 --> | ||
| 76 | + <up-cell | ||
| 77 | + title="提交时间" | ||
| 78 | + :value="timeFormat(orderDetail.createTime, 'yyyy-mm-dd hh:MM:ss') || '--'" | ||
| 79 | + align="middle" | ||
| 80 | + ></up-cell> | ||
| 81 | + | ||
| 82 | + <!-- 处理结果 --> | ||
| 83 | + <up-cell v-if="orderDetail.handleResult"> | ||
| 84 | + <template #title> | ||
| 85 | + <view style="min-width: 200rpx">处理结果</view> | ||
| 86 | + </template> | ||
| 87 | + <template #value> | ||
| 88 | + <view class="common-text-color up-line-1">{{ orderDetail.handleResult || '--' }}</view> | ||
| 89 | + </template> | ||
| 90 | + </up-cell> | ||
| 91 | + | ||
| 92 | + <!-- 街道名称 --> | ||
| 93 | + <up-cell title="街道名称" :value="orderDetail.streetName || '--'" align="middle"></up-cell> | ||
| 94 | + | ||
| 95 | + <!-- 问题照片 --> | ||
| 96 | + <up-cell title="问题照片"> | ||
| 97 | + <template #value> | ||
| 98 | + <view class="cell-content-wrap"> | ||
| 99 | + <up-album | ||
| 100 | + v-if="!!orderDetail.problemsImgs?.length" | ||
| 101 | + :urls="orderDetail.problemsImgs.slice(0, 3)" | ||
| 102 | + :singleSize="70" | ||
| 103 | + :multipleSize="70" | ||
| 104 | + | ||
| 105 | + :preview-full-image="true" | ||
| 106 | + ></up-album> | ||
| 107 | + <text v-else class="empty-text">暂无问题照片</text> | ||
| 108 | + </view> | ||
| 109 | + </template> | ||
| 110 | + </up-cell> | ||
| 111 | + | ||
| 112 | + <!-- 希望完成时间 --> | ||
| 113 | + <up-cell | ||
| 114 | + v-if="orderDetail.expectedFinishDate" | ||
| 115 | + title="希望完成时间" | ||
| 116 | + :value="timeFormat(orderDetail.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss')" | ||
| 117 | + align="middle" | ||
| 118 | + :border="false" | ||
| 119 | + ></up-cell> | ||
| 120 | + | ||
| 121 | + <up-cell | ||
| 122 | + v-if="orderDetail.finishDate" | ||
| 123 | + title="工单完结时间" | ||
| 124 | + :value="timeFormat(orderDetail.finishDate, 'yyyy-mm-dd hh:MM:ss')" | ||
| 125 | + align="middle" | ||
| 126 | + :border="false" | ||
| 127 | + ></up-cell> | ||
| 128 | + </up-cell-group> | ||
| 129 | + | ||
| 130 | + <!-- 图片分类Tabs区块 --> | ||
| 131 | + <view class="img-tabs-block" v-if="orderDetail.startImgs.length>0"> | ||
| 132 | + <up-cell-group :border="false"> | ||
| 133 | + <up-cell> | ||
| 134 | + <template #title> | ||
| 135 | + <view style="min-width: 200rpx">共同处理人</view> | ||
| 136 | + </template> | ||
| 137 | + <template #value> | ||
| 138 | + <view class="common-text-color up-line-1"> | ||
| 139 | + {{ | ||
| 140 | + Array.isArray(orderDetail.coHandlersName) && orderDetail.coHandlersName.length > 0 ? orderDetail.coHandlersName.join(',') : '--' | ||
| 141 | + }} | ||
| 142 | + </view> | ||
| 143 | + </template> | ||
| 144 | + </up-cell> | ||
| 145 | + </up-cell-group> | ||
| 146 | + <up-tabs | ||
| 147 | + @change='imgTabChange' | ||
| 148 | + v-model="activeImgTab" | ||
| 149 | + :list="imgTabList" | ||
| 150 | + :scrollable="false" | ||
| 151 | + active-color="#3c9cff" | ||
| 152 | + inactive-color="#666" | ||
| 153 | + class="img-tabs" | ||
| 154 | + ></up-tabs> | ||
| 155 | + | ||
| 156 | + <!-- 图片Tab内容区 --> | ||
| 157 | + <view class="img-tab-content"> | ||
| 158 | + <up-album | ||
| 159 | + v-if="currentImgList.length" | ||
| 160 | + :urls="currentImgList.slice(0, 3)" | ||
| 161 | + :singleSize="70" | ||
| 162 | + :multipleSize="70" | ||
| 163 | + :preview-full-image="true" | ||
| 164 | + class="img-album custom-album" | ||
| 165 | + ></up-album> | ||
| 166 | + <text v-else class="empty-img-text">养护员未上传图片</text> | ||
| 167 | + </view> | ||
| 168 | + </view> | ||
| 169 | + </view> | ||
| 170 | + | ||
| 171 | + <!-- 2. 流程节点Tab --> | ||
| 172 | + <view v-show="activeTopTab == 1" class="process-content"> | ||
| 173 | + <!-- 竖向步骤条:动态绑定current属性 --> | ||
| 174 | + <up-steps | ||
| 175 | + v-if="processData.activityNodes && processData.activityNodes.length" | ||
| 176 | + :list="processData.activityNodes" | ||
| 177 | + :current="getCurrentStepIndex()" | ||
| 178 | + direction="column" | ||
| 179 | + active-color="#3c9cff" | ||
| 180 | + inactive-color="#999" | ||
| 181 | + class="vertical-steps" | ||
| 182 | + > | ||
| 183 | + <template> | ||
| 184 | + <up-steps-item | ||
| 185 | + v-for="(item, index) in processData.activityNodes" | ||
| 186 | + :key="`${item.id}_${index}`" | ||
| 187 | + > | ||
| 188 | + <!-- 唯一自定义模板:content,包含标题、描述、相册所有内容 --> | ||
| 189 | + <template #content> | ||
| 190 | + <view class="step-content-wrap"> | ||
| 191 | + <!-- 1. 原标题内容:节点名称 + 操作人 --> | ||
| 192 | + <view class="step-title"> | ||
| 193 | + {{ item.name }} | ||
| 194 | + <text class="operator-name"> | ||
| 195 | + {{ | ||
| 196 | + item.tasks && item.tasks[0]?.assigneeUser?.nickname ? '(' + item.tasks[0].assigneeUser.nickname + ')' : '(未知操作人)' | ||
| 197 | + }} | ||
| 198 | + </text> | ||
| 199 | + </view> | ||
| 200 | + | ||
| 201 | + <!-- 2. 原描述内容:时间 + 处理说明(最多200字) --> | ||
| 202 | + <view class="step-desc"> | ||
| 203 | + <!-- 时间行 --> | ||
| 204 | + <view class="time-line"> | ||
| 205 | + 处理时间:{{ timeFormat(item.startTime, 'yyyy-mm-dd hh:MM:ss') }} | ||
| 206 | + <text v-if="item.endTime"> 至 {{ timeFormat(item.endTime, 'yyyy-mm-dd hh:MM:ss') }}</text> | ||
| 207 | + <text v-else class="processing-tag">(处理中)</text> | ||
| 208 | + </view> | ||
| 209 | + | ||
| 210 | + <view class="reason-line up-line-1" v-if="index!==0&&item.endTime"> | ||
| 211 | + 总耗时:{{ calculateFormatTimeDiff(item.startTime, item.endTime) }} | ||
| 212 | + </view> | ||
| 213 | + | ||
| 214 | + <!-- 原因行 --> | ||
| 215 | + <view class="reason-line up-line-2" v-if="item.tasks && item.tasks[0]?.reason"> | ||
| 216 | + 描述:{{ getLimitReason(item.tasks && item.tasks[0]?.reason) }} | ||
| 217 | + </view> | ||
| 218 | + </view> | ||
| 219 | + | ||
| 220 | + <!-- 3. 原相册内容:预留up-album --> | ||
| 221 | + <view class="step-album-wrap"> | ||
| 222 | + <up-album | ||
| 223 | + v-if="item.tasks && item.tasks[0]?.attattmentUrls && item.tasks[0].attattmentUrls.length" | ||
| 224 | + :urls="item.tasks[0].attattmentUrls.slice(0, 3)" | ||
| 225 | + :singleSize="70" | ||
| 226 | + :multipleSize="70" | ||
| 227 | + | ||
| 228 | + :preview-full-image="true" | ||
| 229 | + class="step-album" | ||
| 230 | + ></up-album> | ||
| 231 | + </view> | ||
| 232 | + </view> | ||
| 233 | + </template> | ||
| 234 | + </up-steps-item> | ||
| 235 | + </template> | ||
| 236 | + | ||
| 237 | + </up-steps> | ||
| 238 | + | ||
| 239 | + <!-- 流程节点为空时的提示 --> | ||
| 240 | + <up-empty | ||
| 241 | + v-else | ||
| 242 | + mode="data" | ||
| 243 | + title="暂无流程节点数据" | ||
| 244 | + class="empty-process" | ||
| 245 | + ></up-empty> | ||
| 246 | + </view> | ||
| 247 | + </view> | ||
| 248 | + </view> | ||
| 249 | + | ||
| 250 | + <!-- activeTab==0的时候才出现, 也就是待办 --> | ||
| 251 | + <view v-if="activeTab==0&&nextStepMap[orderDetail.taskKey]" class="fixed-bottom-btn-wrap"> | ||
| 252 | + <view class="u-body-item u-flex common-justify-between common-item-center "> | ||
| 253 | + <up-button type="warning" size="normal" @click="handleReject(orderDetail)" | ||
| 254 | + v-show="nextStepMap[orderDetail.taskKey].backShow">回退 | ||
| 255 | + </up-button> | ||
| 256 | + | ||
| 257 | + <up-button type="success" size="normal" @click="handleRenew(orderDetail)" | ||
| 258 | + v-show="nextStepMap[orderDetail.taskKey].renewShow">重新提交 | ||
| 259 | + </up-button> | ||
| 10 | 260 | ||
| 261 | + <up-button type="primary" size="normal" @click="handleProcess(orderDetail)">{{ | ||
| 262 | + nextStepMap[orderDetail.taskKey].btnText | ||
| 263 | + }} | ||
| 264 | + </up-button> | ||
| 265 | + | ||
| 266 | + </view> | ||
| 267 | + </view> | ||
| 268 | + | ||
| 269 | + <!-- 回退原因弹窗(新增图片上传) --> | ||
| 270 | + <up-modal | ||
| 271 | + :show="rejectModalShow" | ||
| 272 | + title="回退原因" | ||
| 273 | + :closeOnClickOverlay="false" | ||
| 274 | + :showConfirmButton="true" | ||
| 275 | + :showCancelButton="true" | ||
| 276 | + @cancel="handleRejectModalCancel" | ||
| 277 | + @confirm="confirmReject" | ||
| 278 | + > | ||
| 279 | + <view class="reject-modal-content"> | ||
| 280 | + <up-textarea | ||
| 281 | + v-model.trim="rejectReason" | ||
| 282 | + placeholder="请输入回退原因(必填)" | ||
| 283 | + rows="6" | ||
| 284 | + :count="200" | ||
| 285 | + maxlength="200" | ||
| 286 | + class="reject-textarea" | ||
| 287 | + /> | ||
| 288 | + <!-- 新增:回退图片上传(选填) --> | ||
| 289 | + <view class="upload-wrap mt-20"> | ||
| 290 | + <view class="upload-title">上传回退图片(选填)</view> | ||
| 291 | + <up-upload | ||
| 292 | + :file-list="rejectImgs.rawImgList.value || []" | ||
| 293 | + @after-read="rejectImgs.uploadImgs" | ||
| 294 | + @delete="rejectImgs.deleteImg" | ||
| 295 | + multiple | ||
| 296 | + width="70" | ||
| 297 | + height="70" | ||
| 298 | + :max-count="rejectImgs.uploadConfig.maxCount" | ||
| 299 | + :upload-text="rejectImgs.uploadConfig.uploadText" | ||
| 300 | + :size-type="rejectImgs.uploadConfig.sizeType" | ||
| 301 | + /> | ||
| 302 | + </view> | ||
| 303 | + </view> | ||
| 304 | + </up-modal> | ||
| 305 | + | ||
| 306 | + <!-- 验收弹窗(新增图片上传) --> | ||
| 307 | + <up-modal | ||
| 308 | + :show="acceptModalShow" | ||
| 309 | + title="验收" | ||
| 310 | + :closeOnClickOverlay="false" | ||
| 311 | + :showConfirmButton="true" | ||
| 312 | + :showCancelButton="true" | ||
| 313 | + @cancel="handleAcceptModalCancel" | ||
| 314 | + @confirm="handleAcceptModalConfirm" | ||
| 315 | + > | ||
| 316 | + <view class="accept-modal-content"> | ||
| 317 | + <!-- 第一行:单选框(通过/不通过,默认通过) --> | ||
| 318 | + <view class="radio-group-wrap"> | ||
| 319 | + <up-radio-group v-model="acceptRadioValue"> | ||
| 320 | + <up-radio name="0" label="通过"></up-radio> | ||
| 321 | + <up-radio name="1" label="不通过"></up-radio> | ||
| 322 | + </up-radio-group> | ||
| 323 | + </view> | ||
| 324 | + | ||
| 325 | + <!-- 第二行:必填textarea,最多200字 --> | ||
| 326 | + <view class="textarea-wrap mt-30"> | ||
| 327 | + <up-textarea | ||
| 328 | + v-model.trim="acceptReason" | ||
| 329 | + placeholder="请输入验收原因(必填,最多200字)" | ||
| 330 | + :required="true" | ||
| 331 | + maxlength="200" | ||
| 332 | + rows="5" | ||
| 333 | + count | ||
| 334 | + /> | ||
| 335 | + </view> | ||
| 336 | + | ||
| 337 | + <!-- 新增:验收图片上传(选填) --> | ||
| 338 | + <view class="upload-wrap mt-20"> | ||
| 339 | + <view class="upload-title">上传验收图片(选填)</view> | ||
| 340 | + <up-upload | ||
| 341 | + :file-list="acceptImgs.rawImgList.value || []" | ||
| 342 | + @after-read="acceptImgs.uploadImgs" | ||
| 343 | + @delete="acceptImgs.deleteImg" | ||
| 344 | + multiple | ||
| 345 | + width="70" | ||
| 346 | + height="70" | ||
| 347 | + :max-count="acceptImgs.uploadConfig.maxCount" | ||
| 348 | + :upload-text="acceptImgs.uploadConfig.uploadText" | ||
| 349 | + :size-type="acceptImgs.uploadConfig.sizeType" | ||
| 350 | + /> | ||
| 351 | + </view> | ||
| 352 | + </view> | ||
| 353 | + </up-modal> | ||
| 354 | + | ||
| 355 | + </view> | ||
| 11 | </template> | 356 | </template> |
| 12 | 357 | ||
| 358 | +<script setup lang="ts"> | ||
| 359 | +import {ref, watch} from 'vue'; | ||
| 360 | +import {onLoad, onShow} from '@dcloudio/uni-app'; | ||
| 361 | +import {timeFormat} from '@/uni_modules/uview-plus'; | ||
| 362 | +import { | ||
| 363 | + getMyTaskDetail, | ||
| 364 | + getDoneTaskDetail, | ||
| 365 | + getTodoTaskDetail, | ||
| 366 | + getApprovalDetail, | ||
| 367 | + universalApproval | ||
| 368 | +} from '@/api/work-order-manage/work-order-manage'; | ||
| 369 | +import {nextStepMap, buzStatusMap, calculateFormatTimeDiff} from '@/common/utils/common' | ||
| 370 | +// 引入图片上传组合式函数 | ||
| 371 | +import {useUploadImgs} from '@/common/utils/useUploadImgs' | ||
| 372 | + | ||
| 373 | +// 状态管理 | ||
| 374 | +const loading = ref(true); | ||
| 375 | +const activeTopTab = ref(0); // 顶部Tab激活索引 | ||
| 376 | +const activeImgTab = ref(0); // 图片分类Tab激活索引 | ||
| 377 | + | ||
| 378 | +// 顶部Tab列表 | ||
| 379 | +const topTabList = ref([ | ||
| 380 | + {name: '工单详情'}, | ||
| 381 | + {name: '流程节点'} | ||
| 382 | +]); | ||
| 383 | + | ||
| 384 | +// 流程节点数据(初始化适配接口格式) | ||
| 385 | +const processData = ref<any>({ | ||
| 386 | + status: 2, | ||
| 387 | + activityNodes: [], | ||
| 388 | + formFieldsPermission: null, | ||
| 389 | + todoTask: null | ||
| 390 | +}); | ||
| 391 | + | ||
| 392 | +// 图片分类Tab列表(带角标配置) | ||
| 393 | +const imgTabList = ref([ | ||
| 394 | + {name: '开始', badge: {isDot: true}}, | ||
| 395 | + {name: '进行中'}, | ||
| 396 | + {name: '结束', badge: {isDot: true}}, | ||
| 397 | + {name: '人员'}, | ||
| 398 | + {name: '材料'} | ||
| 399 | +]); | ||
| 400 | + | ||
| 401 | +// 工单详情数据(初始化赋值,可被接口数据覆盖) | ||
| 402 | +const orderDetail = ref<any>({ | ||
| 403 | + id: 0, | ||
| 404 | + busiLine: '', | ||
| 405 | + orderNo: '', | ||
| 406 | + orderName: '', | ||
| 407 | + sourceId: 0, | ||
| 408 | + sourceName: '', | ||
| 409 | + roadId: 0, | ||
| 410 | + roadName: '', | ||
| 411 | + streetId: '', | ||
| 412 | + streetName: '', | ||
| 413 | + curingLevelId: 0, | ||
| 414 | + curingLevelName: '', | ||
| 415 | + commitDate: 0, | ||
| 416 | + finishDate: 0, | ||
| 417 | + expectedFinishDate: 0, | ||
| 418 | + pressingType: 0, | ||
| 419 | + userId: 0, | ||
| 420 | + userName: '', | ||
| 421 | + companyId: 0, | ||
| 422 | + latLonType: 0, | ||
| 423 | + lat: 0, | ||
| 424 | + lon: 0, | ||
| 425 | + lonLatAddress: '', | ||
| 426 | + thirdWorkNo: '', | ||
| 427 | + thirdPushState: 0, | ||
| 428 | + buzStatus: null, | ||
| 429 | + status: 0, | ||
| 430 | + processInstanceId: '', | ||
| 431 | + remark: '', | ||
| 432 | + handleResult: '', | ||
| 433 | + createTime: 0, | ||
| 434 | + fileNames: null, | ||
| 435 | + coHandlers: null, | ||
| 436 | + coHandlersName: null, | ||
| 437 | + companyName: null, | ||
| 438 | + userMobile: null, | ||
| 439 | + taskId: '', | ||
| 440 | + taskName: '', | ||
| 441 | + taskKey: '', | ||
| 442 | + processDefinitionName: '', | ||
| 443 | + startTime: 0, | ||
| 444 | + endTime: 0, | ||
| 445 | + key_: '', | ||
| 446 | + problemsImgs: [], | ||
| 447 | + startImgs: [], | ||
| 448 | + processingImgs: [], | ||
| 449 | + endImgs: [], | ||
| 450 | + personImgs: [], | ||
| 451 | + materialImgs: [] | ||
| 452 | +}); | ||
| 453 | + | ||
| 454 | +/** | ||
| 455 | + * 当前激活的图片列表(无需函数调用,直接访问) | ||
| 456 | + */ | ||
| 457 | +const currentImgList = ref([]) | ||
| 458 | + | ||
| 459 | +const tabKeyMap = ['startImgs', 'processingImgs', 'endImgs', 'personImgs', 'materialImgs']; | ||
| 460 | +const imgTabChange = (({index}: { index: number }) => { | ||
| 461 | + console.log(index) | ||
| 462 | + const currentKey = tabKeyMap[index] | ||
| 463 | + console.log(currentKey) | ||
| 464 | + console.log(orderDetail.value[currentKey]) | ||
| 465 | + currentImgList.value = orderDetail.value[currentKey] | ||
| 466 | +}) | ||
| 467 | + | ||
| 468 | +/** | ||
| 469 | + * 截取reason最多200字 | ||
| 470 | + * @param reason 处理说明 | ||
| 471 | + * @returns 截取后的字符串 | ||
| 472 | + */ | ||
| 473 | +const getLimitReason = (reason: string | null | undefined) => { | ||
| 474 | + if (!reason) return '无处理说明'; | ||
| 475 | + if (reason.length <= 200) return reason; | ||
| 476 | + return reason.substring(0, 200) + '...'; | ||
| 477 | +} | ||
| 478 | + | ||
| 479 | +/** | ||
| 480 | + * 动态获取当前步骤索引(核心:根据接口数据的status字段判断) | ||
| 481 | + * status=1:当前步骤(处理中) | ||
| 482 | + * status=2:已完成步骤 | ||
| 483 | + * @returns {number} 当前激活的步骤索引(从0开始) | ||
| 484 | + */ | ||
| 485 | +const getCurrentStepIndex = () => { | ||
| 486 | + const {activityNodes} = processData.value; | ||
| 487 | + if (!activityNodes || !activityNodes.length) return 0; | ||
| 488 | + | ||
| 489 | + // 2. 若没有处理中的节点(全部已完成),则激活最后一个节点 | ||
| 490 | + return activityNodes.length - 1; | ||
| 491 | +} | ||
| 492 | + | ||
| 493 | +/** | ||
| 494 | + * 获取工单详情 | ||
| 495 | + */ | ||
| 496 | +const DetailQuery = async (taskIdStr: string) => { | ||
| 497 | + console.log('当前工单ID:', taskIdStr) | ||
| 498 | + try { | ||
| 499 | + loading.value = true; | ||
| 500 | + // 转换activeTab为数字类型,避免类型不一致导致接口调用失败 | ||
| 501 | + const tabType = Number(activeTab.value); | ||
| 502 | + let res: any; | ||
| 503 | + | ||
| 504 | + if (tabType === 0) { | ||
| 505 | + res = await getTodoTaskDetail({taskId: taskIdStr}); | ||
| 506 | + } else if (tabType === 1) { | ||
| 507 | + res = await getMyTaskDetail({taskId: taskIdStr}); | ||
| 508 | + } else if (tabType === 2) { | ||
| 509 | + res = await getDoneTaskDetail({taskId: taskIdStr}); | ||
| 510 | + } else { | ||
| 511 | + uni.showToast({title: '无效的工单类型', icon: 'none'}); | ||
| 512 | + return; | ||
| 513 | + } | ||
| 514 | + | ||
| 515 | + // 覆盖工单详情数据 | ||
| 516 | + if (res) { | ||
| 517 | + orderDetail.value = res; | ||
| 518 | + currentImgList.value = orderDetail.value.startImgs | ||
| 519 | + } | ||
| 520 | + } catch (error) { | ||
| 521 | + console.error('获取工单详情失败:', error); | ||
| 522 | + uni.showToast({title: '加载失败,请重试', icon: 'none'}); | ||
| 523 | + } finally { | ||
| 524 | + loading.value = false; | ||
| 525 | + } | ||
| 526 | +}; | ||
| 527 | + | ||
| 528 | +// 页面加载参数 | ||
| 529 | +const taskId = ref('') | ||
| 530 | +const activeTab = ref('') | ||
| 531 | +const processInstanceId = ref('') | ||
| 532 | + | ||
| 533 | +const activeTopTabClick = async (item: any) => { | ||
| 534 | + console.log(item) | ||
| 535 | + activeTopTab.value = item.index | ||
| 536 | + if (activeTopTab.value == 1) { | ||
| 537 | + let getData = { | ||
| 538 | + processInstanceId: processInstanceId.value, | ||
| 539 | + } | ||
| 540 | + const res = await getApprovalDetail(getData) | ||
| 541 | + console.log(res) | ||
| 542 | + // 关键:格式化数据,补充up-steps要求的title字段 | ||
| 543 | + if (res && res.activityNodes && res.activityNodes.length) { | ||
| 544 | + // 1. 先过滤:剔除 name 为 "结束" 的节点 | ||
| 545 | + const filteredActivityNodes = res.activityNodes.filter(node => { | ||
| 546 | + // 返回 true 保留节点,返回 false 剔除节点 | ||
| 547 | + return node.name !== '结束'; | ||
| 548 | + }); | ||
| 549 | + const formatActivityNodes = filteredActivityNodes.map(node => ({ | ||
| 550 | + ...node, | ||
| 551 | + title: node.name // 补充强制字段,满足3.3.48版本组件要求 | ||
| 552 | + })); | ||
| 553 | + processData.value = { | ||
| 554 | + ...res, | ||
| 555 | + activityNodes: formatActivityNodes | ||
| 556 | + }; | ||
| 557 | + } else { | ||
| 558 | + processData.value = res; | ||
| 559 | + } | ||
| 560 | + } | ||
| 561 | +} | ||
| 562 | + | ||
| 563 | +// ========== 回退弹窗相关状态(新增图片上传实例) ========== | ||
| 564 | +const rejectModalShow = ref(false); // 回退modal显示开关 | ||
| 565 | +const rejectReason = ref(''); // 回退原因 | ||
| 566 | +const currentRejectItem = ref<any>(null); // 当前回退工单 | ||
| 567 | +// 回退图片上传配置 | ||
| 568 | +const rejectImgs = useUploadImgs({ | ||
| 569 | + maxCount: 3, | ||
| 570 | + uploadText: '选择回退图片', | ||
| 571 | + sizeType: ['compressed'], | ||
| 572 | + formRef: null, | ||
| 573 | + fieldName: 'rejectImgs' | ||
| 574 | +}) | ||
| 575 | + | ||
| 576 | + | ||
| 577 | +// ========== 验收弹窗相关状态(新增图片上传实例) ========== | ||
| 578 | +const acceptModalShow = ref(false); // 验收弹窗显示开关 | ||
| 579 | +const acceptRadioValue = ref('0'); // 单选框值,默认0(通过) | ||
| 580 | +const acceptReason = ref(''); // 验收原因 | ||
| 581 | +const currentAcceptItem = ref<any>(null); // 当前验收的工单项 | ||
| 582 | +// 验收图片上传配置 | ||
| 583 | +const acceptImgs = useUploadImgs({ | ||
| 584 | + maxCount: 3, | ||
| 585 | + uploadText: '选择验收图片', | ||
| 586 | + sizeType: ['compressed'], | ||
| 587 | + formRef: null, | ||
| 588 | + fieldName: 'acceptImgs' | ||
| 589 | +}) | ||
| 590 | + | ||
| 591 | + | ||
| 592 | +// ========== 生成临时key ========== | ||
| 593 | +const generateTempKey = () => { | ||
| 594 | + return 'renew_order_' + Date.now() + '_' + Math.floor(Math.random() * 10000); | ||
| 595 | +}; | ||
| 596 | + | ||
| 597 | +// ========== handleRenew 重新提交工单 ========== | ||
| 598 | +const handleRenew = (item: any) => { | ||
| 599 | + // 校验工单有效性 | ||
| 600 | + if (!item || !item.id) { | ||
| 601 | + uni.showToast({title: '工单信息异常,无法重新提交', icon: 'none'}); | ||
| 602 | + return; | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + // 1. 生成唯一临时标识 | ||
| 606 | + const tempKey = generateTempKey(); | ||
| 607 | + | ||
| 608 | + // 2. 将完整工单数据存入本地临时存储(同步存储,确保数据立即生效) | ||
| 609 | + try { | ||
| 610 | + uni.setStorageSync(tempKey, item); | ||
| 611 | + } catch (error) { | ||
| 612 | + console.error('存储工单数据失败:', error); | ||
| 613 | + uni.showToast({title: '数据存储异常,无法重新提交', icon: 'none'}); | ||
| 614 | + return; | ||
| 615 | + } | ||
| 616 | + | ||
| 617 | + // 3. URL 仅传递「唯一标识」和「重新提交标记」 | ||
| 618 | + uni.navigateTo({ | ||
| 619 | + url: `/pages-sub/problem/work-order-manage/add-order?isRenew=1&tempKey=${tempKey}` | ||
| 620 | + }); | ||
| 621 | +}; | ||
| 622 | + | ||
| 623 | +// ========== handleReject 打开回退弹窗 ========== | ||
| 624 | +const handleReject = (item: any) => { | ||
| 625 | + // 校验工单有效性 | ||
| 626 | + if (!item || !item.id) { | ||
| 627 | + uni.showToast({title: '工单信息异常,无法回退', icon: 'none'}); | ||
| 628 | + return; | ||
| 629 | + } | ||
| 630 | + currentRejectItem.value = item; | ||
| 631 | + rejectReason.value = ''; // 清空上次输入 | ||
| 632 | + rejectImgs.clearImgs(); // 清空上传图片 | ||
| 633 | + rejectModalShow.value = true; // 显示回退modal | ||
| 634 | +}; | ||
| 635 | + | ||
| 636 | +// ========== 回退弹窗取消按钮 ========== | ||
| 637 | +const handleRejectModalCancel = () => { | ||
| 638 | + rejectModalShow.value = false; | ||
| 639 | + rejectReason.value = ''; | ||
| 640 | + rejectImgs.clearImgs(); // 清空上传图片 | ||
| 641 | +}; | ||
| 642 | + | ||
| 643 | +// ========== 确认回退工单(新增returnImgs传参) ========== | ||
| 644 | +const confirmReject = async () => { | ||
| 645 | + // 严格校验回退原因(去除首尾空格) | ||
| 646 | + const rejectReasonTrim = rejectReason.value.trim(); | ||
| 647 | + if (!rejectReasonTrim) { | ||
| 648 | + uni.showToast({title: '请填写回退原因', icon: 'none', duration: 1000}); | ||
| 649 | + return; | ||
| 650 | + } | ||
| 651 | + // 校验当前工单有效性 | ||
| 652 | + if (!currentRejectItem.value || !currentRejectItem.value.id) { | ||
| 653 | + uni.showToast({title: '工单信息异常,无法提交', icon: 'none', duration: 1000}); | ||
| 654 | + rejectModalShow.value = false; | ||
| 655 | + return; | ||
| 656 | + } | ||
| 657 | + try { | ||
| 658 | + // 显示加载中,防止重复提交 | ||
| 659 | + uni.showLoading({title: '提交中...', mask: true}); | ||
| 660 | + | ||
| 661 | + // 构建请求参数(新增returnImgs) | ||
| 662 | + const requestData = { | ||
| 663 | + "returnImgs": rejectImgs.getSuccessImgUrls(), // 回退图片URL数组 | ||
| 664 | + "workerDataId": currentRejectItem.value.id, | ||
| 665 | + "taskKey": currentRejectItem.value.taskKey, | ||
| 666 | + "taskId": currentRejectItem.value.taskId, | ||
| 667 | + "operateType": nextStepMap[currentRejectItem.value.taskKey].operateTypeNoPass, | ||
| 668 | + "agree": 1, | ||
| 669 | + "reason": rejectReasonTrim | ||
| 670 | + }; | ||
| 671 | + // 调用回退工单接口 | ||
| 672 | + const res = await universalApproval(requestData); | ||
| 673 | + uni.showToast({title: '回退成功', icon: 'success', duration: 1000}); | ||
| 674 | + | ||
| 675 | + rejectModalShow.value = false; | ||
| 676 | + // 重新获取工单详情,刷新页面 | ||
| 677 | + // await DetailQuery(taskId.value); | ||
| 678 | + uni.reLaunch({ | ||
| 679 | + url: `/pages-sub/problem/work-order-manage/index` | ||
| 680 | + }); | ||
| 681 | + } catch (error) { | ||
| 682 | + console.error('回退工单失败:', error); | ||
| 683 | + uni.showToast({title: '网络异常,回退失败', icon: 'none', duration: 1000}); | ||
| 684 | + } finally { | ||
| 685 | + // 隐藏加载中 | ||
| 686 | + uni.hideLoading(); | ||
| 687 | + } | ||
| 688 | +}; | ||
| 689 | + | ||
| 690 | +// ========== handleProcess 处理工单 ========== | ||
| 691 | +const handleProcess = async (item: any) => { | ||
| 692 | + console.log(nextStepMap[item.taskKey]?.name) | ||
| 693 | + try { | ||
| 694 | + if (nextStepMap[item.taskKey]?.name == '养护组长分配') { | ||
| 695 | + uni.navigateTo({ | ||
| 696 | + url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}&id=${item.id}` | ||
| 697 | + }) | ||
| 698 | + } | ||
| 699 | + if (nextStepMap[item.taskKey]?.name == '养护员待实施') { | ||
| 700 | + // ① 生成唯一临时key | ||
| 701 | + const tempKey = `maintain_order_${Date.now()}_${Math.floor(Math.random() * 10000)}`; | ||
| 702 | + | ||
| 703 | + // ② 存储完整item到本地缓存 | ||
| 704 | + try { | ||
| 705 | + uni.setStorageSync(tempKey, item); | ||
| 706 | + } catch (error) { | ||
| 707 | + console.error('存储养护工单数据失败:', error); | ||
| 708 | + uni.showToast({title: '数据存储异常,无法跳转', icon: 'none'}); | ||
| 709 | + return; | ||
| 710 | + } | ||
| 711 | + | ||
| 712 | + // ③ URL仅传递临时key | ||
| 713 | + uni.navigateTo({ | ||
| 714 | + url: `/pages-sub/problem/work-order-manage/add-maintain-order?tempKey=${tempKey}` | ||
| 715 | + }) | ||
| 716 | + } | ||
| 717 | + // 养护组长验收 - 打开弹窗 | ||
| 718 | + if (nextStepMap[item.taskKey]?.name == '养护组长验收') { | ||
| 719 | + currentAcceptItem.value = item; // 存储当前工单信息 | ||
| 720 | + acceptReason.value = ''; // 清空上次的验收原因 | ||
| 721 | + acceptRadioValue.value = '0'; // 重置默认选中“通过” | ||
| 722 | + acceptImgs.clearImgs(); // 清空验收图片 | ||
| 723 | + acceptModalShow.value = true; // 显示验收弹窗 | ||
| 724 | + } | ||
| 725 | + // 巡查员验收 - 打开弹窗 | ||
| 726 | + if (nextStepMap[item.taskKey]?.name == '巡查员验收') { | ||
| 727 | + currentAcceptItem.value = item; // 存储当前工单信息 | ||
| 728 | + acceptReason.value = ''; // 清空上次的验收原因 | ||
| 729 | + acceptRadioValue.value = '0'; // 重置默认选中“通过” | ||
| 730 | + acceptImgs.clearImgs(); // 清空验收图片 | ||
| 731 | + acceptModalShow.value = true; // 显示验收弹窗 | ||
| 732 | + } | ||
| 733 | + | ||
| 734 | + // 发起人确认 | ||
| 735 | + if (nextStepMap[item.taskKey]?.name == '发起人确认') { | ||
| 736 | + console.log(item) | ||
| 737 | + uni.showModal({ | ||
| 738 | + title: "结束工单", | ||
| 739 | + content: "请确定是否结束工单?", | ||
| 740 | + success: async function (res) { | ||
| 741 | + if (res.confirm) { | ||
| 742 | + // 构建请求参数(携带returnImgs) | ||
| 743 | + const requestData = { | ||
| 744 | + "returnImgs": rejectImgs.getSuccessImgUrls(), | ||
| 745 | + "workerDataId": item.id, | ||
| 746 | + "taskKey": 'ylInspectorStart', | ||
| 747 | + "taskId": item.taskId, | ||
| 748 | + "operateType": 200, | ||
| 749 | + "agree": 1, | ||
| 750 | + "reason": '结束工单' | ||
| 751 | + }; | ||
| 752 | + // 调用回退工单接口 | ||
| 753 | + const res = await universalApproval(requestData); | ||
| 754 | + uni.showToast({title: '结束成功', icon: 'success', duration: 1000}); | ||
| 755 | + // 重新获取工单详情,刷新页面 | ||
| 756 | + await DetailQuery(taskId.value); | ||
| 757 | + } else if (res.cancel) { | ||
| 758 | + console.log("用户点击取消"); | ||
| 759 | + } | ||
| 760 | + }, | ||
| 761 | + }); | ||
| 762 | + } | ||
| 763 | + } catch (error) { | ||
| 764 | + console.error('处理工单失败:', error); | ||
| 765 | + uni.showToast({title: '处理失败,请重试', icon: 'none'}); | ||
| 766 | + } | ||
| 767 | +}; | ||
| 768 | + | ||
| 769 | +// ========== 验收弹窗取消按钮(新增清空图片) ========== | ||
| 770 | +const handleAcceptModalCancel = () => { | ||
| 771 | + acceptModalShow.value = false; | ||
| 772 | + acceptReason.value = ''; | ||
| 773 | + acceptRadioValue.value = '0'; | ||
| 774 | + acceptImgs.clearImgs(); // 清空验收图片 | ||
| 775 | +}; | ||
| 776 | + | ||
| 777 | +// ========== 验收弹窗确认按钮(新增returnImgs传参) ========== | ||
| 778 | +const handleAcceptModalConfirm = async () => { | ||
| 779 | + // 1. 校验验收原因是否为空 | ||
| 780 | + if (!acceptReason.value.trim()) { | ||
| 781 | + uni.showToast({title: '请填写验收原因', icon: 'none', duration: 1000}); | ||
| 782 | + return; | ||
| 783 | + } | ||
| 784 | + // 2. 校验验收原因长度 | ||
| 785 | + if (acceptReason.value.length > 200) { | ||
| 786 | + uni.showToast({title: '验收原因最多200字', icon: 'none', duration: 1000}); | ||
| 787 | + return; | ||
| 788 | + } | ||
| 789 | + try { | ||
| 790 | + // 3. 调用验收接口 | ||
| 791 | + console.log(currentAcceptItem.value) | ||
| 792 | + let postData: any = {} | ||
| 793 | + if (currentAcceptItem.value?.taskKey == 'ylTeamLeaderConfirm') { // 养护组长验收 | ||
| 794 | + postData = { | ||
| 795 | + "returnImgs": acceptImgs.getSuccessImgUrls(), // 验收图片URL数组 | ||
| 796 | + "taskKey": currentAcceptItem.value.taskKey, // ylTeamLeaderConfirm | ||
| 797 | + "workerDataId": currentAcceptItem.value.id, | ||
| 798 | + "taskId": currentAcceptItem.value.taskId, | ||
| 799 | + "operateType": acceptRadioValue.value == 0 ? nextStepMap[currentAcceptItem.value.taskKey].operateTypePass : nextStepMap[currentAcceptItem.value.taskKey].operateTypeNoPass, | ||
| 800 | + "reason": acceptReason.value.trim() | ||
| 801 | + } | ||
| 802 | + } | ||
| 803 | + if (currentAcceptItem.value?.taskKey == 'ylInspector') { // 巡查员验收 | ||
| 804 | + postData = { | ||
| 805 | + "returnImgs": acceptImgs.getSuccessImgUrls(), // 验收图片URL数组 | ||
| 806 | + "taskKey": currentAcceptItem.value.taskKey, //ylInspector | ||
| 807 | + "taskId": currentAcceptItem.value.taskId, | ||
| 808 | + "workerDataId": currentAcceptItem.value.id, | ||
| 809 | + "operateType": acceptRadioValue.value == 0 ? nextStepMap[currentAcceptItem.value.taskKey].operateTypePass : nextStepMap[currentAcceptItem.value.taskKey].operateTypeNoPass, | ||
| 810 | + "reason": acceptReason.value.trim(), | ||
| 811 | + "agree": acceptRadioValue.value | ||
| 812 | + } | ||
| 813 | + } | ||
| 814 | + const acceptRes = await universalApproval(postData); | ||
| 815 | + // 4. 操作成功处理 | ||
| 816 | + | ||
| 817 | + handleAcceptModalCancel(); // 清空状态 | ||
| 818 | + // 重新获取工单详情,刷新页面 | ||
| 819 | + // await DetailQuery(taskId.value); | ||
| 820 | + // uni.reLaunch({ | ||
| 821 | + // url: `/pages-sub/problem/work-order-manage/index` | ||
| 822 | + // }); | ||
| 823 | + eventChannel.emit('needRefresh'); | ||
| 824 | + // 4. 返回列表页 | ||
| 825 | + uni.navigateBack({delta: 1}); | ||
| 826 | + uni.showToast({title: '提交成功', icon: 'success', duration: 1000}); | ||
| 827 | + } catch (error) { | ||
| 828 | + // 5. 操作失败处理 | ||
| 829 | + console.error('验收失败:', error); | ||
| 830 | + uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 1000}); | ||
| 831 | + } | ||
| 832 | +}; | ||
| 833 | + | ||
| 834 | +onLoad((options: any) => { | ||
| 835 | + console.log('页面入参:', options) | ||
| 836 | + const {taskId: taskIdOpt, activeTab: activeTabOpt, processInstanceId: processInstanceIdOpt} = options; | ||
| 837 | + // 0-待办 1-我发起的 2-已办 | ||
| 838 | + taskId.value = taskIdOpt || ''; | ||
| 839 | + activeTab.value = activeTabOpt || '0'; | ||
| 840 | + processInstanceId.value = processInstanceIdOpt; | ||
| 841 | + DetailQuery(taskId.value); | ||
| 842 | +}); | ||
| 843 | + | ||
| 844 | +onShow(() => { | ||
| 845 | + // 注释原有逻辑,避免重复加载 | ||
| 846 | +}); | ||
| 847 | +</script> | ||
| 848 | + | ||
| 13 | <style scoped lang="scss"> | 849 | <style scoped lang="scss"> |
| 850 | +// 全局样式 | ||
| 851 | +.page-container { | ||
| 852 | + min-height: 100vh; | ||
| 853 | +} | ||
| 854 | + | ||
| 855 | +// 主内容容器 | ||
| 856 | +.main-content { | ||
| 857 | + padding-bottom: 80rpx; | ||
| 858 | +} | ||
| 859 | + | ||
| 860 | +// 顶部Tabs | ||
| 861 | +.top-tabs { | ||
| 862 | + //background-color: #fff; | ||
| 863 | +} | ||
| 864 | + | ||
| 865 | +// Tab内容区 | ||
| 866 | +.tab-content { | ||
| 867 | + //padding: 16rpx; | ||
| 868 | +} | ||
| 869 | + | ||
| 870 | +// 工单详情内容 | ||
| 871 | +.detail-content { | ||
| 872 | + .detail-cell-group { | ||
| 873 | + background-color: #fff; | ||
| 874 | + margin-bottom: 20rpx; | ||
| 875 | + } | ||
| 876 | + | ||
| 877 | + .cell-content-wrap { | ||
| 878 | + // 保持原有样式,兼容up-album布局 | ||
| 879 | + } | ||
| 880 | + | ||
| 881 | + .empty-text { | ||
| 882 | + color: #999; | ||
| 883 | + font-size: 26rpx; | ||
| 884 | + } | ||
| 885 | +} | ||
| 886 | + | ||
| 887 | +// 图片分类Tabs区块 | ||
| 888 | +.img-tabs-block { | ||
| 889 | + background-color: #fff; | ||
| 890 | + //border-radius: 12rpx; | ||
| 891 | + //padding: 16rpx; | ||
| 892 | + | ||
| 893 | + // 图片内容区 | ||
| 894 | + .img-tab-content { | ||
| 895 | + padding: 20rpx 15px ; | ||
| 896 | + text-align: center; | ||
| 897 | + //min-height: 120rpx; | ||
| 898 | + //display: flex; | ||
| 899 | + //align-items: center; | ||
| 900 | + //justify-content: center; | ||
| 901 | + // | ||
| 902 | + .img-album { | ||
| 903 | + //width: 100%; | ||
| 904 | + | ||
| 905 | + } | ||
| 906 | + | ||
| 907 | + .empty-img-text { | ||
| 908 | + height: 75px; | ||
| 909 | + line-height: 75px; | ||
| 910 | + color: #999; | ||
| 911 | + font-size: 28rpx; | ||
| 912 | + } | ||
| 913 | + } | ||
| 914 | +} | ||
| 915 | + | ||
| 916 | +// 流程节点区域(完整样式,确保内容可见) | ||
| 917 | +.process-content { | ||
| 918 | + //padding: 16rpx; | ||
| 919 | + //min-height: 400rpx; | ||
| 920 | + | ||
| 921 | + .empty-process { | ||
| 922 | + margin-top: 100rpx; | ||
| 923 | + } | ||
| 924 | + | ||
| 925 | + // 竖向步骤条容器样式 | ||
| 926 | + .vertical-steps { | ||
| 927 | + //width: 100%; | ||
| 928 | + background-color: #fff; | ||
| 929 | + padding: 20rpx; | ||
| 930 | + border-radius: 12rpx; | ||
| 931 | + display: flex; | ||
| 932 | + flex-direction: column; | ||
| 933 | + gap: 20rpx; // 步骤项间距 | ||
| 934 | + } | ||
| 935 | + | ||
| 936 | + // 自定义内容容器样式 | ||
| 937 | + .step-content-wrap { | ||
| 938 | + width: 100%; | ||
| 939 | + //padding: 10rpx 0; | ||
| 940 | + box-sizing: border-box; | ||
| 941 | + | ||
| 942 | + // 节点标题 + 操作人样式 | ||
| 943 | + .step-title { | ||
| 944 | + font-size: 30rpx; | ||
| 945 | + font-weight: 600; | ||
| 946 | + color: #333; | ||
| 947 | + margin-bottom: 12rpx; | ||
| 948 | + | ||
| 949 | + .operator-name { | ||
| 950 | + font-size: 30rpx; | ||
| 951 | + font-weight: 600; | ||
| 952 | + color: #333; | ||
| 953 | + margin-left: 20rpx; | ||
| 954 | + } | ||
| 955 | + } | ||
| 956 | + | ||
| 957 | + // 描述(时间 + 处理说明)样式 | ||
| 958 | + .step-desc { | ||
| 959 | + font-size: 24rpx; | ||
| 960 | + color: #666; | ||
| 961 | + line-height: 1.6; | ||
| 962 | + margin-bottom: 12rpx; | ||
| 963 | + | ||
| 964 | + .time-line { | ||
| 965 | + margin-bottom: 8rpx; | ||
| 966 | + | ||
| 967 | + .processing-tag { | ||
| 968 | + color: #f59e0b; | ||
| 969 | + margin-left: 10rpx; | ||
| 970 | + } | ||
| 971 | + } | ||
| 972 | + | ||
| 973 | + .reason-line { | ||
| 974 | + word-break: break-all; // 长文本自动换行 | ||
| 975 | + } | ||
| 976 | + } | ||
| 977 | + | ||
| 978 | + // 相册容器样式 | ||
| 979 | + .step-album-wrap { | ||
| 980 | + padding: 10rpx 0; | ||
| 981 | + | ||
| 982 | + .step-album { | ||
| 983 | + //width: 100%; | ||
| 984 | + } | ||
| 985 | + | ||
| 986 | + .no-img-tip { | ||
| 987 | + font-size: 24rpx; | ||
| 988 | + color: #999; | ||
| 989 | + margin-top: 10rpx; | ||
| 990 | + } | ||
| 991 | + } | ||
| 992 | + } | ||
| 993 | +} | ||
| 994 | + | ||
| 995 | +// 上传图片通用样式 | ||
| 996 | +.upload-wrap { | ||
| 997 | + margin-top: 20rpx; | ||
| 998 | + | ||
| 999 | + .upload-title { | ||
| 1000 | + font-size: 28rpx; | ||
| 1001 | + color: #333; | ||
| 1002 | + margin-bottom: 10rpx; | ||
| 1003 | + } | ||
| 1004 | +} | ||
| 1005 | + | ||
| 1006 | +.mt-20 { | ||
| 1007 | + margin-top: 20rpx; | ||
| 1008 | +} | ||
| 1009 | + | ||
| 1010 | +// 回退弹窗样式 | ||
| 1011 | +.reject-modal-content { | ||
| 1012 | + width: 100%; | ||
| 1013 | + box-sizing: border-box; | ||
| 1014 | + padding: 10rpx 0; | ||
| 1015 | +} | ||
| 1016 | + | ||
| 1017 | +.reject-textarea { | ||
| 1018 | + width: 100%; | ||
| 1019 | +} | ||
| 1020 | + | ||
| 1021 | +// 验收弹窗样式 | ||
| 1022 | +.accept-modal-content { | ||
| 1023 | + width: 100%; | ||
| 1024 | + box-sizing: border-box; | ||
| 1025 | +} | ||
| 1026 | + | ||
| 1027 | +.radio-group-wrap { | ||
| 1028 | + display: flex; | ||
| 1029 | + align-items: center; | ||
| 1030 | + gap: 40rpx; | ||
| 1031 | + font-size: 28rpx; | ||
| 1032 | + margin-bottom: 20rpx; | ||
| 1033 | +} | ||
| 1034 | + | ||
| 1035 | +.textarea-wrap { | ||
| 1036 | + width: 100%; | ||
| 1037 | + margin-top: 30rpx; | ||
| 1038 | +} | ||
| 1039 | + | ||
| 1040 | +.mt-30 { | ||
| 1041 | + margin-top: 30rpx; | ||
| 1042 | +} | ||
| 1043 | +// 针对 up-album 单图容器的样式(穿透 scoped 限制) | ||
| 1044 | +:deep .u-album__row__wrapper image { | ||
| 1045 | + width: 70px !important; // 与多图保持一致 | ||
| 1046 | + height: 70px !important; | ||
| 1047 | +} | ||
| 1048 | + | ||
| 14 | 1049 | ||
| 15 | </style> | 1050 | </style> |
| 16 | \ No newline at end of file | 1051 | \ No newline at end of file |
pages-sub/problem/work-order-manage/add-order.vue
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | label-position="left" | 5 | label-position="left" |
| 6 | :model="workOrderForm" | 6 | :model="workOrderForm" |
| 7 | ref="workOrderFormRef" | 7 | ref="workOrderFormRef" |
| 8 | - labelWidth="190rpx" | 8 | + labelWidth="200rpx" |
| 9 | > | 9 | > |
| 10 | <!-- 业务线单选框:移入form内,作为第一个表单项(核心调整) --> | 10 | <!-- 业务线单选框:移入form内,作为第一个表单项(核心调整) --> |
| 11 | <up-form-item | 11 | <up-form-item |
pages-sub/problem/work-order-manage/distribution-order.vue
| @@ -97,6 +97,7 @@ const assigneeList = ref([]) // 养护员列表 | @@ -97,6 +97,7 @@ const assigneeList = ref([]) // 养护员列表 | ||
| 97 | // ========== 工单表单数据(仅保留所需字段) ========== | 97 | // ========== 工单表单数据(仅保留所需字段) ========== |
| 98 | const workOrderForm = reactive({ | 98 | const workOrderForm = reactive({ |
| 99 | id:'', | 99 | id:'', |
| 100 | + busiLine:'', | ||
| 100 | taskId:'', | 101 | taskId:'', |
| 101 | orderNo: '', // 工单编号(对应接口参数id) | 102 | orderNo: '', // 工单编号(对应接口参数id) |
| 102 | assigneeId: '', // 养护员ID(对应接口参数nextAssignee) | 103 | assigneeId: '', // 养护员ID(对应接口参数nextAssignee) |
| @@ -120,6 +121,9 @@ onLoad((options) => { | @@ -120,6 +121,9 @@ onLoad((options) => { | ||
| 120 | workOrderForm.orderNo = options.orderNo | 121 | workOrderForm.orderNo = options.orderNo |
| 121 | workOrderForm.taskId = options.taskId | 122 | workOrderForm.taskId = options.taskId |
| 122 | workOrderForm.id = options.id | 123 | workOrderForm.id = options.id |
| 124 | + workOrderForm.busiLine = options.busiLine | ||
| 125 | + | ||
| 126 | + | ||
| 123 | } | 127 | } |
| 124 | console.log('从URL获取工单编号:', workOrderForm.orderNo) | 128 | console.log('从URL获取工单编号:', workOrderForm.orderNo) |
| 125 | }) | 129 | }) |
| @@ -141,8 +145,8 @@ const loadAssigneeList = async () => { | @@ -141,8 +145,8 @@ const loadAssigneeList = async () => { | ||
| 141 | console.log(userStore.userInfo.user.busiLine) | 145 | console.log(userStore.userInfo.user.busiLine) |
| 142 | let queryData = { | 146 | let queryData = { |
| 143 | // roleCode:userStore.userInfo.roles, | 147 | // roleCode:userStore.userInfo.roles, |
| 144 | - roleCode: 'yl_worker', | ||
| 145 | - busiLine: 'yl', | 148 | + // roleCode: 'yl_worker', |
| 149 | + busiLine: workOrderForm.busiLine, | ||
| 146 | // busiLine: userStore.userInfo.user.busiLine, | 150 | // busiLine: userStore.userInfo.user.busiLine, |
| 147 | pageNo: 1, | 151 | pageNo: 1, |
| 148 | pageSize: 100 | 152 | pageSize: 100 |
pages-sub/problem/work-order-manage/index.vue
| @@ -202,7 +202,7 @@ | @@ -202,7 +202,7 @@ | ||
| 202 | <view class="upload-wrap mt-20"> | 202 | <view class="upload-wrap mt-20"> |
| 203 | <view class="upload-title">上传图片(选填)</view> | 203 | <view class="upload-title">上传图片(选填)</view> |
| 204 | <up-upload | 204 | <up-upload |
| 205 | - :file-list="rejectImgs.imgList" | 205 | + :file-list="rejectImgs.rawImgList.value|| []" |
| 206 | @after-read="rejectImgs.uploadImgs" | 206 | @after-read="rejectImgs.uploadImgs" |
| 207 | @delete="rejectImgs.deleteImg" | 207 | @delete="rejectImgs.deleteImg" |
| 208 | multiple | 208 | multiple |
| @@ -251,7 +251,7 @@ | @@ -251,7 +251,7 @@ | ||
| 251 | <view class="upload-wrap mt-20"> | 251 | <view class="upload-wrap mt-20"> |
| 252 | <view class="upload-title">上传验收图片(选填)</view> | 252 | <view class="upload-title">上传验收图片(选填)</view> |
| 253 | <up-upload | 253 | <up-upload |
| 254 | - :file-list="acceptImgs.imgList" | 254 | + :file-list="acceptImgs.rawImgList.value || []" |
| 255 | @after-read="acceptImgs.uploadImgs" | 255 | @after-read="acceptImgs.uploadImgs" |
| 256 | @delete="acceptImgs.deleteImg" | 256 | @delete="acceptImgs.deleteImg" |
| 257 | 257 | ||
| @@ -325,10 +325,6 @@ const rejectImgs = useUploadImgs({ | @@ -325,10 +325,6 @@ const rejectImgs = useUploadImgs({ | ||
| 325 | fieldName: 'rejectImgs' // 自定义字段名 | 325 | fieldName: 'rejectImgs' // 自定义字段名 |
| 326 | }) | 326 | }) |
| 327 | 327 | ||
| 328 | -// 监听上传实例响应式变化,解决u-upload不刷新问题 | ||
| 329 | -watch(() => rejectImgs.rawImgList.value, (newVal) => { | ||
| 330 | - rejectImgs.imgList = newVal | ||
| 331 | -}, { deep: true }) | ||
| 332 | 328 | ||
| 333 | // ========== 验收弹窗相关状态(含图片上传) ========== | 329 | // ========== 验收弹窗相关状态(含图片上传) ========== |
| 334 | const acceptModalShow = ref(false); // 验收弹窗显示开关 | 330 | const acceptModalShow = ref(false); // 验收弹窗显示开关 |
| @@ -345,11 +341,6 @@ const acceptImgs = useUploadImgs({ | @@ -345,11 +341,6 @@ const acceptImgs = useUploadImgs({ | ||
| 345 | fieldName: 'acceptImgs' // 自定义字段名,区分回退图片 | 341 | fieldName: 'acceptImgs' // 自定义字段名,区分回退图片 |
| 346 | }) | 342 | }) |
| 347 | 343 | ||
| 348 | -// 监听验收图片上传实例响应式变化,解决u-upload不刷新问题 | ||
| 349 | -watch(() => acceptImgs.rawImgList.value, (newVal) => { | ||
| 350 | - acceptImgs.imgList = newVal | ||
| 351 | -}, { deep: true }) | ||
| 352 | - | ||
| 353 | // 分页查询列表 | 344 | // 分页查询列表 |
| 354 | const queryList = async (pageNo, pageSize) => { | 345 | const queryList = async (pageNo, pageSize) => { |
| 355 | try { | 346 | try { |
| @@ -451,7 +442,7 @@ const handleProcess = async (item) => { | @@ -451,7 +442,7 @@ const handleProcess = async (item) => { | ||
| 451 | try { | 442 | try { |
| 452 | if (nextStepMap[item.taskKey]?.name == '养护组长分配') { | 443 | if (nextStepMap[item.taskKey]?.name == '养护组长分配') { |
| 453 | uni.navigateTo({ | 444 | uni.navigateTo({ |
| 454 | - url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}&id=${item.id}` | 445 | + url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}&id=${item.id}&busiLine=${item.busiLine}` |
| 455 | }) | 446 | }) |
| 456 | } | 447 | } |
| 457 | if (nextStepMap[item.taskKey]?.name == '养护员待实施') { | 448 | if (nextStepMap[item.taskKey]?.name == '养护员待实施') { |
pages-sub/problem/work-order-manage/order-detail.vue
| @@ -160,11 +160,10 @@ | @@ -160,11 +160,10 @@ | ||
| 160 | :urls="currentImgList.slice(0, 3)" | 160 | :urls="currentImgList.slice(0, 3)" |
| 161 | :singleSize="70" | 161 | :singleSize="70" |
| 162 | :multipleSize="70" | 162 | :multipleSize="70" |
| 163 | - | ||
| 164 | :preview-full-image="true" | 163 | :preview-full-image="true" |
| 165 | class="img-album custom-album" | 164 | class="img-album custom-album" |
| 166 | ></up-album> | 165 | ></up-album> |
| 167 | - <text v-else class="empty-img-text">暂无图片</text> | 166 | + <text v-else class="empty-img-text">养护员未上传图片</text> |
| 168 | </view> | 167 | </view> |
| 169 | </view> | 168 | </view> |
| 170 | </view> | 169 | </view> |
| @@ -290,7 +289,7 @@ | @@ -290,7 +289,7 @@ | ||
| 290 | <view class="upload-wrap mt-20"> | 289 | <view class="upload-wrap mt-20"> |
| 291 | <view class="upload-title">上传回退图片(选填)</view> | 290 | <view class="upload-title">上传回退图片(选填)</view> |
| 292 | <up-upload | 291 | <up-upload |
| 293 | - :file-list="rejectImgs.imgList" | 292 | + :file-list="rejectImgs.rawImgList.value || []" |
| 294 | @after-read="rejectImgs.uploadImgs" | 293 | @after-read="rejectImgs.uploadImgs" |
| 295 | @delete="rejectImgs.deleteImg" | 294 | @delete="rejectImgs.deleteImg" |
| 296 | multiple | 295 | multiple |
| @@ -339,7 +338,7 @@ | @@ -339,7 +338,7 @@ | ||
| 339 | <view class="upload-wrap mt-20"> | 338 | <view class="upload-wrap mt-20"> |
| 340 | <view class="upload-title">上传验收图片(选填)</view> | 339 | <view class="upload-title">上传验收图片(选填)</view> |
| 341 | <up-upload | 340 | <up-upload |
| 342 | - :file-list="acceptImgs.imgList" | 341 | + :file-list="acceptImgs.rawImgList.value || []" |
| 343 | @after-read="acceptImgs.uploadImgs" | 342 | @after-read="acceptImgs.uploadImgs" |
| 344 | @delete="acceptImgs.deleteImg" | 343 | @delete="acceptImgs.deleteImg" |
| 345 | multiple | 344 | multiple |
| @@ -573,10 +572,7 @@ const rejectImgs = useUploadImgs({ | @@ -573,10 +572,7 @@ const rejectImgs = useUploadImgs({ | ||
| 573 | formRef: null, | 572 | formRef: null, |
| 574 | fieldName: 'rejectImgs' | 573 | fieldName: 'rejectImgs' |
| 575 | }) | 574 | }) |
| 576 | -// 监听上传实例响应式变化,解决u-upload不刷新问题 | ||
| 577 | -watch(() => rejectImgs.rawImgList.value, (newVal) => { | ||
| 578 | - rejectImgs.imgList = newVal | ||
| 579 | -}, {deep: true}) | 575 | + |
| 580 | 576 | ||
| 581 | // ========== 验收弹窗相关状态(新增图片上传实例) ========== | 577 | // ========== 验收弹窗相关状态(新增图片上传实例) ========== |
| 582 | const acceptModalShow = ref(false); // 验收弹窗显示开关 | 578 | const acceptModalShow = ref(false); // 验收弹窗显示开关 |
| @@ -591,10 +587,7 @@ const acceptImgs = useUploadImgs({ | @@ -591,10 +587,7 @@ const acceptImgs = useUploadImgs({ | ||
| 591 | formRef: null, | 587 | formRef: null, |
| 592 | fieldName: 'acceptImgs' | 588 | fieldName: 'acceptImgs' |
| 593 | }) | 589 | }) |
| 594 | -// 监听验收图片上传实例响应式变化 | ||
| 595 | -watch(() => acceptImgs.rawImgList.value, (newVal) => { | ||
| 596 | - acceptImgs.imgList = newVal | ||
| 597 | -}, {deep: true}) | 590 | + |
| 598 | 591 | ||
| 599 | // ========== 生成临时key ========== | 592 | // ========== 生成临时key ========== |
| 600 | const generateTempKey = () => { | 593 | const generateTempKey = () => { |
| @@ -900,6 +893,7 @@ onShow(() => { | @@ -900,6 +893,7 @@ onShow(() => { | ||
| 900 | // 图片内容区 | 893 | // 图片内容区 |
| 901 | .img-tab-content { | 894 | .img-tab-content { |
| 902 | padding: 20rpx 15px ; | 895 | padding: 20rpx 15px ; |
| 896 | + text-align: center; | ||
| 903 | //min-height: 120rpx; | 897 | //min-height: 120rpx; |
| 904 | //display: flex; | 898 | //display: flex; |
| 905 | //align-items: center; | 899 | //align-items: center; |
| @@ -911,8 +905,8 @@ onShow(() => { | @@ -911,8 +905,8 @@ onShow(() => { | ||
| 911 | } | 905 | } |
| 912 | 906 | ||
| 913 | .empty-img-text { | 907 | .empty-img-text { |
| 914 | - height: 100px; | ||
| 915 | - line-height: 100px; | 908 | + height: 75px; |
| 909 | + line-height: 75px; | ||
| 916 | color: #999; | 910 | color: #999; |
| 917 | font-size: 28rpx; | 911 | font-size: 28rpx; |
| 918 | } | 912 | } |