吉安感知网项目-前端
罗广辉
2026-02-03 6a15a201470e1f1ca7323b7cb8cee9a8a41c733f
applications/mobile-web-view/src/appPages/work/workDetail/index.vue
@@ -10,641 +10,82 @@
            </van-swipe>
            <van-image-preview v-model:show="previewShow" :images="getImageList" :initial-index="previewIndex" />
            <div class="detailTitle">
               <div class="titleText">
                  <div class="itemStatus">
                     <span v-if="currentDetail.status === 0" style="background-color: #ff7411"></span>
                     <span v-else-if="currentDetail.status === 2" style="background-color: #ff472f"></span>
                     <span v-else-if="currentDetail.status === 3" style="background-color: #ffc300"></span>
                     <span v-else-if="currentDetail.status === 4" style="background-color: #06d957"></span>
                     <div>{{ currentDetail.event_name }}</div>
                  </div>
                  <div class="timeNavigation">
                     <p>{{ formatDate(currentDetail.create_time) }}</p>
                     <img @click="jumpMap(currentDetail)" src="/src/appDataSource/appwork/navigation.svg"
                        alt="" />
                  </div>
               </div>
            </div>
         </div>
      </div>
      <!-- 步骤条 -->
      <div class="stepBox">
         <div class="stepContainer">
            <van-steps direction="vertical" :active="currentStep">
               <van-step v-for="(step, index) in displayedSteps" :key="step.status">
                  <div class="horizontal-step">
                     <span class="step-title" :class="getStatusClass(index)">{{ step.title }}</span>
   <!-- 工单内容 -->
    <div class="worderContainer">
      <div class="workOrderContent">
        <div class="workOrderTitle">工单内容</div>
        <div class="workOrderContainer">
          <div class="orderRow">
            <div class="rowTitle">工单编号</div>
            <div>{{ workDetailData.eventNum }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">工单处置人</div>
            <div>{{ workDetailData.disposeUserName }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">处置部门</div>
            <div>{{ workDetailData.disposeDeptName }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">拍摄时间</div>
            <div>{{ workDetailData.shootTime }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">分发人员</div>
            <div>{{ workDetailData.distributeUserName }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">分发部门</div>
            <div>{{ workDetailData.distributeDeptName }}</div>
          </div>
                     <div class="step-desc" v-if="stepResponse[index]">
                        <span>{{ stepResponse[index].name || '' }}</span>
                        <span>{{ stepResponse[index].create_time || '' }}</span>
                     </div>
                  </div>
               </van-step>
            </van-steps>
         </div>
      </div>
      <!-- 工单内容 -->
      <div class="worderContainer">
         <div class="workOrderContent">
            <div class="workOrderTitle">工单内容</div>
            <div class="workOrderContainer">
               <div class="orderRow">
                  <span class="required-mark" v-if="isEditable">*</span>
                  <div class="rowTitle">工单名称</div>
                  <div v-if="!isEditable">{{ currentDetail.event_name }}</div>
                  <van-field v-else v-model="currentDetail.event_name" name="event_name" required
                     input-align="right" placeholder="请输入" class="custom-field" />
               </div>
               <div class="orderRow">
                  <div class="rowTitle">工单编号</div>
                  <div>{{ currentDetail.event_num }}</div>
               </div>
               <div class="orderRow">
                  <div class="rowTitle">工单类型</div>
                  <div>{{ workOrderTypeName }}</div>
               </div>
               <div class="orderRow" v-if="currentDetail.work_type == '0'">
                  <div class="rowTitle">关联任务</div>
                  <div>{{ currentDetail.job_name }}</div>
               </div>
               <div class="orderRow">
                  <div class="rowTitle">工单创建人</div>
                  <div>{{ currentDetail.event_num?.slice(0, 2) === 'AI' ? '智飞agent' : currentDetail.create_user }}
                  </div>
               </div>
               <div class="orderRow">
                  <div class="rowTitle">事件地址</div>
                  <div class="addressBox" @click="jumpMap(currentDetail)">
                     <div class="rowAddress">{{ currentDetail.address }}</div>
                     <img class="pointing" src="/src/appDataSource/appwork/pointing.svg" alt="" />
                  </div>
               </div>
               <div class="orderRow">
                  <div class="guanlian">
                     <span class="required-mark" v-if="isEditable">*</span>
                     <div class="rowTitle">关联算法</div>
                  </div>
                  <div v-if="!isEditable">{{ currentDetail.ai_types }}</div>
                  <div v-else>
                     <span @click="openselect" class="selectTrigger">
                        {{ currentDetail.ai_types }}
                        <img class="downpointing" src="/src/appDataSource/appwork/downpointing.svg" alt="" />
                     </span>
                     <van-popup v-model:show="showPicker" destroy-on-close position="bottom"
                        :close-on-click-overlay="true">
                        <van-picker v-model="selectedValues" title="选择关联算法" :columns="columns"
                           @confirm="onConfirm" @cancel="onCancel" />
                     </van-popup>
                  </div>
               </div>
               <div class="orderRow">
                  <div class="rowTitle">发起部门</div>
                  <div>{{ currentDetail.dept_name }}</div>
               </div>
               <div class="orderRow">
                  <div class="rowTitle">发起任务时间</div>
                  <div>{{ currentDetail.create_time }}</div>
               </div>
               <div class="orderRow">
                  <div class="rowTitle">所属机巢</div>
                  <div>{{ currentDetail.device_names }}</div>
               </div>
               <div class="orderRow">
                  <span class="required-mark" v-if="isEditable">*</span>
                  <div class="rowTitle">工单内容</div>
                  <div v-if="!isEditable">{{ currentDetail.content }}</div>
                  <van-field v-else class="custom-field" input-align="right" v-model="currentDetail.content"
                     name="remark" required placeholder="请输入" />
               </div>
               <div class="rowCard" v-if="isEditableProcess">
                  <div class="guanlian">
                     <span class="required-mark">*</span>
                     <div class="rowTitle">
                        上传图片
                        <span>(只能上传jpg、jpeg、png照片,且不超过5M)</span>
                     </div>
                  </div>
                  <div>
                     <van-field name="uploader">
                        <template #input>
                           <van-uploader :disabled="!isCurrentUserAssigned" v-model="fileList"
                              :after-read="afterRead" :max-count="1" :max-size="5 * 1024 * 1024"
                              @oversize="onOversize" :before-read="beforeRead" @delete="handleDelete"
                              accept="image/jpeg,image/jpg,image/png" />
                        </template>
                     </van-field>
                  </div>
               </div>
               <div class="orderRow" v-if="isEditableProcess">
                  <span class="required-mark">*</span>
                  <div class="rowTitle">事件处理详情</div>
                  <van-field class="custom-field" input-align="right" v-model="currentDetail.processingDetail"
                     name="event_name" required placeholder="请输入" :disabled="!isCurrentUserAssigned" />
               </div>
               <div class="orderRow" v-if="isComplent">
                  <div class="rowTitle">事件处理详情</div>
                  <div>{{ currentDetail.processingDetail }}</div>
               </div>
            </div>
         </div>
      </div>
      <!-- 操作按钮 -->
      <div class="actionButton">
         <div class="floatingBtn leftFloatingBtn" @click="leftClick">
            <img src="/src/appDataSource/appwork/leftBtn1.svg" alt="" />
         </div>
         <div class="paginationInfo">
            <span>{{ currentPage }} / {{ totalRecords }}</span>
         </div>
         <div class="btngroups" v-if="currentDetail.status === 2">
            <van-button type="primary" color="#FF452C" round text="不通过" @click="rejectTicket"></van-button>
            <van-button type="primary" color="#1D6FE9" round text="通过" @click="approveTicket"></van-button>
         </div>
         <div class="btngroups" v-else-if="currentDetail.status === 0">
            <van-button type="primary" color="#FF452C" round text="不受理" @click="rejectTicket"></van-button>
            <van-button type="primary" color="#1D6FE9" round text="受理" @click="approveAndDispatch"></van-button>
         </div>
         <div class="btngroups" v-else-if="currentDetail.status === 3">
            <van-button type="primary" color="#FF452C" round text="取消" @click="cancellation"></van-button>
            <van-button :disabled="!isCurrentUserAssigned" type="primary" color="#1D6FE9" round text="完成工单"
               @click="completeTicket"></van-button>
         </div>
         <div class="btngroups back-btn" v-else>
            <van-button type="primary" round color="#FF730F" text="返回" @click="cancellation"></van-button>
         </div>
         <div class="floatingBtn rightFloatingBtn" @click="rightClick">
            <img src="/src/appDataSource/appwork/rightBtn1.svg" alt="" />
         </div>
      </div>
      <!--派发工单对话框-->
      <van-dialog v-model:show="isshowDispatch" title="派发工单" show-cancel-button @confirm="submitDispatch"
         @cancel="dispatchCancel">
         <van-field v-model="dispatchForm.departmentName" is-link readonly label="选择部门" placeholder="请选择部门"
            @click="openPicker('department')" />
         <van-field v-model="dispatchForm.handlerName" is-link readonly label="选择处理人" placeholder="请选择处理人"
            @click="openPicker('processor')" :disabled="!dispatchForm.department" />
      </van-dialog>
      <teleport to="body">
         <van-popup v-model:show="showGlobalPicker" position="bottom">
            <!-- 部门选择器 -->
            <van-picker v-if="currentPickerType === 'department'" v-model="selectedDepartment" title="选择部门"
               :columns="departments" @confirm="onDepartmentConfirm" @cancel="onPickerCancel" />
            <!-- 处理人选择器 -->
            <van-picker v-if="currentPickerType === 'processor'" v-model="selectedProcessor" title="选择处理人"
               :columns="availableDispatchHandlers" @confirm="onProcessorConfirm" @cancel="onPickerCancel" />
         </van-popup>
      </teleport>
          <div class="orderRow">
            <div class="rowTitle">分发时间</div>
            <div>{{ workDetailData.distributeTime }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">工单位置</div>
            <div class="rowAddress" @click="jumpMap(workDetailData)">{{ workDetailData.eventLocation }}</div>
          </div>
        </div>
      </div>
    </div>
   </div>
</template>
<script setup>
import {ALL_WORK_ORDER_TYPE_OPTIONS} from '@ztzf/constants'
import { getDeviceRegion } from '@/api/home/aggregation'
import { usePermission } from '@/appPages/work/usePermission'
import { showToast, showNotify, showImagePreview } from 'vant'
import { getShowImg, getSmallImg } from '@/utils/util'
import { useRoute } from 'vue-router'
import { getStepInfo, getList, flowEvent, getTicketInfo } from '/src/api/work/index.js'
import { showToast, showNotify, showImagePreview } from 'vant'
import dayjs from 'dayjs'
import _ from 'lodash'
import { useStore } from 'vuex'
const store = useStore()
const userInfo = computed(() => store?.state?.user?.userInfo)
const { permission, getButtonsApi } = usePermission()
const showPicker = ref(false)
const selectedValues = ref([])
const columns = ref([])
const allAlgorithms = ref([])
const algorithms = ref([])
const types = ref([]) //工单类型
const eventNum = ref('')
const currentStatus = ref(0)
const stepResponse = ref([])
const currentStep = ref(0)
const route = useRoute()
const currentDetail = ref({ status: 0 })
const currentIndex = ref(null) //当前显示数据索引
const departments = ref([]) //部门
const departmentUsers = ref({})
const fileList = ref([])
// 机巢数据
let machineData = ref([])
// 处理人选择相关
const processorColumns = ref([])
// 可编辑状态
const isEditable = computed(() => currentDetail.value.status === 0)
const isEditableProcess = computed(() => currentDetail.value.status === 3)
const isComplent = computed(() => currentDetail.value.status === 4)
// 工单内容
const workDetailData = ref({})
// 分页相关
const currentPage = ref(1)
const pageSize = ref(1)
const totalRecords = ref(0)
const formatDate = dateString => {
   return dayjs(dateString).format('MM/DD HH:mm')
}
const allStepConfigs = ref([
   { title: '待审核', status: 2 },
   { title: '待处理', status: 0 },
   { title: '处理中', status: 3 },
   { title: '已完成', status: 4 },
])
const hasProcessingBtnPermission = () => {
   return permission.value && permission.value.tickets_processing_btn === true
}
// 完成工单
const hasProcessedAndOverBtnPermission = () => {
   return permission.value && permission.value.tickets_view_processedAndOver === true
}
// 通过不通过
const hasReviewBtnPermission = () => {
   return permission.value && permission.value.tickets_review_btn === true
}
// 是否有权限完成工单
const isCurrentUserAssigned = computed(() => {
   const handleUserId = currentDetail.value?.handle_user_id
   const currentUserId = userInfo.value?.user_id
   return !!handleUserId && !!currentUserId && String(handleUserId) === String(currentUserId)
// 预览图片
const previewShow = ref(false)
const previewIndex = ref(0)
const getImageList = computed(() => {
   const imageArr = []
   const detail = workDetailData.value
   if (detail.eventImageUrl) {
      const smallUrl = getSmallImg(detail.eventImageUrl)
      imageArr.push(smallUrl)
   }
   return imageArr
})
const getStatusClass = index => {
   if (index <= currentStep.value) {
      const status = Number(stepResponse.value[index]?.status) || 0
      const statusClasses = {
         2: 'status-pending', // 待审核
         0: 'status-waiting', // 待处理
         3: 'status-processing', // 处理中
         4: 'status-completed', // 已完成
      }
      return statusClasses[status] || ''
   }
   return 'status-default'
}
// 关联算法
const getTicketInfoData = async () => {
   const response = await getTicketInfo()
   const { dept_data, event_type, ai_type, info } = response.data.data
   allAlgorithms.value = info
   types.value = Object.entries(event_type).map(([key, value]) => ({
      label: value,
      value: key,
   }))
   departments.value = dept_data.map(item => ({
      text: item.dept_name,
      value: item.id,
   }))
   departmentUsers.value = dept_data.reduce((acc, dept) => {
      acc[dept.id] = dept.user_data || []
      return acc
   }, {})
}
// 处理人
const availableDispatchHandlers = computed(() => {
   if (!dispatchForm.value.department) return []
   const users = departmentUsers.value[dispatchForm.value.department]
   if (!users) return []
   return users.map(user => ({
      text: user.name,
      value: user.id,
   }))
})
// 关联算法选择
const handleTypeChange = typeValue => {
   const matchedCategory = allAlgorithms.value.find(category => category.dict_key === typeValue)
   if (!matchedCategory || !matchedCategory.algorithms || matchedCategory.algorithms.length === 0) {
      // 无匹配的算法时清空
      algorithms.value = []
      return
   }
   algorithms.value = matchedCategory.algorithms.map(algo => ({
      label: algo.dict_value,
      value: algo.dict_key,
      dict_key: algo.dict_key,
      dict_value: algo.dict_value,
   }))
   columns.value = algorithms.value.map(item => ({
      text: item.label,
      value: item.value,
   }))
}
// 机巢数据
const handleNodeClick = async data => {
   const droneList = await getDeviceRegion({ areaCode: userInfo.value.detail.areaCode })
   machineData.value = droneList?.data?.data
}
const tableData = ref([])
const fetchWorkData = async (val) => {
   const params = {
      current: Number(currentPage.value) || 1,
      size: pageSize.value,
      source: 1,
      // event_name: val.keyword || val.eventNum,
      ai_types: val.aiType,
      way_line_job_info_id: val.wLJobInfoId,
      work_types: ALL_WORK_ORDER_TYPE_OPTIONS
   }
   if (val.status !== 'undefined') {
      params.status = val.status
   }
   const res = await getList(params)
   const response = res.data.data.records
   totalRecords.value = res.data.data.total || 0
  console.log(totalRecords.value,res.data.data.total,2222)
   if (response && response.length > 0) {
      const item = response[0]
      const matchedMachine = machineData.value.find(m => m.device_sn === item.device_sn)
      const deviceNickname = matchedMachine?.nickname || ''
      currentDetail.value = {
         ...item,
         processingDetail: item.processing_details,
         update_photo_url: item.update_photo_url,
         photos: [],
         aiType: item.ai_type_key_list?.join(',') || '',
         status: Number(item.status) || 0,
         device_names: deviceNickname ? deviceNickname : ''
      }
      currentStatus.value = currentDetail.value.status
      handleTypeChange(currentDetail.value.work_order_type_dict_key)
      await getStepInfoData(currentDetail.value.event_num)
   }
}
// 计算要显示的步骤
const displayedSteps = computed(() => {
   return allStepConfigs.value.filter(stepConfig => {
      return stepResponse.value.some(stepData => Number(stepData?.status) === stepConfig.status)
const openPreview = index => {
   const detail = workDetailData.value
   const showUrl = getShowImg(detail.eventImageUrl)
   showImagePreview({
      images: [showUrl],
      startPosition: 0,
   })
})
// 计算工单类型显示名称
const workOrderTypeName = computed(() => {
   const type = types.value.find(item => item.value === currentDetail.value.work_order_type_dict_key)
   return type ? type.label : currentDetail.value.work_order_type_dict_key
})
// 步骤条
const calculateCurrentStep = status => {
   const stepIndex = displayedSteps.value.findIndex(step => step.status === status)
   return stepIndex !== -1 ? stepIndex : 0
}
const getStepInfoData = async val => {
   const res = await getStepInfo(val)
   stepResponse.value = res.data.data.map(item => ({
      ...item,
      status: Number(item.status) || 0,
   }))
   currentStep.value = calculateCurrentStep(currentStatus.value)
}
// 通过
const approveTicket = async () => {
   const data = {
      id: currentDetail.value.id,
      status: currentDetail.value.status,
      isPass: 0, // 0 表示通过
      eventNum: currentDetail.value.event_num,
   }
   const file = currentDetail.value.file || null
   const response = await flowEvent(data, file)
   if (response.data.code === 0) {
      showToast('工单已通过')
   }
   const transmitData = { data: { type: 'workback', fun: 'add' } }
   wx.miniProgram.switchTab({ url: `/pages/work/index?addLog=111` })
   wx.miniProgram.postMessage(transmitData)
   uni.postMessage(transmitData)
}
// 不通过/不受理
const rejectTicket = async () => {
   const data = {
      id: currentDetail.value.id,
      status: currentDetail.value.status,
      isPass: 1,
   }
   const response = await flowEvent(data)
   if (response.data.code === 0) {
      showToast('工单未通过')
   }
   const transmitData = { data: { type: 'workback', fun: 'add' } }
   wx.miniProgram.switchTab({ url: `/pages/work/index?addLog=111` })
   wx.miniProgram.postMessage(transmitData)
   uni.postMessage(transmitData)
}
const isshowDispatch = ref(false)
// 受理
const approveAndDispatch = () => {
   if (!currentDetail.value.event_name) {
      showToast('请填写工单名称')
      return
   }
   if (!currentDetail.value.ai_types) {
      showToast('请选择关联算法')
      return
   }
   if (!currentDetail.value.content) {
      showToast('请填写工单内容')
      return
   }
   isshowDispatch.value = true
}
const dispatchCancel = () => {
   // 重置表单
   dispatchForm.value = {
      department: '',
      departmentName: '',
      handler: '',
      handlerName: '',
   }
   isshowDispatch.value = false
}
const dispatchForm = ref({
   department: '', // 存储部门ID (value)
   departmentName: '', // 显示部门名称 (text)
   handler: '', // 存储处理人ID (value)
   handlerName: '', // 显示处理人名称 (text)
})
const selectedDepartment = ref([])
const selectedProcessor = ref([])
const showGlobalPicker = ref(false)
const currentPickerType = ref('')
const openPicker = type => {
   currentPickerType.value = type
   showGlobalPicker.value = true
}
// 部门选择确认
const onDepartmentConfirm = value => {
   dispatchForm.value.department = value.selectedValues[0]
   dispatchForm.value.departmentName = value.selectedOptions[0].text
   showGlobalPicker.value = false
}
// 处理人选择确认
const onProcessorConfirm = value => {
   if (!dispatchForm.value.department) {
      showToast('请先选择部门')
      return
   }
   dispatchForm.value.handler = value.selectedValues[0]
   dispatchForm.value.handlerName = value.selectedOptions[0].text
   showGlobalPicker.value = false
}
// 取消选择
const onPickerCancel = () => {
   showGlobalPicker.value = false
}
// 派发工单
const submitDispatch = async () => {
   if (!dispatchForm.value.department) {
      showToast('请选择部门')
      return
   }
   if (!dispatchForm.value.handler) {
      showToast('请选择处理人')
      return
   }
   try {
      const data = {
         id: currentDetail.value.id,
         status: currentDetail.value.status,
         isPass: 0,
         eventName: currentDetail.value.event_name,
         eventNum: currentDetail.value.event_num,
         workOrderTypeDictKey: currentDetail.value.work_order_type_dict_key,
         content: currentDetail.value.content,
         createDept: dispatchForm.value.department,
         updateUser: dispatchForm.value.handler,
         aiType: currentDetail.value.aiType,
      }
      const file = currentDetail.value.file || null
      const response = await flowEvent(data, file)
      if (response.data.code === 0) {
         showToast('工单派发成功')
         const transmitData = { data: { type: 'workback', fun: 'add' } }
         wx.miniProgram.switchTab({ url: `/pages/work/index?addLog=111` })
         wx.miniProgram.postMessage(transmitData)
         uni.postMessage(transmitData)
         isshowDispatch.value = false
      }
   } catch (error) {
      showToast('工单派发失败')
   }
}
// 完成工单
const completeTicket = async () => {
   if (!currentDetail.value.processingDetail) {
      showToast('请先填写事件处理详情')
      return
   }
   if (!currentDetail.value.photos || currentDetail.value.photos.length === 0) {
      showToast('请选择上传图片')
      return
   }
   const data = {
      id: currentDetail.value.id,
      status: currentDetail.value.status,
      processingDetails: currentDetail.value.processingDetail,
      eventNum: currentDetail.value.event_num,
   }
   const file = currentDetail.value.photos?.[0] || null
   const response = await flowEvent(data, file)
   if (response.data.code === 0) {
      showToast('工单已完成')
   }
   const transmitData = { data: { type: 'workback', fun: 'add' } }
   wx.miniProgram.switchTab({ url: `/pages/work/index?addLog=111` })
   wx.miniProgram.postMessage(transmitData)
   uni.postMessage(transmitData)
}
// 取消
const cancellation = () => {
   const transmitData = { data: { type: 'workback', fun: 'add' } }
   wx.miniProgram.switchTab({ url: `/pages/work/index?addLog=111` })
   wx.miniProgram.postMessage(transmitData)
   uni.postMessage(transmitData)
}
// 下拉选择
const openselect = () => {
   showPicker.value = true
}
// 选择器确认方法
const onConfirm = val => {
   currentDetail.value.ai_types = val.selectedOptions.map(option => option.text).join(',')
   currentDetail.value.aiType = val.selectedValues.join(',')
   showPicker.value = false
}
// 选择器取消方法
const onCancel = () => {
   showPicker.value = false
}
// 文件上传前的校验
const beforeRead = file => {
   const ext = file.name.split('.').pop().toLowerCase()
   const allowedExts = ['jpg', 'jpeg', 'png']
   if (!allowedExts.includes(ext)) {
      showToast('请上传 jpg/jpeg/png 格式图片')
      return false
   }
   return true
}
// 文件大小超过限制时的回调
const onOversize = file => {
   showToast('文件大小不能超过 5MB')
}
// 文件读取完成后的回调
const afterRead = file => {
   currentDetail.value.photos = [file.file]
}
// 处理图片删除
const handleDelete = () => {
   currentDetail.value.photos = []
}
// 更新当前显示的工单详情
const updateCurrentDetail = () => {
   currentDetail.value = tableData.value[currentIndex.value]
   if (currentDetail.value.status !== undefined) {
      currentDetail.value.status = Number(currentDetail.value.status) || 0
   }
   currentStatus.value = currentDetail.value.status
   getStepInfoData(currentDetail.value.event_num)
}
// 上一页
const leftClick = () => {
   if (currentPage.value > 1) {
      currentPage.value--
      fetchWorkData(route.query)
   } else {
      showToast('已经是第一页')
   }
}
// 下一页
const rightClick = () => {
   if (currentPage.value < totalRecords.value) {
      currentPage.value++
      fetchWorkData(route.query)
   } else {
      showToast('已经是最后一页')
   }
   previewIndex.value = index
   previewShow.value = true
}
// 跳转地图
const jumpMap = item => {
@@ -653,57 +94,15 @@
   wx.miniProgram.postMessage(transmitData)
   uni.postMessage(transmitData)
}
// 预览图片
const previewShow = ref(false)
const previewIndex = ref(0)
const getImageList = computed(() => {
   const imageArr = []
   const detail = currentDetail.value
   if (detail.photo_url) {
      const smallUrl = getSmallImg(detail.photo_url)
      imageArr.push(smallUrl)
   }
   if (detail.update_photo_url) {
      const smallUrl = getSmallImg(detail.update_photo_url)
      imageArr.push(smallUrl)
   }
   return imageArr
})
const openPreview = index => {
   const detail = currentDetail.value
   const showUrl = getShowImg(detail.photo_url || detail.update_photo_url)
   showImagePreview({
      images: [showUrl],
      startPosition: 0,
   })
   previewIndex.value = index
   previewShow.value = true
}
onMounted(async () => {
   handleNodeClick()
   eventNum.value = route.query.eventNum || ''
   await getTicketInfoData()
  currentPage.value = route.query.current
   await fetchWorkData(route.query)
   await getStepInfoData(eventNum.value)
   currentIndex.value = tableData.value.findIndex(item => item.event_num === currentDetail.value.event_num)
workDetailData.value = JSON.parse(route.query.workDetailData)
console.log('route.query',workDetailData.value);
})
</script>
<style lang="scss" scoped>
.workDetailContainer {
   position: relative;
   .required-mark {
      color: #ff4d4f; // 红色
      margin-left: 4px;
   }
  padding-top: 44px;
   .detailTop {
      .image-container {
         position: relative;
@@ -716,255 +115,6 @@
            display: block;
            object-fit: cover;
         }
         .detailTitle {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            padding: 5px;
            height: 30px;
            background: rgba(7, 7, 7, 0.4);
         }
         .titleText {
            display: flex;
            width: 100%;
            justify-content: space-between;
            align-items: center;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 13px;
            color: #ffffff;
            .itemStatus {
               display: flex;
               align-items: center;
               font-family: Source Han Sans CN, Source Han Sans CN;
               font-weight: 400;
               font-size: 13px;
               color: #ffffff;
               span {
                  display: inline-block;
                  width: 10px;
                  height: 10px;
                  border-radius: 50%;
                  margin-right: 7px;
               }
            }
         }
         .timeNavigation {
            display: flex;
            align-items: center;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 13px;
            color: #ffffff;
            img {
               width: 20px;
               height: 20px;
               margin-left: 5px;
            }
         }
      }
   }
   .stepBox {
      padding: 0 12px;
   }
   .stepContainer {
      margin-top: 10px;
      display: flex;
      border-radius: 5px;
      padding: 10px;
      background: #fff;
      :deep() {
         .van-step__circle-container {
            font-size: 20px;
         }
         .van-step__circle {
            width: 15px;
            height: 15px;
         }
         .van-step--vertical {
            padding: 20px 20px 20px 0;
         }
         .van-step__circle-container,
         .van-step__line {
            top: 50%;
         }
         .van-step--vertical:not(:last-child):after {
            border-bottom-width: 0;
         }
      }
      .horizontal-step {
         display: flex;
         align-items: center;
         gap: 12px;
         .step-title {
            min-width: 60px;
            background: #e8e8e8;
            padding: 5px;
            border-radius: 5px;
            text-align: center;
            &.status-pending {
               background-color: #ffebeb; // 待审核
               color: #ff1414;
            }
            &.status-waiting {
               background-color: #fff1e6; // 待处理
               color: #ff7411;
            }
            &.status-processing {
               background-color: #fff6d8; // 处理中
               color: #ffbb00;
            }
            &.status-completed {
               background-color: #e5fcff; // 已完成
               color: #0291a1;
            }
            &.status-default {
               background-color: #e8e8e8; // 默认背景色
               color: #191919;
            }
         }
         .step-desc {
            display: flex;
            justify-content: space-between;
            gap: 28px;
            color: #222324;
            font-size: 14px;
         }
         .step-desc span:first-child {
            width: 60px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
         }
         span:last-child {
            margin-left: auto;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
         }
      }
   }
   :deep(.van-step__circle) {
      width: 8px;
      height: 8px;
   }
   /* 悬浮左右按钮样式 */
   .floatingBtn {
      position: fixed;
      top: 50%;
      width: 46px;
      height: 46px;
      z-index: 9;
      transform: translateY(-50%);
      background: rgba(17, 17, 17, 0.28);
      backdrop-filter: blur(3px);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
   }
   .leftFloatingBtn {
      left: 5px;
      /* 左边距离 */
   }
   .rightFloatingBtn {
      right: 5px;
      /* 右边距离 */
   }
   .floatingBtn img {
      width: 10px;
      height: 18px;
   }
   .paginationInfo {
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      font-size: 14px;
      color: #666;
      background: rgba(255, 255, 255, 0.9);
      padding: 4px 12px;
      border-radius: 12px;
   }
   .actionButton {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 61px;
      background: #ffffff;
      border-radius: 6px 6px 6px 6px;
      padding: 0 18px;
      .btngroups {
         display: flex;
         justify-content: space-between;
         align-items: center;
         .van-button {
            padding: 9px 20px;
            height: 38px;
            width: 156px;
            &:last-child {
               margin-left: 12px;
            }
         }
      }
      .back-btn :deep(.van-button) {
         width: 100%;
         width: 324px;
         margin-left: 0px !important;
      }
      .leftBtn {
         width: 27px;
         height: 27px;
         cursor: pointer;
         img {
            width: 27px;
            height: 27px;
         }
      }
      .disableds {
         background: #999 !important;
         cursor: not-allowed !important;
         pointer-events: none;
         opacity: 0.3 !important;
      }
   }
@@ -986,12 +136,10 @@
         font-weight: bold;
         font-size: 16px;
         color: #222324;
         // margin-bottom: 16px;
      }
      .workOrderContainer {
         .orderRow {
            // margin-bottom: 10px;
            display: flex;
            justify-content: space-between;
            align-items: center;
@@ -1034,35 +182,16 @@
         }
         .rowAddress {
             font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: 400;
            font-size: 14px;
            color: #1d6fe9;
            white-space: nowrap;
            /* 禁止换行 */
            overflow: hidden;
            text-overflow: ellipsis;
            // max-width: 74%;
            text-decoration: underline;
            text-align: right;
            padding-top: 1px;
            padding-left: 5px;
            padding-right: 2px;
         }
         .selectTrigger {
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 14px;
            color: #222324;
         }
         .pointing {
            width: 8px;
            height: 12px;
         }
         .downpointing {
            width: 12px;
            height: 7px;
         }
         :deep(.custom-field) {
            padding: 0 !important;
            padding-left: 10px !important;
@@ -1072,20 +201,8 @@
            padding: 0 !important;
         }
         .titketName {
            display: flex;
            align-items: center;
         }
      }
   }
   .upload-link {
      font-family: Source Han Sans CN, Source Han Sans CN;
      font-weight: 400;
      font-size: 12px;
      color: #1d6fe9;
      cursor: pointer;
      text-decoration: underline;
   }
}
</style>