Commit 34d239d6f0c79ebeb702c877f7e075afaf5acfa3

Authored by 刘淇
1 parent f0ec74d6

全域巡查员

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