<template>
|
<div class="workDetailContainer">
|
<div class="detailTop">
|
<div class="image-container">
|
<van-swipe class="detailSwipe" :autoplay="3000" indicator-color="#4C85FF">
|
<van-swipe-item v-for="(img, index) in getImageList" :key="index">
|
<van-image class="detailImage" :src="img" fit="cover" width="100%" height="200px"
|
@click="openPreview(index)" preview-visible="false" />
|
</van-swipe-item>
|
</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="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>
|
</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 { 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 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 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('已经是最后一页')
|
}
|
}
|
// 跳转地图
|
const jumpMap = item => {
|
const transmitData = { data: { type: 'jumpMapNav', eventNum: item.event_num } }
|
wx.miniProgram.navigateTo({ url: `/subPackages/workDetail/mapWork/index?currentItem=${item.event_num}` })
|
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)
|
|
})
|
</script>
|
<style lang="scss" scoped>
|
.workDetailContainer {
|
position: relative;
|
|
.required-mark {
|
color: #ff4d4f; // 红色
|
margin-left: 4px;
|
}
|
|
.detailTop {
|
.image-container {
|
position: relative;
|
width: 100%;
|
height: 205px;
|
|
.detailImage {
|
width: 100%;
|
height: 100%;
|
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;
|
}
|
}
|
|
.worderContainer {
|
padding: 0 12px;
|
padding-bottom: 2px;
|
background: #f6f6f6;
|
}
|
|
.workOrderContent {
|
margin-top: 15px;
|
background-color: #fff;
|
border-radius: 6px;
|
padding: 10px;
|
margin-bottom: 17px;
|
|
.workOrderTitle {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
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;
|
min-height: 48px;
|
border-bottom: 1px solid #f5f5f5;
|
color: #7b7b7b;
|
}
|
|
.rowCard {
|
margin-top: 10px;
|
|
min-height: 48px;
|
border-bottom: 1px solid #f5f5f5;
|
color: #7b7b7b;
|
}
|
|
.guanlian {
|
display: flex;
|
}
|
|
.rowTitle {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 15px;
|
color: #222324;
|
white-space: nowrap;
|
|
span {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 10px;
|
color: #3a3a3a;
|
}
|
}
|
|
.addressBox {
|
display: flex;
|
align-items: center;
|
overflow: hidden;
|
}
|
|
.rowAddress {
|
font-size: 14px;
|
color: #1d6fe9;
|
white-space: nowrap;
|
/* 禁止换行 */
|
overflow: hidden;
|
text-overflow: ellipsis;
|
// max-width: 74%;
|
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;
|
}
|
|
:deep(.custom-field .van-field__control) {
|
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>
|