| | |
| | | > |
| | | <div class="content" style="display: flex"> |
| | | <div class="processBox" v-if="dialogMode !== 'add' && processList.length"> |
| | | <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 class="timeline-wrapper"> |
| | | <div v-for="(stage, stageIndex) in processList" :key="stageIndex" class="stage-group"> |
| | | <!-- 大节点 Stage Node --> |
| | | <div class="stage-node"> |
| | | <div class="stage-icon" :class="{ reached: stage.reached }"> |
| | | <el-icon v-if="stage.reached"><Check /></el-icon> |
| | | <span v-else class="stage-index">{{ stageIndex + 1 }}</span> |
| | | </div> |
| | | <span class="stage-name">{{ stage.stageName }}</span> |
| | | </div> |
| | | </el-timeline-item> |
| | | </el-timeline> |
| | | |
| | | <!-- 小节点 Child Nodes --> |
| | | <div class="child-list" v-if="stage.child && stage.child.length"> |
| | | <template v-for="(child, childIndex) in stage.child.filter(c => c.reached)"> |
| | | <div v-if="child.reached" :key="childIndex" class="child-node"> |
| | | <div class="child-left"> |
| | | <span class="child-status">{{ child.statusName }}</span> |
| | | </div> |
| | | <div class="child-dot"></div> |
| | | <div class="child-right"> |
| | | <span class="child-operator">{{ child.operator || '-' }}</span> |
| | | <span class="child-time">{{ child.createTime || '-' }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | </div> |
| | | |
| | | <!-- 连接线 --> |
| | | <div |
| | | class="connector-line" |
| | | v-if="stageIndex < processList.length - 1" |
| | | :class="{ reached: stage.reached }" |
| | | ></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="leftBox"> |
| | | <div v-if="dialogReadonly"> |
| | |
| | | </el-row> |
| | | <div class="detail-title" :style="{ marginTop: pxToRem(20) }">已选设备</div> |
| | | <el-table class="setHeight gd-dialog-table" ref="deviceTableRef" :data="deviceList" row-key="id"> |
| | | <el-table-column type="index" label="序号" /> |
| | | <el-table-column prop="nickname" label="设备名称" /> |
| | | <el-table-column prop="deviceName" label="设备型号" /> |
| | | <el-table-column prop="devicePayload" label="设备负载" /> |
| | |
| | | <el-table-column prop="patrolTaskName" show-overflow-tooltip label="巡查任务名称" /> |
| | | <el-table-column prop="patrolTaskType" show-overflow-tooltip label="巡查任务类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.patrolTaskType, dictObj.patrolTaskType) }} |
| | | {{ getDictLabel(row.patrolTaskType, dictObj.workOrderType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="taskStatus" show-overflow-tooltip label="任务状态"> |
| | |
| | | :disabled="dialogReadonly" |
| | | label-width="90px" |
| | | > |
| | | <div class="detail-title">工单详情</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="工单名称" prop="workOrderName"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="detail-title" :style="{ marginTop: pxToRem(20) }">工单执行范围</div> |
| | | <div class="detail-title" :style="{ marginTop: pxToRem(20) }"> |
| | | <span class="required-star" v-if="!dialogReadonly">*</span> |
| | | 工单执行范围 |
| | | </div> |
| | | <CommonCesiumMap |
| | | ref="mapRef" |
| | | class="gd-cesium" |
| | |
| | | /> |
| | | </div> |
| | | <div class="rightBox" v-if="!dialogReadonly"> |
| | | <div class="detail-title">推荐设备</div> |
| | | <div class="detail-title"> |
| | | <span class="required-star" v-if="!dialogReadonly">*</span> |
| | | 推荐设备 |
| | | </div> |
| | | <el-table |
| | | :empty-text="(formData.deviceLoadDemand && pointList.length) ? '暂无数据' : '请先选择设备需求并在地图上绘制工单范围'" |
| | | class="separateTable" |
| | | :empty-text=" |
| | | formData.deviceLoadDemand && pointList.length ? '暂无数据' : '请先选择设备需求并在地图上绘制工单范围' |
| | | " |
| | | ref="deviceTableRef" |
| | | :data="(formData.deviceLoadDemand && pointList.length) ? deviceList : []" |
| | | :data="formData.deviceLoadDemand && pointList.length ? deviceList : []" |
| | | row-key="id" |
| | | @selection-change="handleDeviceSelectionChange" |
| | | > |
| | |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button |
| | | v-if="['11', '21', '23','31', '60'].includes(gdStatus)" |
| | | @click="viewDescription" |
| | | color="#F2F3F5" |
| | | > |
| | | {{ gdStatusObj[gdStatus].reason }} |
| | | <el-button v-if="['11', '21', '23', '31', '60'].includes(gdStatus)" @click="viewDescription" color="#F2F3F5"> |
| | | {{ gdStatusObj[gdStatus]?.reason }} |
| | | </el-button> |
| | | |
| | | <template v-if="!suddenlyEdit"> |
| | |
| | | <el-button |
| | | color="#4C34FF" |
| | | @click="requestModification" |
| | | v-if="['20'].includes(gdStatus) && permission.order_applyNegotiation" |
| | | v-if="['20'].includes(gdStatus) && permission.order_applyEdit" |
| | | > |
| | | 申请修改 |
| | | </el-button> |
| | |
| | | </template> |
| | | <template v-if="permission.order_controlCancel"> |
| | | <el-button v-if="gdStatus === '21'" @click="statusChange(6)" color="#F2F3F5">驳回</el-button> |
| | | <el-button v-if="gdStatus === '21'" @click="statusChange(5)" color="#4C34FF">同意</el-button> |
| | | <el-button v-if="gdStatus === '21'" @click="statusChange(5)" color="#4C34FF">通过</el-button> |
| | | </template> |
| | | <el-button v-if="gdStatus === '30' && permission.order_applyNegotiation" @click="addDescription" color="#4C34FF"> |
| | | 协商修改 |
| | |
| | | const hasPatrolTaskList = computed(() => ['30', '40', '50', '60'].includes(String(formData.value.workOrderStatus))) |
| | | |
| | | const gdStatusObj = { |
| | | '10': { reason: '驳回原因', operationType: '2' }, |
| | | '11': { reason: '驳回原因' }, |
| | | '20': { reason: '取消原因', operationType: '3' }, |
| | | '10': { reason: '拒单原因', operationType: '2', title: '拒绝接单' }, |
| | | '11': { reason: '拒单原因' }, |
| | | '20': { reason: '原因', operationType: '3', title: '申请取消' }, |
| | | '21': { reason: '取消原因' }, |
| | | '23': { reason: '取消原因' }, |
| | | '30': { reason: '协商修改原因', operationType: '9' }, |
| | | '31': { reason: '协商修改原因' }, |
| | | '30': { reason: '修改原因', operationType: '9', title: '协商修改' }, |
| | | '31': { reason: '修改原因' }, |
| | | '40': { reason: '' }, |
| | | '50': { reason: '情况说明', operationType: '11' }, |
| | | '50': { reason: '情况说明', operationType: '11', title: '结算' }, |
| | | '60': { reason: '情况说明' }, |
| | | } |
| | | |
| | |
| | | row: formData.value, |
| | | type: gdStatusObj[gdStatus.value].operationType, |
| | | formLabel: gdStatusObj[gdStatus.value].reason, |
| | | title: gdStatusObj[gdStatus.value]?.title || '新增', |
| | | }) |
| | | }) |
| | | } |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .el-table{ |
| | | .separateTable { |
| | | height: 0; |
| | | flex: 1; |
| | | :deep(){ |
| | | .el-scrollbar__view{ |
| | | :deep() { |
| | | .el-scrollbar__view { |
| | | height: 100%; |
| | | } |
| | | .el-table__empty-text{ |
| | | .el-table__empty-text { |
| | | line-height: normal; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | .processBox { |
| | | padding: 24px 0; |
| | | padding: 24px 16px; |
| | | width: 312px; |
| | | border: 1px solid #e4e4e4; |
| | | border-radius: 8px; |
| | | overflow: auto; |
| | | background: #fff; |
| | | |
| | | .item-content { |
| | | .timeline-wrapper { |
| | | padding-left: 100px; |
| | | position: relative; |
| | | .flowName { |
| | | width: 80px; |
| | | } |
| | | |
| | | .stage-group { |
| | | position: relative; |
| | | } |
| | | |
| | | // 大节点 - Stage Node |
| | | .stage-node { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | margin-bottom: 8px; |
| | | |
| | | .stage-icon { |
| | | width: 28px; |
| | | height: 28px; |
| | | border-radius: 50%; |
| | | background: #e0e0e0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #fff; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | flex-shrink: 0; |
| | | position: relative; |
| | | z-index: 2; |
| | | |
| | | &.reached { |
| | | background: #1a1a2e; |
| | | } |
| | | |
| | | .el-icon { |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .stage-index { |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | .stage-name { |
| | | width: 70px; |
| | | text-align: right; |
| | | position: absolute; |
| | | left: -120px; |
| | | top: 0px; |
| | | left: -80px; |
| | | font-family: Roboto, Roboto; |
| | | font-weight: bold; |
| | | font-size: 16px; |
| | | color: rgba(0,0,0,0.85); |
| | | } |
| | | } |
| | | |
| | | // 小节点 - Child Nodes |
| | | .child-list { |
| | | position: relative; |
| | | left: -52px; |
| | | } |
| | | |
| | | .child-node { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | position: relative; |
| | | |
| | | |
| | | &:last-child::before { |
| | | bottom: 50%; |
| | | } |
| | | |
| | | .child-left { |
| | | width: 100px; |
| | | flex-shrink: 0; |
| | | text-align: right; |
| | | padding-right: 20px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0,0,0,0.85); |
| | | |
| | | .child-status { |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | |
| | | .child-dot { |
| | | width: 12px; |
| | | height: 12px; |
| | | border-radius: 50%; |
| | | background: #1a1a2e; |
| | | flex-shrink: 0; |
| | | position: relative; |
| | | z-index: 2; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | .child-right { |
| | | flex: 1; |
| | | padding-left: 12px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 2px; |
| | | |
| | | .child-operator { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0,0,0,0.85); |
| | | |
| | | } |
| | | |
| | | .child-time { |
| | | white-space: nowrap; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: rgba(0,0,0,0.45); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 连接线 |
| | | .connector-line { |
| | | position: absolute; |
| | | left: 13px; |
| | | width: 2px; |
| | | height: 100%; |
| | | background: #e0e0e0; |
| | | top: 28px; |
| | | z-index: 1; |
| | | |
| | | &.reached { |
| | | background: #1a1a2e; |
| | | } |
| | | } |
| | | } |
| | |
| | | height: 200px; |
| | | line-height: 200px; |
| | | } |
| | | |
| | | .required-star { |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | </style> |