<template>
|
<el-dialog
|
class="gd-dialog"
|
v-model="visible"
|
:title="titleEnum[dialogMode]"
|
@closed="visible = false"
|
destroy-on-close
|
:close-on-click-modal="false"
|
width="80%"
|
>
|
<div class="detail-container" style="display: flex">
|
<div class="processBox">
|
<div class="detail-title">巡查需求记录</div>
|
<div class="detail-left" v-if="dialogMode !== 'add'">
|
<el-timeline class="gd-timeline">
|
<el-timeline-item
|
v-for="(activity, index) in processList"
|
:key="index"
|
:icon="Check"
|
:type="index === processList.length - 1 ? 'success' : 'info'"
|
:color="activity.color"
|
:hollow="activity.hollow"
|
:timestamp="activity.createTime"
|
>
|
<div class="item-content">
|
<div>{{ activity.operator }}</div>
|
<div class="flowName">{{ activity.flowName }}</div>
|
</div>
|
</el-timeline-item>
|
</el-timeline>
|
</div>
|
</div>
|
|
<div class="detail-right">
|
<!-- 查看模式 -->
|
<div class="view-container" v-if="dialogReadonly">
|
<div class="detail-title">巡查任务详情</div>
|
<el-row class="detail-row-view">
|
<el-col :span="12">
|
<div class="label">巡查任务名称</div>
|
<div class="val">{{ formData.patrolTaskName }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">巡查任务类型</div>
|
<div class="val">{{ getTaskTypeLabel(formData.patrolTaskType, workOrderTypeXT) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">任务执行时间</div>
|
<div class="val">{{ formData.executeTime }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">巡查任务航线</div>
|
<div class="val val-long">
|
<el-tooltip :content="getAirName(formData.patrolRouteUrl)" placement="top">
|
{{ getAirName(formData.patrolRouteUrl) }}
|
</el-tooltip>
|
</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">推荐飞手</div>
|
<div class="val">{{ getFlyerName(formData.deviceFlyerId) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">选择设备</div>
|
<div class="val">{{ getDeviceName(formData.deviceId) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">关联工单</div>
|
<div class="val">{{ getWorkOrderName(formData.workOrderId) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">巡查任务描述</div>
|
<div class="val">{{ formData.taskDesc }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">算法</div>
|
<div class="val">{{ getAlgorithmNames(formData.algorithmIds) }}</div>
|
</el-col>
|
</el-row>
|
<template v-if="['6', '7', '8'].includes(taskStatus)">
|
<div class="detail-title" :style="{ marginTop: pxToRem(10) }">
|
任务成果({{ taskResultList.length || 0 }}条)
|
</div>
|
<div class="imgBox">
|
<div
|
v-for="item in taskResultList.filter(
|
item1 => item1.resultUrl && [1, 2, 3].includes(item1.attachmentType)
|
)"
|
>
|
<el-image
|
v-if="item.attachmentType === 1 || item.attachmentType === 2"
|
:src="item.attachmentType === 1 ? item.resultUrl : item.aiImg"
|
:preview-src-list="[item.attachmentType === 1 ? item.resultUrl : item.aiImg]"
|
fit="cover"
|
preview-teleported
|
/>
|
<div class="video-btn" v-if="item.attachmentType === 3" @click="videoClick(item)">
|
<el-icon :size="30" color="#fff">
|
<VideoPlay />
|
</el-icon>
|
</div>
|
</div>
|
</div>
|
</template>
|
</div>
|
|
<!-- 编辑模式 -->
|
<el-form class="gd-dialog-form" v-else ref="formRef" :model="formData" :rules="rules" label-width="130px">
|
<div class="detail-title">巡查任务详情</div>
|
<el-row>
|
<el-col :span="12">
|
<el-form-item label="巡查任务名称" prop="patrolTaskName">
|
<el-input class="gd-input" v-model="formData.patrolTaskName" placeholder="请输入" clearable />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="巡查任务类型" prop="patrolTaskType">
|
<el-cascader
|
class="gd-select"
|
popper-class="gd-select-popper"
|
v-model="formData.patrolTaskType"
|
:options="workOrderTypeXT"
|
:props="{ ...taskTypeCascaderProps, multiple: true }"
|
placeholder="请选择"
|
collapse-tags
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="任务执行时间" prop="executeTime">
|
<el-date-picker
|
class="gd-date-picker"
|
v-model="formData.executeTime"
|
type="datetime"
|
placeholder="请选择"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="巡查任务航线" prop="patrolRouteUrl">
|
<el-select
|
class="gd-select"
|
popper-class="gd-select-popper"
|
v-model="formData.patrolRouteUrl"
|
placeholder="请选择"
|
clearable
|
@change="getAirDetails"
|
>
|
<el-option v-for="item in routeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="推荐飞手" prop="deviceFlyerId">
|
<el-select
|
class="gd-select"
|
popper-class="gd-select-popper"
|
v-model="formData.deviceFlyerId"
|
placeholder="请选择"
|
filterable
|
clearable
|
>
|
<el-option v-for="item in flyerList" :key="item.id" :label="item.flyerName" :value="item.flyerId" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="选择设备" prop="deviceId">
|
<el-select
|
class="gd-select"
|
popper-class="gd-select-popper"
|
v-model="formData.deviceId"
|
placeholder="请选择"
|
filterable
|
clearable
|
>
|
<el-option v-for="item in deviceList" :key="item.id" :label="item.nickname" :value="item.id" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="关联工单">
|
<span>{{ getWorkOrderName(formData.workOrderId) }}</span>
|
</el-form-item>
|
</el-col>
|
<!-- 算法下拉 -->
|
<el-col :span="12">
|
<el-form-item label="算法" prop="algorithmIds">
|
<el-tree-select
|
class="gd-select"
|
popper-class="gd-tree-select-popper"
|
v-model="formData.algorithmIds"
|
:data="algorithmTreeData"
|
:props="{ label: 'name', children: 'children', value: 'id' }"
|
node-key="id"
|
multiple
|
collapse-tags
|
collapse-tags-tooltip
|
check-strictly
|
filterable
|
clearable
|
placeholder="请选择"
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="24">
|
<el-form-item label="巡查任务描述" prop="taskDesc">
|
<el-input
|
class="gd-input-text"
|
type="textarea"
|
:rows="4"
|
v-model="formData.taskDesc"
|
placeholder="请输入"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
|
<div class="detail-title" :style="{ marginTop: pxToRem(10) }">任务航线</div>
|
<!-- 地图组件 -->
|
<CommonCesiumMap
|
ref="mapRef"
|
class="gd-cesium"
|
:active="visible"
|
:flat-mode="false"
|
:terrain="true"
|
:layer-mode="4"
|
:boundary="false"
|
:zoomToBoundary="false"
|
@ready="readyMap"
|
/>
|
</div>
|
</div>
|
|
<template #footer v-if="detailLoaded">
|
<el-button v-if="['1', '4', '7'].includes(taskStatus)" @click="viewDescription" color="#F2F3F5">
|
{{ gdStatusObj[taskStatus].reason }}
|
</el-button>
|
<el-button @click="statusChange(3)" v-if="taskStatus === '3' && permission.flyOrder_revoke" color="#4C34FF">
|
撤回任务
|
</el-button>
|
|
<template v-if="permission.flyOrder_controlAcceptance">
|
<el-button @click="refusalToAccept" v-if="taskStatus === '6'" color="#F2F3F5">拒绝验收</el-button>
|
<el-button @click="statusChange(6)" v-if="taskStatus === '6'" color="#4C34FF">验收通过</el-button>
|
</template>
|
<el-button
|
v-if="!dialogReadonly || (['1', '4'].includes(taskStatus) && permission.flyOrder_add)"
|
:loading="submitting"
|
:disabled="submitting"
|
color="#4C34FF"
|
@click="handleSubmit"
|
>
|
提交
|
</el-button>
|
<template v-if="permission.flyOrder_controlSignFor">
|
<el-button v-if="taskStatus === '0'" @click="addDescription" color="#F2F3F5">拒绝签收</el-button>
|
<el-button v-if="taskStatus === '0'" @click="statusChange(1)" color="#4C34FF">签收</el-button>
|
</template>
|
<template v-if="permission.flyOrder_controlReview">
|
<el-button v-if="taskStatus === '3'" @click="addDescription" color="#F2F3F5">驳回</el-button>
|
<el-button v-if="taskStatus === '3'" @click="statusChange(4)" color="#4C34FF">通过</el-button>
|
</template>
|
</template>
|
<RefuseOrderDialog1
|
ref="refuseOrderDialogRef"
|
v-if="rejectVisible"
|
v-model="rejectVisible"
|
@success="rejectSuccess"
|
/>
|
</el-dialog>
|
|
<VideoPlayDialog
|
ref="videoPlayDialogRef"
|
v-if="VideoShow"
|
v-model="VideoShow"
|
:playUrl="currentVideo.resultUrl"
|
></VideoPlayDialog>
|
</template>
|
|
<script setup>
|
import { computed, ref, onMounted, inject } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import { fieldRules, flyVisual, geomAnalysis, getAiImg } from '@ztzf/utils'
|
import {
|
gdPatrolTaskRepublish,
|
gdFlyerPageApi,
|
gdPatrolTaskAuditApi,
|
gdPatrolTaskDetailApi,
|
} from './inspectionRequestApi'
|
import {
|
gdWorkOrderFlowListApi,
|
gdWorkOrderFlowPatrolListApi,
|
gdWorkOrderDetailApi,
|
} from '../orderManage/orderManageApi'
|
import { gdManageDeviceListApi } from '../orderManage/gdManageDeviceApi'
|
import { pxToRem } from '@/utils/rem'
|
import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
|
import { gdTaskResultListApi } from '@/views/orderView/orderManage/clueEvents/achievementApi'
|
import RefuseOrderDialog1 from '@/views/orderView/orderManage/inspectionRequest/RefuseOrderDialog1.vue'
|
import { Check, VideoPlay } from '@element-plus/icons-vue'
|
import { queryAirById, airlineListApi, algorithmGroupedApi } from '@/api/zkxt'
|
import * as Cesium from 'cesium'
|
import { useStore } from 'vuex'
|
import { getTaskTypeLabel, taskTypeCascaderProps } from '../taskTypeOptions'
|
|
// 初始化表单数据
|
const initForm = () => ({
|
id: null,
|
patrolTaskName: '',
|
patrolTaskType: [],
|
executeTime: '',
|
patrolRouteUrl: '',
|
deviceFlyerId: null,
|
deviceId: null,
|
algorithmIds: [],
|
taskDesc: '',
|
workOrderId: null,
|
})
|
const store = useStore()
|
const permission = computed(() => store.state.user.permission)
|
|
const rejectVisible = ref(false)
|
const mapRef = ref(null)
|
const dictObj = inject('dictObj')
|
const emit = defineEmits(['success', 'refusalAccept'])
|
const formRef = ref(null)
|
const formData = ref(initForm())
|
const visible = defineModel()
|
const dialogMode = ref('view')
|
const submitting = ref(false)
|
const detailLoaded = ref(false)
|
const dialogReadonly = computed(() => dialogMode.value === 'view')
|
const titleEnum = ref({ edit: '编辑', view: '查看' })
|
const taskStatus = computed(() => formData.value.taskStatus)
|
const refuseOrderDialogRef = ref(null)
|
|
const flyerList = ref([])
|
const deviceList = ref([])
|
const workOrderDetail = ref(null) // 工单详情
|
const routeOptions = ref([]) // 航线选项(根据工单范围获取)
|
const getAirName = id => {
|
const item = routeOptions.value.find(item => item.id === id)
|
return item ? item.name : id
|
}
|
|
const algorithmTreeData = ref([]) // 算法树形数据
|
const workOrderTypeXT = inject('workOrderTypeXT', ref([]))
|
|
// 获取算法分组数据
|
async function getAlgorithmList() {
|
try {
|
const res = await algorithmGroupedApi()
|
const list = res?.data?.data ?? []
|
algorithmTreeData.value = list.map(group => ({
|
id: 'group_' + group.type,
|
name: group.type,
|
disabled: true,
|
children: (group.algorithms || []).map(alg => ({
|
id: alg.id,
|
name: alg.name,
|
})),
|
}))
|
} catch (e) {
|
console.error('获取算法列表失败', e)
|
}
|
}
|
|
// 根据 algorithmIds 数组获取算法名称,逗号分割回显
|
function getAlgorithmNames(algorithmIds) {
|
if (!algorithmIds || !algorithmIds.length) return ''
|
const allAlgorithms = algorithmTreeData.value.flatMap(group => group.children || [])
|
return algorithmIds
|
.map(id => {
|
const item = allAlgorithms.find(alg => alg.id === id)
|
return item ? item.name : id
|
})
|
.join(', ')
|
}
|
|
const gdStatusObj = {
|
'0': { reason: '拒绝原因', operationType: '2', title: '拒绝签收' },
|
'1': { reason: '拒绝原因' },
|
'2': { reason: '' },
|
'3': { reason: '驳回原因', operationType: '5', title: '驳回' },
|
'4': { reason: '驳回原因' },
|
'5': { reason: '' },
|
'6': { reason: '拒绝原因' },
|
'7': { reason: '拒绝原因' },
|
'8': { reason: '' },
|
}
|
|
let viewer
|
|
// 校验规则
|
const rules = {
|
patrolTaskName: fieldRules(true, 50),
|
patrolTaskType: fieldRules(true),
|
executeTime: fieldRules(true),
|
patrolRouteUrl: fieldRules(true),
|
deviceFlyerId: fieldRules(true),
|
deviceId: fieldRules(true),
|
}
|
|
function rejectSuccess() {
|
visible.value = false
|
emit('success')
|
}
|
|
// 填写说明
|
function addDescription() {
|
rejectVisible.value = true
|
nextTick(() => {
|
refuseOrderDialogRef.value.open({
|
mode: 'add',
|
row: formData.value,
|
type: gdStatusObj[taskStatus.value].operationType,
|
formLabel: gdStatusObj[taskStatus.value].reason,
|
title: gdStatusObj[taskStatus.value]?.title,
|
})
|
})
|
}
|
// 查看说明
|
function viewDescription() {
|
rejectVisible.value = true
|
nextTick(() => {
|
refuseOrderDialogRef.value.open({
|
mode: 'view',
|
row: formData.value,
|
formLabel: gdStatusObj[taskStatus.value].reason,
|
})
|
})
|
}
|
|
// 获取航线名称
|
function getRouteName(id) {
|
const item = routeOptions.value.find(item => item.id === id)
|
return item ? item.name : id
|
}
|
|
// 获取设备名称
|
function getDeviceName(id) {
|
const item = deviceList.value.find(item => item.id === id)
|
return item ? item.nickname : id
|
}
|
|
// 获取飞手名称
|
function getFlyerName(id) {
|
const item = flyerList.value.find(item => item.flyerId === id)
|
return item ? item.flyerName : id
|
}
|
|
// 获取工单名称
|
function getWorkOrderName(id) {
|
if (workOrderDetail.value?.id === id) return workOrderDetail.value.workOrderName
|
return id
|
}
|
|
// 获取飞手列表
|
async function getFlyerList() {
|
const res = await gdFlyerPageApi({ size: 999, current: 1 })
|
flyerList.value = res?.data?.data?.records ?? []
|
}
|
|
// 操作类型:1.同意签收、2.拒绝签收 、3.撤回任务 、4.同意审核、 5.拒绝审核、 6.验收通过、 7.验收拒绝
|
function statusChange(auditStatus) {
|
gdPatrolTaskAuditApi({ auditStatus, id: formData.value.id }).then(res => {
|
visible.value = false
|
emit('success')
|
})
|
}
|
|
function refusalToAccept() {
|
emit('refusalAccept', formData.value)
|
visible.value = false
|
}
|
|
// 获取设备列表
|
async function getDeviceList() {
|
const res = await gdManageDeviceListApi()
|
deviceList.value = res?.data?.data ?? []
|
}
|
|
const processList = ref([])
|
// 加载时间线list
|
function loadList() {
|
gdWorkOrderFlowPatrolListApi({ workOrderId: formData.value.id, type: '1' }).then(res => {
|
processList.value = res.data.data
|
})
|
}
|
|
// 提交编辑
|
async function handleSubmit() {
|
const isValid = await formRef.value?.validate().catch(() => false)
|
if (!isValid) return
|
submitting.value = true
|
try {
|
await gdPatrolTaskRepublish(formData.value)
|
ElMessage.success('更新成功')
|
visible.value = false
|
emit('success')
|
} finally {
|
submitting.value = false
|
}
|
}
|
|
let taskResultList = ref([])
|
// 获取成果列表
|
async function getTaskResultList() {
|
if (!formData.value?.id) return
|
try {
|
const res = await gdTaskResultListApi({ patrolTaskId: formData.value.id })
|
taskResultList.value = await Promise.all(
|
(res?.data?.data ?? []).map(async item => {
|
if (item.attachmentType !== 2) return item
|
const aiImg = await getAiImg(item.resultUrl, item.geojson)
|
return { ...item, aiImg }
|
})
|
)
|
} finally {
|
}
|
}
|
import { ArrowLineMaterialProperty } from '@/utils/cesium/Material'
|
import OrderStepBar from '@/views/orderView/orderManage/orderManage/OrderStepBar.vue'
|
import VideoPlayDialog from '@/components/VideoPlayDialog.vue'
|
let arrowLineMaterialProperty = new ArrowLineMaterialProperty({
|
color: new Cesium.Color(128 / 255, 215 / 255, 255 / 255, 1),
|
directionColor: new Cesium.Color(1, 1, 1, 1),
|
outlineColor: new Cesium.Color(1, 1, 1, 1),
|
outlineWidth: 0,
|
speed: 5,
|
})
|
// 获取航线详情
|
function getAirDetails() {
|
const dockHeight = formData.value.height
|
queryAirById(formData.value.patrolRouteUrl).then(res => {
|
const { airlineWaypoints, airlineSetting } = res.data.data
|
// 使用空值合并运算符 ?? 或 逻辑或 || 兜底
|
const { globalAirlineHeight = 0, airlineHeightMode } = airlineSetting || {}
|
const relative = airlineHeightMode === 'relativeToStartPoint'
|
const list = airlineWaypoints
|
if (!list.length) return mapRef.value?.flyBoundary()
|
const result = list.map(item => {
|
let height = item?.globalHeight || globalAirlineHeight
|
if (relative) {
|
height = height + Number(dockHeight)
|
}
|
return [Number(item.longitude), Number(item.latitude), height || 0]
|
})
|
viewer.entities.add({
|
polyline: {
|
positions: Cesium.Cartesian3.fromDegreesArrayHeights(result.flat()),
|
width: 4,
|
material: arrowLineMaterialProperty,
|
},
|
})
|
// 渲染起点(蓝色)
|
const startPoint = result[0]
|
viewer.entities.add({
|
position: Cesium.Cartesian3.fromDegrees(Number(startPoint[0]), Number(startPoint[1]), startPoint[2]),
|
point: {
|
pixelSize: 12,
|
color: Cesium.Color.BLUE,
|
outlineColor: Cesium.Color.WHITE,
|
outlineWidth: 2,
|
},
|
})
|
// 渲染终点(红色)
|
const endPoint = result[result.length - 1]
|
viewer.entities.add({
|
position: Cesium.Cartesian3.fromDegrees(Number(endPoint[0]), Number(endPoint[1]), endPoint[2]),
|
point: {
|
pixelSize: 12,
|
color: Cesium.Color.RED,
|
outlineColor: Cesium.Color.WHITE,
|
outlineWidth: 2,
|
},
|
})
|
flyVisual({
|
positionsData: list.map(i => [Number(i.longitude), Number(i.latitude), i.height || 0]),
|
viewer,
|
multiple: 6,
|
})
|
})
|
}
|
|
// 打开弹框
|
async function open({ mode = 'view', row } = {}) {
|
detailLoaded.value = false
|
dialogMode.value = mode
|
|
const res = await gdPatrolTaskDetailApi({ id: row.id })
|
formData.value = { ...initForm(), ...res.data.data }
|
// 确保 algorithmIds 是数组
|
if (formData.value.algorithmIds && typeof formData.value.algorithmIds === 'string') {
|
formData.value.algorithmIds = formData.value.algorithmIds.split(',').filter(Boolean)
|
} else if (!formData.value.algorithmIds) {
|
formData.value.algorithmIds = []
|
}
|
detailLoaded.value = true
|
// 获取算法列表
|
getAlgorithmList()
|
// 获取工单详情并根据geom范围获取航线列表
|
await getWorkOrderDetail(formData.value.workOrderId)
|
;['6', '7', '8'].includes(row.taskStatus) && (await getTaskResultList())
|
loadList()
|
initMap()
|
getAirDetails()
|
}
|
|
// 获取工单详情
|
async function getWorkOrderDetail(workOrderId) {
|
if (!workOrderId) return
|
try {
|
const res = await gdWorkOrderDetailApi({ id: workOrderId })
|
workOrderDetail.value = res?.data?.data ?? null
|
// 根据工单geom范围获取航线列表
|
const geom = workOrderDetail.value?.geom
|
if (!geom) return
|
const coordinates = geomAnalysis(geom)
|
if (!coordinates || !coordinates.length) return
|
const airRes = await airlineListApi(coordinates)
|
routeOptions.value = (airRes.data.data || []).filter(item => item)
|
} catch (e) {
|
console.error('获取工单详情或航线列表失败', e)
|
}
|
}
|
|
// 点击视频
|
let VideoShow = ref(false)
|
let currentVideo = ref({})
|
function videoClick(row) {
|
currentVideo.value = row
|
VideoShow.value = true
|
}
|
|
// 初始化地图实例
|
function initMap() {
|
if (viewer) return
|
const map = mapRef.value?.getMap()
|
viewer = map?.viewer || null
|
}
|
|
onMounted(() => {
|
getFlyerList()
|
getDeviceList()
|
})
|
|
defineExpose({ open })
|
</script>
|
|
<style lang="scss" scoped>
|
/* 时间线样式 */
|
:deep(.gd-timeline) {
|
padding-left: 90px;
|
}
|
|
:deep(.el-timeline-item) {
|
padding-bottom: 20px;
|
.item-content {
|
position: relative;
|
.flowName {
|
width: 72px;
|
position: absolute;
|
left: -120px;
|
top: 0px;
|
}
|
}
|
}
|
.imgBox {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 10px;
|
> div {
|
width: calc((100% - 40px) / 5); /* 5列布局,减去4个10px间隙 */
|
height: 110px;
|
flex-shrink: 0;
|
position: relative;
|
overflow: hidden;
|
border-radius: 4px;
|
cursor: pointer;
|
box-shadow: inset 0 0 0 1px rgba(17, 31, 68, 0.08);
|
transition: box-shadow 0.16s ease;
|
|
&:hover {
|
box-shadow: inset 0 0 0 2px rgba(76, 52, 255, 0.48), 0 8px 20px rgba(76, 52, 255, 0.24);
|
}
|
}
|
.el-image {
|
width: 100%;
|
height: 100%;
|
}
|
.video-btn {
|
width: 100%;
|
height: 100%;
|
position: relative;
|
overflow: hidden;
|
//border: 1px solid #D8D6FF;
|
border-radius: 4px;
|
background: linear-gradient(135deg, rgba(76, 52, 255, 0.14), rgba(76, 52, 255, 0) 48%),
|
linear-gradient(180deg, #f4f5ff 0%, #e9ecff 100%);
|
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.7);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
|
&::before {
|
content: '';
|
position: absolute;
|
inset: 0;
|
background-image: linear-gradient(
|
90deg,
|
rgba(76, 52, 255, 0.05) 0,
|
rgba(76, 52, 255, 0.05) 1px,
|
transparent 1px,
|
transparent 12px
|
);
|
opacity: 0.42;
|
}
|
|
.el-icon {
|
position: relative;
|
z-index: 1;
|
width: 42px;
|
height: 42px;
|
border-radius: 50%;
|
background: rgba(76, 52, 255, 0.72);
|
box-shadow: 0 4px 12px rgba(76, 52, 255, 0.2);
|
}
|
}
|
}
|
:deep(.el-timeline-item__timestamp) {
|
font-size: 12px;
|
color: #999;
|
margin-top: 2px;
|
}
|
|
.processBox {
|
display: flex;
|
flex-direction: column;
|
|
.detail-left {
|
height: 100%;
|
overflow: auto;
|
}
|
}
|
</style>
|