2777 lines
110 KiB
HTML
2777 lines
110 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>施工操作台- 施工操作台</title>
|
||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
|
||
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.2/dist/echarts.min.js"></script>
|
||
<style>
|
||
/* 基础样式 */
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
|
||
color: #333;
|
||
background-color: #f0f2f5;
|
||
}
|
||
|
||
.app-container {
|
||
display: flex;
|
||
min-height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 侧边栏样式 */
|
||
.sidebar {
|
||
width: 220px;
|
||
background-color: #304156;
|
||
color: #fff;
|
||
transition: width 0.3s;
|
||
flex-shrink: 0;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.sidebar.collapsed {
|
||
width: 64px;
|
||
}
|
||
|
||
.main-content {
|
||
flex: 1;
|
||
padding: 20px;
|
||
overflow-y: auto;
|
||
transition: margin-left 0.3s;
|
||
}
|
||
|
||
.sidebar.collapsed + .main-content {
|
||
margin-left: -156px;
|
||
}
|
||
|
||
.logo {
|
||
padding: 10px 0;
|
||
text-align: center;
|
||
position: relative;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.logo h2 {
|
||
font-size: 18px;
|
||
margin: 5px 0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
padding: 0 10px;
|
||
}
|
||
|
||
.logo p {
|
||
font-size: 12px;
|
||
margin: 0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
padding: 0 10px;
|
||
}
|
||
|
||
.toggle-sidebar {
|
||
position: absolute;
|
||
right: 10px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
cursor: pointer;
|
||
color: #fff;
|
||
}
|
||
|
||
/* 菜单项样式 */
|
||
.el-menu {
|
||
border-right: none;
|
||
background-color: transparent;
|
||
}
|
||
|
||
.el-menu-item, .el-submenu__title {
|
||
color: #fff;
|
||
height: 46px;
|
||
line-height: 46px;
|
||
}
|
||
|
||
.el-menu-item:hover, .el-submenu__title:hover {
|
||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||
}
|
||
|
||
.el-menu-item.is-active {
|
||
background-color: rgba(0, 0, 0, 0.2) !important;
|
||
color: #409EFF !important;
|
||
}
|
||
|
||
.el-submenu .el-menu-item {
|
||
min-width: 0 !important;
|
||
padding-left: 50px !important;
|
||
background-color: #1f2d3d !important;
|
||
}
|
||
|
||
.el-submenu .el-menu-item:hover {
|
||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||
}
|
||
|
||
.el-submenu__title {
|
||
padding-left: 20px !important;
|
||
}
|
||
|
||
.el-menu-item [class^=el-icon-], .el-submenu [class^=el-icon-] {
|
||
margin-right: 10px;
|
||
}
|
||
|
||
/* 二级菜单样式 */
|
||
.el-menu--inline .el-menu-item {
|
||
padding-left: 60px !important;
|
||
}
|
||
|
||
/* 折叠状态下的样式 */
|
||
.sidebar.collapsed .el-submenu__icon-arrow {
|
||
display: none;
|
||
}
|
||
|
||
.sidebar.collapsed .el-submenu > .el-menu {
|
||
display: none;
|
||
}
|
||
|
||
/* 徽标样式 */
|
||
.el-badge {
|
||
position: absolute;
|
||
right: 20px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
.sidebar.collapsed .el-badge {
|
||
right: 5px;
|
||
}
|
||
|
||
/* 用户信息样式 */
|
||
.user-info {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 10px;
|
||
border-top: 1px solid rgba(255,255,255,0.1);
|
||
position: absolute;
|
||
bottom: 0;
|
||
width: 220px;
|
||
background-color: #304156;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 50%;
|
||
margin-right: 10px;
|
||
background-color: #409EFF;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: white;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.user-name {
|
||
flex: 1;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.user-logout {
|
||
cursor: pointer;
|
||
padding: 5px;
|
||
}
|
||
|
||
.sidebar.collapsed .user-info {
|
||
justify-content: center;
|
||
padding: 10px 5px;
|
||
width: 64px;
|
||
}
|
||
|
||
.sidebar.collapsed .user-name,
|
||
.sidebar.collapsed .user-logout {
|
||
display: none;
|
||
}
|
||
|
||
.sidebar.collapsed .user-avatar {
|
||
margin-right: 0;
|
||
}
|
||
|
||
/* 主内容区样式 */
|
||
.module-title {
|
||
margin-bottom: 20px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 1px solid #ebeef5;
|
||
}
|
||
|
||
.card-container {
|
||
background: #fff;
|
||
padding: 20px;
|
||
border-radius: 4px;
|
||
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
/* 实时数据卡片 */
|
||
.real-time-data {
|
||
display: flex;
|
||
margin-bottom: 15px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.data-card {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
margin-right: 15px;
|
||
margin-bottom: 15px;
|
||
padding: 15px;
|
||
background: #fff;
|
||
border-radius: 4px;
|
||
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.data-card:last-child {
|
||
margin-right: 0;
|
||
}
|
||
|
||
.data-title {
|
||
font-size: 14px;
|
||
color: #909399;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.data-value {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.data-unit {
|
||
font-size: 12px;
|
||
color: #909399;
|
||
margin-left: 5px;
|
||
}
|
||
|
||
/* 图表容器 */
|
||
.chart-container {
|
||
height: 300px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
/* 表格样式 */
|
||
.el-table {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
/* 步骤条样式 */
|
||
.process-steps {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
/* 机组列表样式 */
|
||
.turbine-list {
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.turbine-item {
|
||
padding: 15px;
|
||
border-bottom: 1px solid #ebeef5;
|
||
}
|
||
|
||
.turbine-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.turbine-title {
|
||
font-weight: bold;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.blade-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 8px 0;
|
||
border-bottom: 1px dashed #ebeef5;
|
||
}
|
||
|
||
.blade-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.blade-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.blade-status {
|
||
width: 80px;
|
||
text-align: center;
|
||
margin: 0 10px;
|
||
padding: 2px 5px;
|
||
border-radius: 3px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.status-待开始 {
|
||
background-color: #f5f5f5;
|
||
color: #909399;
|
||
}
|
||
|
||
.status-进行中 {
|
||
background-color: #ecf5ff;
|
||
color: #409EFF;
|
||
}
|
||
|
||
.status-已完成 {
|
||
background-color: #f0f9eb;
|
||
color: #67C23A;
|
||
}
|
||
|
||
/* 上传区域样式 */
|
||
.upload-area {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.upload-icon {
|
||
font-size: 50px;
|
||
color: #409EFF;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
/* 报告预览样式 */
|
||
.report-preview {
|
||
border: 1px solid #ebeef5;
|
||
padding: 20px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.report-section {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.report-title {
|
||
font-weight: bold;
|
||
margin-bottom: 10px;
|
||
padding-bottom: 5px;
|
||
border-bottom: 1px solid #ebeef5;
|
||
}
|
||
|
||
.report-content {
|
||
padding: 0 10px;
|
||
}
|
||
|
||
/* 缺陷项样式 */
|
||
.defect-item {
|
||
margin-bottom: 15px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 1px dashed #ebeef5;
|
||
}
|
||
|
||
.defect-title {
|
||
font-weight: bold;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.defect-desc {
|
||
margin-bottom: 10px;
|
||
color: #606266;
|
||
}
|
||
|
||
/* 缺陷图片预览 */
|
||
.defect-images {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.defect-image-preview {
|
||
width: 100px;
|
||
height: 100px;
|
||
margin-right: 10px;
|
||
margin-bottom: 10px;
|
||
border: 1px solid #ebeef5;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.defect-image-preview:hover {
|
||
border-color: #409EFF;
|
||
}
|
||
|
||
/* 图片预览对话框 */
|
||
.image-preview-dialog .el-dialog__body {
|
||
padding: 0;
|
||
}
|
||
|
||
.full-image {
|
||
width: 100%;
|
||
display: block;
|
||
}
|
||
|
||
/* 响应式调整 */
|
||
@media (max-width: 992px) {
|
||
.data-card {
|
||
width: calc(50% - 10px);
|
||
}
|
||
|
||
.data-card:nth-child(2n) {
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.sidebar {
|
||
position: fixed;
|
||
z-index: 1000;
|
||
height: 100vh;
|
||
}
|
||
|
||
.sidebar.collapsed + .main-content {
|
||
margin-left: 0;
|
||
}
|
||
|
||
.main-content {
|
||
margin-left: 220px;
|
||
}
|
||
|
||
.sidebar.collapsed {
|
||
width: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.real-time-data {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.data-card {
|
||
margin-right: 0;
|
||
margin-bottom: 15px;
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="app" class="app-container">
|
||
<!-- 侧边栏导航 - 优化后的版本 -->
|
||
<div class="sidebar" :class="{collapsed: isCollapse}">
|
||
<div class="logo">
|
||
<h2>施工操作台</h2>
|
||
<div class="toggle-sidebar" @click="toggleSidebar">
|
||
<i :class="isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"></i>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 使用Element UI的菜单组件重构导航 -->
|
||
<el-menu
|
||
:default-active="activeModule"
|
||
class="el-menu-vertical"
|
||
:collapse="isCollapse"
|
||
:collapse-transition="false"
|
||
background-color="#304156"
|
||
text-color="#fff"
|
||
active-text-color="#409EFF"
|
||
>
|
||
<!-- 工作台 -->
|
||
<el-menu-item index="dashboard" @click="switchModule('dashboard')">
|
||
<i class="el-icon-data-line"></i>
|
||
<span slot="title">工作台</span>
|
||
</el-menu-item>
|
||
|
||
<!-- 外业施工 - 下拉菜单 -->
|
||
<el-submenu index="fieldwork">
|
||
<template slot="title">
|
||
<i class="el-icon-map-location"></i>
|
||
<span>外业施工</span>
|
||
</template>
|
||
<el-menu-item
|
||
index="fieldwork-project"
|
||
@click="switchModule('fieldwork-project')"
|
||
>
|
||
<span>项目列表</span>
|
||
<el-badge :value="3" :max="99" class="item"></el-badge>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="fieldwork-tools"
|
||
@click="switchModule('fieldwork-tools')"
|
||
>
|
||
<span>现场工艺/装备/软件工具/算法开发</span>
|
||
</el-menu-item>
|
||
</el-submenu>
|
||
|
||
<!-- 数据处理 - 下拉菜单 -->
|
||
<el-submenu index="data">
|
||
<template slot="title">
|
||
<i class="el-icon-upload"></i>
|
||
<span>数据处理</span>
|
||
</template>
|
||
<el-menu-item
|
||
index="data-import"
|
||
@click="switchModule('data-import')"
|
||
>
|
||
<span>数据入库</span>
|
||
</el-menu-item>
|
||
|
||
<!-- 智能巡检平台 - 二级下拉菜单 -->
|
||
<el-submenu index="inspection">
|
||
<template slot="title">智能巡检平台</template>
|
||
<el-menu-item
|
||
index="inspection-defect"
|
||
@click="switchModule('inspection-defect')"
|
||
>
|
||
<span>缺陷检测算法</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="inspection-tree"
|
||
@click="switchModule('inspection-tree')"
|
||
>
|
||
<span>树状可视化管理</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="inspection-standard"
|
||
@click="switchModule('inspection-standard')"
|
||
>
|
||
<span>标准信息库</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="inspection-report"
|
||
@click="switchModule('inspection-report')"
|
||
>
|
||
<span>报告生成</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="inspection-lifecycle"
|
||
@click="switchModule('inspection-lifecycle')"
|
||
>
|
||
<span>全生命周期管理</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="inspection-drone"
|
||
@click="switchModule('inspection-drone')"
|
||
>
|
||
<span>无人机云服务、航线规划、机场管理</span>
|
||
</el-menu-item>
|
||
</el-submenu>
|
||
|
||
<el-menu-item
|
||
index="data-report"
|
||
@click="switchModule('data-report')"
|
||
>
|
||
<span>报告修改审核</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="data-video"
|
||
@click="switchModule('data-video')"
|
||
>
|
||
<span>塔下检测视频</span>
|
||
</el-menu-item>
|
||
</el-submenu>
|
||
|
||
<!-- 项目交付 - 下拉菜单 -->
|
||
<el-submenu index="delivery">
|
||
<template slot="title">
|
||
<i class="el-icon-finished"></i>
|
||
<span>项目交付</span>
|
||
</template>
|
||
<el-menu-item
|
||
index="delivery-reliability"
|
||
@click="switchModule('delivery-reliability')"
|
||
>
|
||
<span>可靠性评估</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="delivery-quality"
|
||
@click="switchModule('delivery-quality')"
|
||
>
|
||
<span>数据质量评估</span>
|
||
</el-menu-item>
|
||
<el-menu-item
|
||
index="delivery-storage"
|
||
@click="switchModule('delivery-storage')"
|
||
>
|
||
<span>质量入库</span>
|
||
</el-menu-item>
|
||
</el-submenu>
|
||
|
||
<!-- 其他(原工具与资源) -->
|
||
<el-menu-item index="others" @click="switchModule('others')">
|
||
<i class="el-icon-set-up"></i>
|
||
<span slot="title">其他</span>
|
||
</el-menu-item>
|
||
</el-menu>
|
||
|
||
<div class="user-info">
|
||
<div class="user-avatar">{{ userInfo.name.substring(0,1) }}</div>
|
||
<div class="user-name">{{ userInfo.name }} ({{ userInfo.role }})</div>
|
||
<div class="user-logout" @click="logout">
|
||
<i class="el-icon-switch-button"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主内容区 -->
|
||
<div class="main-content">
|
||
<!-- 工作台模块 -->
|
||
<div v-if="activeModule === 'dashboard'">
|
||
<h2 class="module-title">工作台</h2>
|
||
|
||
<div class="real-time-data">
|
||
<div class="data-card">
|
||
<div class="data-title">今日检查机组</div>
|
||
<div class="data-value">12<span class="data-unit">台</span></div>
|
||
</div>
|
||
<div class="data-card">
|
||
<div class="data-title">发现缺陷</div>
|
||
<div class="data-value">8<span class="data-unit">处</span></div>
|
||
</div>
|
||
<div class="data-card">
|
||
<div class="data-title">待审核报告</div>
|
||
<div class="data-value">3<span class="data-unit">份</span></div>
|
||
</div>
|
||
<div class="data-card">
|
||
<div class="data-title">设备在线</div>
|
||
<div class="data-value">5/6<span class="data-unit">台</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card-container">
|
||
<el-tabs v-model="dashboardTab">
|
||
<el-tab-pane label="任务进度" name="tasks">
|
||
<div class="chart-container" ref="taskChart"></div>
|
||
|
||
<h3>我的任务</h3>
|
||
<el-table :data="myTasks" border style="width: 100%">
|
||
<el-table-column prop="name" label="任务名称" width="180"></el-table-column>
|
||
<el-table-column prop="project" label="所属项目"></el-table-column>
|
||
<el-table-column prop="progress" label="进度" width="120">
|
||
<template slot-scope="scope">
|
||
<el-progress :percentage="scope.row.progress" :status="scope.row.status"></el-progress>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="deadline" label="截止时间" width="180"></el-table-column>
|
||
<el-table-column label="操作" width="120">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewTaskDetail(scope.row)">查看</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="缺陷统计" name="defects">
|
||
<div class="chart-container" ref="defectChart"></div>
|
||
|
||
<h3>最新缺陷</h3>
|
||
<el-table :data="recentDefects" border style="width: 100%">
|
||
<el-table-column prop="type" label="缺陷类型" width="180"></el-table-column>
|
||
<el-table-column prop="position" label="位置"></el-table-column>
|
||
<el-table-column prop="severity" label="严重程度" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.severity === '高' ? 'danger' : scope.row.severity === '中' ? 'warning' : 'success'">
|
||
{{ scope.row.severity }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="time" label="发现时间" width="180"></el-table-column>
|
||
<el-table-column label="操作" width="120">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewDefectDetail(scope.row)">详情</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="消息通知" name="notifications">
|
||
<el-timeline>
|
||
<el-timeline-item
|
||
v-for="(notification, index) in notifications"
|
||
:key="index"
|
||
:timestamp="notification.time"
|
||
placement="top"
|
||
>
|
||
<el-card>
|
||
<h4>{{ notification.title }}</h4>
|
||
<p>{{ notification.content }}</p>
|
||
<el-button size="mini" v-if="notification.action" @click="handleNotification(notification)">{{ notification.action }}</el-button>
|
||
</el-card>
|
||
</el-timeline-item>
|
||
</el-timeline>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 外业施工 - 项目列表模块 -->
|
||
<div v-if="activeModule === 'fieldwork-project'">
|
||
<h2 class="module-title">项目列表</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="display: flex; justify-content: space-between; margin-bottom: 20px;">
|
||
<el-input
|
||
placeholder="搜索项目名称"
|
||
v-model="projectSearch"
|
||
clearable
|
||
style="width: 300px;"
|
||
>
|
||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||
</el-input>
|
||
|
||
<div>
|
||
<el-button type="primary" icon="el-icon-plus" @click="showProjectDialog">新建项目</el-button>
|
||
<el-button icon="el-icon-refresh" @click="refreshProjects">刷新</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<el-table :data="filteredProjects" border style="width: 100%">
|
||
<el-table-column prop="name" label="项目名称" width="200"></el-table-column>
|
||
<el-table-column prop="turbineCount" label="机组数量" width="100"></el-table-column>
|
||
<el-table-column prop="startDate" label="开始日期" width="150"></el-table-column>
|
||
<el-table-column prop="endDate" label="结束日期" width="150"></el-table-column>
|
||
<el-table-column prop="status" label="状态" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '进行中' ? 'primary' : scope.row.status === '已完成' ? 'success' : 'info'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="progress" label="进度" width="180">
|
||
<template slot-scope="scope">
|
||
<el-progress :percentage="scope.row.progress" :status="scope.row.status === '已完成' ? 'success' : ''"></el-progress>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewProjectDetail(scope.row)">查看</el-button>
|
||
<el-button size="mini" type="primary" @click="editProject(scope.row)">编辑</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 外业施工 - 现场工具模块 -->
|
||
<div v-if="activeModule === 'fieldwork-tools'">
|
||
<h2 class="module-title">现场工艺/装备/软件工具/算法开发</h2>
|
||
|
||
<div class="card-container">
|
||
<el-alert
|
||
title="此功能正在开发中,敬请期待"
|
||
type="info"
|
||
show-icon
|
||
:closable="false"
|
||
>
|
||
</el-alert>
|
||
|
||
<div style="margin-top: 20px; text-align: center;">
|
||
<img src="https://via.placeholder.com/600x300?text=开发中" style="max-width: 100%;">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 数据入库模块 -->
|
||
<div v-if="activeModule === 'data-import'">
|
||
<h2 class="module-title">数据入库 - {{ currentBlade ? currentBlade.position + '叶片' + currentBlade.type + '检查' : '请选择检查项' }}</h2>
|
||
|
||
<div class="card-container" v-if="currentBlade">
|
||
<el-tabs v-model="activeDataType" class="data-type-tabs">
|
||
<el-tab-pane label="图片" name="image"></el-tab-pane>
|
||
<el-tab-pane label="视频" name="video"></el-tab-pane>
|
||
<el-tab-pane label="语音" name="audio"></el-tab-pane>
|
||
<el-tab-pane label="文档" name="document"></el-tab-pane>
|
||
<el-tab-pane label="其他" name="other"></el-tab-pane>
|
||
</el-tabs>
|
||
|
||
<el-upload
|
||
class="upload-area"
|
||
drag
|
||
action=""
|
||
multiple
|
||
:auto-upload="false"
|
||
:on-change="handleFileChange"
|
||
:file-list="fileList"
|
||
:before-upload="beforeUpload"
|
||
:on-remove="handleRemove"
|
||
>
|
||
<i class="el-icon-upload upload-icon"></i>
|
||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||
<div class="el-upload__tip" slot="tip">支持上传{{ activeDataType === 'image' ? 'JPG/PNG/BMP (不超过10MB)' : activeDataType === 'video' ? 'MP4/AVI/MOV (不超过100MB)' : activeDataType === 'audio' ? 'MP3/WAV (不超过20MB)' : activeDataType === 'document' ? 'PDF/DOC/XLS (不超过50MB)' : '任意 (不超过100MB)' }}格式文件</div>
|
||
</el-upload>
|
||
|
||
<div style="margin: 20px 0;">
|
||
<el-button type="primary" @click="submitUpload">开始上传</el-button>
|
||
<el-button @click="clearFiles">清空文件</el-button>
|
||
<el-button type="text" @click="showBatchImportDialog">批量导入...</el-button>
|
||
</div>
|
||
|
||
<h3>已上传数据</h3>
|
||
<el-table :data="uploadedData" border style="width: 100%; margin-bottom: 20px;">
|
||
<el-table-column prop="name" label="文件名" width="200"></el-table-column>
|
||
<el-table-column prop="type" label="类型" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.type === 'image' ? 'primary' : scope.row.type === 'video' ? 'success' : scope.row.type === 'audio' ? 'warning' : 'info'">
|
||
{{ scope.row.type }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="size" label="大小" width="120"></el-table-column>
|
||
<el-table-column prop="time" label="上传时间" width="180"></el-table-column>
|
||
<el-table-column prop="status" label="状态" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '成功' ? 'success' : scope.row.status === '失败' ? 'danger' : 'warning'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="previewFile(scope.row)">预览</el-button>
|
||
<el-button size="mini" type="danger" @click="deleteFile(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<div class="card-container" v-else>
|
||
<el-alert
|
||
title="请先选择要上传数据的检查项"
|
||
type="info"
|
||
show-icon
|
||
:closable="false"
|
||
>
|
||
</el-alert>
|
||
<el-button type="primary" @click="switchModule('fieldwork-project')">返回项目列表</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 智能巡检平台 - 缺陷检测算法模块 -->
|
||
<div v-if="activeModule === 'inspection-defect'">
|
||
<h2 class="module-title">缺陷检测算法</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-button type="primary" @click="runDefectDetection" icon="el-icon-cpu">运行缺陷检测算法</el-button>
|
||
<el-button @click="showDetectionSettings" icon="el-icon-setting">检测设置</el-button>
|
||
<el-button @click="exportDetectionResults" icon="el-icon-download" :disabled="defectDetectionResults.length === 0">导出结果</el-button>
|
||
</div>
|
||
|
||
<div v-if="detectionRunning" style="margin-bottom: 20px;">
|
||
<el-progress :percentage="detectionProgress"></el-progress>
|
||
<div style="margin-top: 10px; color: #909399;">
|
||
正在检测: {{ detectionStatus }}
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="defectDetectionResults.length > 0">
|
||
<h3>检测结果</h3>
|
||
<el-table :data="defectDetectionResults" border style="width: 100%">
|
||
<el-table-column prop="type" label="缺陷类型" width="180"></el-table-column>
|
||
<el-table-column prop="position" label="位置"></el-table-column>
|
||
<el-table-column prop="size" label="尺寸" width="120"></el-table-column>
|
||
<el-table-column prop="severity" label="严重程度" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.severity === '高' ? 'danger' : scope.row.severity === '中' ? 'warning' : 'success'">
|
||
{{ scope.row.severity }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="图片" width="120">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="previewDefectImages(scope.row)">查看({{ scope.row.images.length }})</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewDefectDetail(scope.row)">详情</el-button>
|
||
<el-button size="mini" type="danger" @click="markAsFalseAlarm(scope.row)">误报</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 智能巡检平台 - 树状可视化管理模块 -->
|
||
<div v-if="activeModule === 'inspection-tree'">
|
||
<h2 class="module-title">树状可视化管理</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="height: 600px; display: flex;">
|
||
<div style="width: 300px; border-right: 1px solid #ebeef5; padding-right: 20px; overflow-y: auto;">
|
||
<el-input
|
||
placeholder="搜索机组或叶片"
|
||
v-model="treeSearch"
|
||
clearable
|
||
style="margin-bottom: 15px;"
|
||
>
|
||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||
</el-input>
|
||
|
||
<el-tree
|
||
:data="treeData"
|
||
:props="treeProps"
|
||
node-key="id"
|
||
default-expand-all
|
||
:filter-node-method="filterTreeNode"
|
||
@node-click="handleTreeNodeClick"
|
||
:expand-on-click-node="false"
|
||
>
|
||
<span class="custom-tree-node" slot-scope="{ node, data }">
|
||
<span>
|
||
<i :class="data.type === 'turbine' ? 'el-icon-office-building' : 'el-icon-wind-power'" style="margin-right: 5px;"></i>
|
||
{{ node.label }}
|
||
</span>
|
||
<span v-if="data.type === 'blade' && data.status" style="margin-left: 10px;">
|
||
<el-tag size="mini" :type="data.status === '正常' ? 'success' : 'danger'">
|
||
{{ data.status }}
|
||
</el-tag>
|
||
</span>
|
||
</span>
|
||
</el-tree>
|
||
</div>
|
||
|
||
<div style="flex: 1; padding-left: 20px;">
|
||
<div v-if="selectedTreeNode" style="margin-bottom: 20px;">
|
||
<h3>{{ selectedTreeNode.type === 'turbine' ? '机组' : '叶片' }}详情</h3>
|
||
<el-descriptions :column="2" border>
|
||
<el-descriptions-item label="名称">{{ selectedTreeNode.label }}</el-descriptions-item>
|
||
<el-descriptions-item label="类型">{{ selectedTreeNode.type === 'turbine' ? '机组' : '叶片' }}</el-descriptions-item>
|
||
<el-descriptions-item label="状态" v-if="selectedTreeNode.status">
|
||
<el-tag :type="selectedTreeNode.status === '正常' ? 'success' : 'danger'">
|
||
{{ selectedTreeNode.status }}
|
||
</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="最后检查时间" v-if="selectedTreeNode.lastInspection">
|
||
{{ selectedTreeNode.lastInspection }}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="缺陷数量" v-if="selectedTreeNode.defects">
|
||
{{ selectedTreeNode.defects }}处
|
||
</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<div v-if="selectedTreeNode.type === 'blade' && selectedTreeNode.images" style="margin-top: 20px;">
|
||
<h4>检查图片</h4>
|
||
<div style="display: flex; flex-wrap: wrap;">
|
||
<div
|
||
v-for="(img, index) in selectedTreeNode.images"
|
||
:key="index"
|
||
class="defect-image-preview"
|
||
@click="previewImage(img)"
|
||
>
|
||
<img :src="img.thumbnail" style="width: 100%; height: 100%; object-fit: cover;">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-else style="height: 500px; display: flex; align-items: center; justify-content: center; color: #909399;">
|
||
请从左侧选择机组或叶片查看详情
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 智能巡检平台 - 标准信息库模块 -->
|
||
<div v-if="activeModule === 'inspection-standard'">
|
||
<h2 class="module-title">标准信息库</h2>
|
||
|
||
<div class="card-container">
|
||
<el-tabs v-model="standardTab">
|
||
<el-tab-pane label="缺陷标准" name="defect">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-button type="primary" icon="el-icon-plus" @click="showAddStandardDialog('defect')">新增缺陷标准</el-button>
|
||
<el-button icon="el-icon-download" @click="exportStandards('defect')">导出标准</el-button>
|
||
<el-button icon="el-icon-upload2">导入标准</el-button>
|
||
</div>
|
||
|
||
<el-table :data="defectStandards" border style="width: 100%">
|
||
<el-table-column prop="code" label="缺陷代码" width="120"></el-table-column>
|
||
<el-table-column prop="name" label="缺陷名称" width="180"></el-table-column>
|
||
<el-table-column prop="category" label="缺陷类别" width="120"></el-table-column>
|
||
<el-table-column prop="severity" label="严重程度" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.severity === '高' ? 'danger' : scope.row.severity === '中' ? 'warning' : 'success'">
|
||
{{ scope.row.severity }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="description" label="缺陷描述"></el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="editStandard(scope.row)">编辑</el-button>
|
||
<el-button size="mini" type="danger" @click="deleteStandard(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="检查标准" name="inspection">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-button type="primary" icon="el-icon-plus" @click="showAddStandardDialog('inspection')">新增检查标准</el-button>
|
||
<el-button icon="el-icon-download" @click="exportStandards('inspection')">导出标准</el-button>
|
||
<el-button icon="el-icon-upload2">导入标准</el-button>
|
||
</div>
|
||
|
||
<el-table :data="inspectionStandards" border style="width: 100%">
|
||
<el-table-column prop="code" label="标准代码" width="120"></el-table-column>
|
||
<el-table-column prop="name" label="标准名称" width="180"></el-table-column>
|
||
<el-table-column prop="category" label="适用部位" width="120"></el-table-column>
|
||
<el-table-column prop="method" label="检查方法" width="120"></el-table-column>
|
||
<el-table-column prop="description" label="标准描述"></el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="editStandard(scope.row)">编辑</el-button>
|
||
<el-button size="mini" type="danger" @click="deleteStandard(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="维修标准" name="repair">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-button type="primary" icon="el-icon-plus" @click="showAddStandardDialog('repair')">新增维修标准</el-button>
|
||
<el-button icon="el-icon-download" @click="exportStandards('repair')">导出标准</el-button>
|
||
<el-button icon="el-icon-upload2">导入标准</el-button>
|
||
</div>
|
||
|
||
<el-table :data="repairStandards" border style="width: 100%">
|
||
<el-table-column prop="code" label="标准代码" width="120"></el-table-column>
|
||
<el-table-column prop="name" label="标准名称" width="180"></el-table-column>
|
||
<el-table-column prop="defectType" label="适用缺陷" width="120"></el-table-column>
|
||
<el-table-column prop="method" label="维修方法" width="120"></el-table-column>
|
||
<el-table-column prop="description" label="标准描述"></el-table-column>
|
||
<el-table-column prop="material" label="所需材料" width="180"></el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="editStandard(scope.row)">编辑</el-button>
|
||
<el-button size="mini" type="danger" @click="deleteStandard(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 智能巡检平台 - 报告生成模块 -->
|
||
<div v-if="activeModule === 'inspection-report'">
|
||
<h2 class="module-title">报告生成</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-button type="primary" icon="el-icon-plus" @click="generateNewReport">生成新报告</el-button>
|
||
<el-button icon="el-icon-refresh" @click="refreshReportsList">刷新列表</el-button>
|
||
<el-button icon="el-icon-download" @click="exportAllReports">导出全部</el-button>
|
||
</div>
|
||
|
||
<el-table :data="reportList" border style="width: 100%">
|
||
<el-table-column prop="name" label="报告名称" width="200"></el-table-column>
|
||
<el-table-column prop="project" label="所属项目" width="180"></el-table-column>
|
||
<el-table-column prop="turbine" label="机组编号" width="120"></el-table-column>
|
||
<el-table-column prop="date" label="生成日期" width="150"></el-table-column>
|
||
<el-table-column prop="status" label="状态" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '已发布' ? 'success' : scope.row.status === '待审核' ? 'warning' : 'info'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="250">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewReport(scope.row)">查看</el-button>
|
||
<el-button size="mini" type="primary" @click="editReport(scope.row)">编辑</el-button>
|
||
<el-button size="mini" type="success" @click="publishReport(scope.row)" :disabled="scope.row.status === '已发布'">发布</el-button>
|
||
<el-button size="mini" type="danger" @click="deleteReport(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 报告预览对话框 -->
|
||
<el-dialog title="报告预览" :visible.sync="reportPreviewDialogVisible" width="80%" top="5vh">
|
||
<div class="report-preview" v-if="currentReport">
|
||
<div class="report-section">
|
||
<h2 class="report-title">{{ currentReport.name }}</h2>
|
||
<div class="report-content">
|
||
<p><strong>项目名称:</strong> {{ currentReport.project }}</p>
|
||
<p><strong>机组编号:</strong> {{ currentReport.turbine }}</p>
|
||
<p><strong>检查日期:</strong> {{ currentReport.date }}</p>
|
||
<p><strong>检查人员:</strong> {{ currentReport.inspector }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="report-section">
|
||
<h3 class="report-title">检查概况</h3>
|
||
<div class="report-content">
|
||
<p>{{ currentReport.summary }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="report-section" v-if="currentReport.defects && currentReport.defects.length > 0">
|
||
<h3 class="report-title">缺陷列表</h3>
|
||
<div class="report-content">
|
||
<div class="defect-item" v-for="(defect, index) in currentReport.defects" :key="index">
|
||
<div class="defect-title">{{ defect.code }} - {{ defect.name }} ({{ defect.severity }})</div>
|
||
<div class="defect-desc">{{ defect.description }}</div>
|
||
<div class="defect-images" v-if="defect.images && defect.images.length > 0">
|
||
<img
|
||
v-for="(img, imgIndex) in defect.images"
|
||
:key="imgIndex"
|
||
:src="img.thumbnail"
|
||
class="defect-image-preview"
|
||
@click="previewImage(img.full)"
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="report-section">
|
||
<h3 class="report-title">检查结论</h3>
|
||
<div class="report-content">
|
||
<p>{{ currentReport.conclusion }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="report-section" v-if="currentReport.recommendations">
|
||
<h3 class="report-title">处理建议</h3>
|
||
<div class="report-content">
|
||
<p>{{ currentReport.recommendations }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button @click="reportPreviewDialogVisible = false">关闭</el-button>
|
||
<el-button type="primary" @click="downloadReport(currentReport)">下载报告</el-button>
|
||
</span>
|
||
</el-dialog>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 智能巡检平台 - 全生命周期管理模块 -->
|
||
<div v-if="activeModule === 'inspection-lifecycle'">
|
||
<h2 class="module-title">全生命周期管理</h2>
|
||
|
||
<div class="card-container">
|
||
<el-tabs v-model="lifecycleTab">
|
||
<el-tab-pane label="机组档案" name="turbine">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-input
|
||
placeholder="搜索机组编号或名称"
|
||
v-model="turbineSearch"
|
||
clearable
|
||
style="width: 300px;"
|
||
>
|
||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||
</el-input>
|
||
</div>
|
||
|
||
<el-table :data="filteredTurbines" border style="width: 100%">
|
||
<el-table-column prop="code" label="机组编号" width="120"></el-table-column>
|
||
<el-table-column prop="name" label="机组名称" width="180"></el-table-column>
|
||
<el-table-column prop="type" label="机组类型" width="120"></el-table-column>
|
||
<el-table-column prop="location" label="地理位置"></el-table-column>
|
||
<el-table-column prop="installDate" label="投运日期" width="120"></el-table-column>
|
||
<el-table-column prop="status" label="运行状态" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '运行中' ? 'success' : scope.row.status === '停机' ? 'warning' : 'danger'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewTurbineLifecycle(scope.row)">查看</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="叶片档案" name="blade">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-input
|
||
placeholder="搜索叶片编号或所属机组"
|
||
v-model="bladeSearch"
|
||
clearable
|
||
style="width: 300px;"
|
||
>
|
||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||
</el-input>
|
||
</div>
|
||
|
||
<el-table :data="filteredBlades" border style="width: 100%">
|
||
<el-table-column prop="code" label="叶片编号" width="120"></el-table-column>
|
||
<el-table-column prop="turbine" label="所属机组" width="180"></el-table-column>
|
||
<el-table-column prop="position" label="叶片位置" width="120"></el-table-column>
|
||
<el-table-column prop="type" label="叶片型号" width="120"></el-table-column>
|
||
<el-table-column prop="manufacturer" label="制造商" width="120"></el-table-column>
|
||
<el-table-column prop="status" label="当前状态" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '正常' ? 'success' : 'danger'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewBladeLifecycle(scope.row)">查看</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
|
||
<!-- 机组生命周期详情对话框 -->
|
||
<el-dialog :title="currentTurbine ? currentTurbine.name + ' - 生命周期记录' : '机组生命周期'" :visible.sync="turbineLifecycleDialogVisible" width="80%">
|
||
<div v-if="currentTurbine">
|
||
<el-descriptions :column="3" border style="margin-bottom: 20px;">
|
||
<el-descriptions-item label="机组编号">{{ currentTurbine.code }}</el-descriptions-item>
|
||
<el-descriptions-item label="机组类型">{{ currentTurbine.type }}</el-descriptions-item>
|
||
<el-descriptions-item label="投运日期">{{ currentTurbine.installDate }}</el-descriptions-item>
|
||
<el-descriptions-item label="地理位置">{{ currentTurbine.location }}</el-descriptions-item>
|
||
<el-descriptions-item label="运行状态">
|
||
<el-tag :type="currentTurbine.status === '运行中' ? 'success' : currentTurbine.status === '停机' ? 'warning' : 'danger'">
|
||
{{ currentTurbine.status }}
|
||
</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="累计发电量">{{ currentTurbine.totalPower }} kWh</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<h3 style="margin-bottom: 15px;">生命周期事件</h3>
|
||
<el-timeline>
|
||
<el-timeline-item
|
||
v-for="(event, index) in turbineLifecycleEvents"
|
||
:key="index"
|
||
:timestamp="event.time"
|
||
placement="top"
|
||
:type="event.type === '检查' ? 'primary' : event.type === '维修' ? 'warning' : event.type === '更换' ? 'danger' : 'info'"
|
||
>
|
||
<el-card>
|
||
<h4>{{ event.type }} - {{ event.title }}</h4>
|
||
<p>{{ event.description }}</p>
|
||
<div v-if="event.images && event.images.length > 0" style="margin-top: 10px;">
|
||
<el-image
|
||
v-for="(img, imgIndex) in event.images"
|
||
:key="imgIndex"
|
||
:src="img.thumbnail"
|
||
:preview-src-list="[img.full]"
|
||
style="width: 100px; height: 100px; margin-right: 10px;"
|
||
></el-image>
|
||
</div>
|
||
</el-card>
|
||
</el-timeline-item>
|
||
</el-timeline>
|
||
</div>
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button @click="turbineLifecycleDialogVisible = false">关闭</el-button>
|
||
</span>
|
||
</el-dialog>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 智能巡检平台 - 无人机云服务模块 -->
|
||
<div v-if="activeModule === 'inspection-drone'">
|
||
<h2 class="module-title">无人机云服务、航线规划、机场管理</h2>
|
||
|
||
<div class="card-container">
|
||
<el-alert
|
||
title="此功能正在开发中,敬请期待"
|
||
type="info"
|
||
show-icon
|
||
:closable="false"
|
||
>
|
||
</el-alert>
|
||
|
||
<div style="margin-top: 20px; text-align: center;">
|
||
<img src="https://via.placeholder.com/600x300?text=开发中" style="max-width: 100%;">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 报告修改审核模块 -->
|
||
<div v-if="activeModule === 'data-report'">
|
||
<h2 class="module-title">报告修改审核</h2>
|
||
|
||
<div class="card-container">
|
||
<el-tabs v-model="reportReviewTab">
|
||
<el-tab-pane label="待审核" name="pending">
|
||
<el-table :data="pendingReports" border style="width: 100%">
|
||
<el-table-column prop="name" label="报告名称" width="200"></el-table-column>
|
||
<el-table-column prop="project" label="所属项目" width="180"></el-table-column>
|
||
<el-table-column prop="turbine" label="机组编号" width="120"></el-table-column>
|
||
<el-table-column prop="submitter" label="提交人" width="120"></el-table-column>
|
||
<el-table-column prop="submitTime" label="提交时间" width="180"></el-table-column>
|
||
<el-table-column label="操作" width="250">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="reviewReport(scope.row)">审核</el-button>
|
||
<el-button size="mini" type="primary" @click="viewReport(scope.row)">查看</el-button>
|
||
<el-button size="mini" type="success" @click="approveReport(scope.row)">通过</el-button>
|
||
<el-button size="mini" type="danger" @click="rejectReport(scope.row)">驳回</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="已审核" name="reviewed">
|
||
<el-table :data="reviewedReports" border style="width: 100%">
|
||
<el-table-column prop="name" label="报告名称" width="200"></el-table-column>
|
||
<el-table-column prop="project" label="所属项目" width="180"></el-table-column>
|
||
<el-table-column prop="turbine" label="机组编号" width="120"></el-table-column>
|
||
<el-table-column prop="submitter" label="提交人" width="120"></el-table-column>
|
||
<el-table-column prop="reviewer" label="审核人" width="120"></el-table-column>
|
||
<el-table-column prop="reviewTime" label="审核时间" width="180"></el-table-column>
|
||
<el-table-column prop="status" label="审核结果" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '通过' ? 'success' : 'danger'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="viewReport(scope.row)">查看</el-button>
|
||
<el-button size="mini" type="primary" @click="viewReviewComments(scope.row)">备注</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
|
||
<!-- 报告审核对话框 -->
|
||
<el-dialog title="报告审核" :visible.sync="reportReviewDialogVisible" width="80%">
|
||
<div v-if="currentReviewReport">
|
||
<div class="report-preview">
|
||
<div class="report-section">
|
||
<h2 class="report-title">{{ currentReviewReport.name }}</h2>
|
||
<div class="report-content">
|
||
<p><strong>项目名称:</strong> {{ currentReviewReport.project }}</p>
|
||
<p><strong>机组编号:</strong> {{ currentReviewReport.turbine }}</p>
|
||
<p><strong>检查日期:</strong> {{ currentReviewReport.date }}</p>
|
||
<p><strong>检查人员:</strong> {{ currentReviewReport.inspector }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="report-section" v-if="currentReviewReport.defects && currentReviewReport.defects.length > 0">
|
||
<h3 class="report-title">缺陷列表</h3>
|
||
<div class="report-content">
|
||
<div class="defect-item" v-for="(defect, index) in currentReviewReport.defects" :key="index">
|
||
<div class="defect-title">{{ defect.code }} - {{ defect.name }} ({{ defect.severity }})</div>
|
||
<div class="defect-desc">{{ defect.description }}</div>
|
||
<div class="defect-images" v-if="defect.images && defect.images.length > 0">
|
||
<img
|
||
v-for="(img, imgIndex) in defect.images"
|
||
:key="imgIndex"
|
||
:src="img.thumbnail"
|
||
class="defect-image-preview"
|
||
@click="previewImage(img.full)"
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top: 20px;">
|
||
<h3>审核意见</h3>
|
||
<el-input
|
||
type="textarea"
|
||
:rows="4"
|
||
placeholder="请输入审核意见"
|
||
v-model="reviewComments"
|
||
></el-input>
|
||
</div>
|
||
</div>
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button @click="reportReviewDialogVisible = false">取消</el-button>
|
||
<el-button type="danger" @click="rejectReport(currentReviewReport)">驳回</el-button>
|
||
<el-button type="primary" @click="approveReport(currentReviewReport)">通过</el-button>
|
||
</span>
|
||
</el-dialog>
|
||
</div>
|
||
|
||
<!-- 数据处理 - 塔下检测视频模块 -->
|
||
<div v-if="activeModule === 'data-video'">
|
||
<h2 class="module-title">塔下检测视频</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-input
|
||
placeholder="搜索项目或机组"
|
||
v-model="videoSearch"
|
||
clearable
|
||
style="width: 300px;"
|
||
>
|
||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||
</el-input>
|
||
</div>
|
||
|
||
<el-table :data="filteredVideos" border style="width: 100%">
|
||
<el-table-column prop="name" label="视频名称" width="200"></el-table-column>
|
||
<el-table-column prop="project" label="所属项目" width="180"></el-table-column>
|
||
<el-table-column prop="turbine" label="机组编号" width="120"></el-table-column>
|
||
<el-table-column prop="date" label="拍摄日期" width="150"></el-table-column>
|
||
<el-table-column prop="duration" label="时长" width="100"></el-table-column>
|
||
<el-table-column prop="size" label="文件大小" width="120"></el-table-column>
|
||
<el-table-column label="操作" width="200">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" @click="playVideo(scope.row)">播放</el-button>
|
||
<el-button size="mini" type="primary" @click="analyzeVideo(scope.row)">分析</el-button>
|
||
<el-button size="mini" type="danger" @click="deleteVideo(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 视频播放对话框 -->
|
||
<el-dialog title="视频播放" :visible.sync="videoPlayerDialogVisible" width="70%">
|
||
<video
|
||
v-if="currentVideo"
|
||
controls
|
||
autoplay
|
||
style="width: 100%;"
|
||
>
|
||
<source :src="currentVideo.url" type="video/mp4">
|
||
您的浏览器不支持 HTML5 视频。
|
||
</video>
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button @click="videoPlayerDialogVisible = false">关闭</el-button>
|
||
</span>
|
||
</el-dialog>
|
||
</div>
|
||
|
||
<!-- 项目交付 - 可靠性评估模块 -->
|
||
<div v-if="activeModule === 'delivery-reliability'">
|
||
<h2 class="module-title">可靠性评估</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-select v-model="selectedProject" placeholder="请选择项目" style="width: 300px;">
|
||
<el-option
|
||
v-for="project in projects"
|
||
:key="project.id"
|
||
:label="project.name"
|
||
:value="project.id"
|
||
></el-option>
|
||
</el-select>
|
||
<el-button type="primary" @click="generateReliabilityReport" style="margin-left: 20px;">生成评估报告</el-button>
|
||
</div>
|
||
|
||
<div v-if="reliabilityData" class="chart-container" ref="reliabilityChart"></div>
|
||
|
||
<div v-if="reliabilityData" style="margin-top: 20px;">
|
||
<h3>评估结果</h3>
|
||
<el-table :data="reliabilityData.details" border style="width: 100%">
|
||
<el-table-column prop="turbine" label="机组编号" width="120"></el-table-column>
|
||
<el-table-column prop="score" label="可靠性评分" width="120">
|
||
<template slot-scope="scope">
|
||
<el-rate
|
||
v-model="scope.row.score"
|
||
disabled
|
||
show-score
|
||
text-color="#ff9900"
|
||
score-template="{value} 分"
|
||
></el-rate>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="defectCount" label="缺陷数量" width="120"></el-table-column>
|
||
<el-table-column prop="severity" label="严重程度" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.severity === '高' ? 'danger' : scope.row.severity === '中' ? 'warning' : 'success'">
|
||
{{ scope.row.severity }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="recommendation" label="维护建议"></el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<div v-if="reliabilityData" style="margin-top: 20px;">
|
||
<el-button type="primary" @click="exportReliabilityReport">导出评估报告</el-button>
|
||
<el-button @click="printReliabilityReport">打印</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 项目交付 - 数据质量评估模块 -->
|
||
<div v-if="activeModule === 'delivery-quality'">
|
||
<h2 class="module-title">数据质量评估</h2>
|
||
|
||
<div class="card-container">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-select v-model="selectedProject" placeholder="请选择项目" style="width: 300px;">
|
||
<el-option
|
||
v-for="project in projects"
|
||
:key="project.id"
|
||
:label="project.name"
|
||
:value="project.id"
|
||
></el-option>
|
||
</el-select>
|
||
<el-button type="primary" @click="generateQualityReport" style="margin-left: 20px;">生成质量报告</el-button>
|
||
</div>
|
||
|
||
<div v-if="qualityData" class="chart-container" ref="qualityChart"></div>
|
||
|
||
<div v-if="qualityData" style="margin-top: 20px;">
|
||
<h3>质量评估指标</h3>
|
||
<el-table :data="qualityData.metrics" border style="width: 100%">
|
||
<el-table-column prop="name" label="指标名称" width="180"></el-table-column>
|
||
<el-table-column prop="score" label="评分" width="120">
|
||
<template slot-scope="scope">
|
||
<el-progress :percentage="scope.row.score" :status="scope.row.score >= 90 ? 'success' : scope.row.score >= 70 ? '' : 'exception'"></el-progress>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="description" label="说明"></el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<div v-if="qualityData" style="margin-top: 20px;">
|
||
<h3>改进建议</h3>
|
||
<el-card shadow="never">
|
||
<div v-html="qualityData.suggestions"></div>
|
||
</el-card>
|
||
</div>
|
||
|
||
<div v-if="qualityData" style="margin-top: 20px;">
|
||
<el-button type="primary" @click="exportQualityReport">导出质量报告</el-button>
|
||
<el-button @click="printQualityReport">打印</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 项目交付 - 质量入库模块 -->
|
||
<div v-if="activeModule === 'delivery-storage'">
|
||
<h2 class="module-title">质量入库</h2>
|
||
|
||
<div class="card-container">
|
||
<el-steps :active="storageStep" finish-status="success" style="margin-bottom: 20px;">
|
||
<el-step title="选择项目"></el-step>
|
||
<el-step title="数据验证"></el-step>
|
||
<el-step title="质量检查"></el-step>
|
||
<el-step title="入库完成"></el-step>
|
||
</el-steps>
|
||
|
||
<div v-if="storageStep === 0">
|
||
<h3>选择要入库的项目</h3>
|
||
<el-select v-model="selectedProject" placeholder="请选择项目" style="width: 300px;">
|
||
<el-option
|
||
v-for="project in projects"
|
||
:key="project.id"
|
||
:label="project.name"
|
||
:value="project.id"
|
||
></el-option>
|
||
</el-select>
|
||
<el-button type="primary" @click="checkProjectData" style="margin-left: 20px;">检查数据</el-button>
|
||
</div>
|
||
|
||
<div v-if="storageStep === 1">
|
||
<h3>数据验证结果</h3>
|
||
<el-table :data="storageCheckResults" border style="width: 100%; margin-bottom: 20px;">
|
||
<el-table-column prop="item" label="检查项" width="200"></el-table-column>
|
||
<el-table-column prop="status" label="状态" width="120">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '通过' ? 'success' : 'danger'">
|
||
{{ scope.row.status }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="message" label="说明"></el-table-column>
|
||
</el-table>
|
||
|
||
<el-button type="primary" @click="storageStep = 2" :disabled="!canProceedToNextStep">下一步</el-button>
|
||
</div>
|
||
|
||
<div v-if="storageStep === 2">
|
||
<h3>质量检查</h3>
|
||
<el-form :model="storageForm" label-width="120px">
|
||
<el-form-item label="数据质量评分">
|
||
<el-rate
|
||
v-model="storageForm.qualityScore"
|
||
show-text
|
||
:texts="['很差', '较差', '一般', '良好', '优秀']"
|
||
></el-rate>
|
||
</el-form-item>
|
||
<el-form-item label="入库备注">
|
||
<el-input type="textarea" v-model="storageForm.notes"></el-input>
|
||
</el-form-item>
|
||
<el-form-item label="入库位置">
|
||
<el-select v-model="storageForm.storageLocation" placeholder="请选择入库位置">
|
||
<el-option label="主数据库" value="main"></el-option>
|
||
<el-option label="历史数据库" value="history"></el-option>
|
||
<el-option label="测试数据库" value="test"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<el-button @click="storageStep = 1">上一步</el-button>
|
||
<el-button type="primary" @click="completeStorage">完成入库</el-button>
|
||
</div>
|
||
|
||
<div v-if="storageStep === 3">
|
||
<el-result
|
||
icon="success"
|
||
title="入库成功"
|
||
subTitle="项目数据已成功入库"
|
||
>
|
||
<template slot="extra">
|
||
<el-button type="primary" size="medium" @click="viewStoredData">查看入库数据</el-button>
|
||
<el-button size="medium" @click="storageStep = 0">继续入库</el-button>
|
||
</template>
|
||
</el-result>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 其他模块 -->
|
||
<div v-if="activeModule === 'others'">
|
||
<h2 class="module-title">其他</h2>
|
||
|
||
<div class="card-container">
|
||
<el-tabs v-model="othersTab">
|
||
<el-tab-pane label="系统设置" name="settings">
|
||
<el-form :model="settingsForm" label-width="120px">
|
||
<el-form-item label="主题颜色">
|
||
<el-color-picker v-model="settingsForm.themeColor"></el-color-picker>
|
||
</el-form-item>
|
||
<el-form-item label="通知方式">
|
||
<el-checkbox-group v-model="settingsForm.notificationMethods">
|
||
<el-checkbox label="站内消息" name="type"></el-checkbox>
|
||
<el-checkbox label="电子邮件" name="type"></el-checkbox>
|
||
<el-checkbox label="手机短信" name="type"></el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
<el-form-item label="数据备份">
|
||
<el-switch v-model="settingsForm.autoBackup"></el-switch>
|
||
<span style="margin-left: 10px; color: #909399;">{{ settingsForm.autoBackup ? '已开启' : '已关闭' }}</span>
|
||
</el-form-item>
|
||
<el-form-item label="备份频率">
|
||
<el-select v-model="settingsForm.backupFrequency" :disabled="!settingsForm.autoBackup">
|
||
<el-option label="每天" value="daily"></el-option>
|
||
<el-option label="每周" value="weekly"></el-option>
|
||
<el-option label="每月" value="monthly"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="saveSettings">保存设置</el-button>
|
||
<el-button @click="resetSettings">恢复默认</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="帮助文档" name="help">
|
||
<div style="margin-bottom: 20px;">
|
||
<el-input
|
||
placeholder="搜索帮助内容"
|
||
v-model="helpSearch"
|
||
clearable
|
||
style="width: 300px;"
|
||
>
|
||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||
</el-input>
|
||
</div>
|
||
|
||
<el-collapse v-model="activeHelpItems">
|
||
<el-collapse-item title="如何创建新项目" name="1">
|
||
<div>1. 点击"外业施工" -> "项目列表"</div>
|
||
<div>2. 点击右上角的"新建项目"按钮</div>
|
||
<div>3. 填写项目基本信息并保存</div>
|
||
</el-collapse-item>
|
||
<el-collapse-item title="如何上传检查数据" name="2">
|
||
<div>1. 在项目列表中选择要上传数据的项目</div>
|
||
<div>2. 点击"数据处理" -> "数据入库"</div>
|
||
<div>3. 拖拽或选择要上传的文件</div>
|
||
<div>4. 点击"开始上传"按钮</div>
|
||
</el-collapse-item>
|
||
<el-collapse-item title="如何生成检查报告" name="3">
|
||
<div>1. 确保所有检查数据已上传</div>
|
||
<div>2. 点击"数据处理" -> "报告生成"</div>
|
||
<div>3. 点击"生成新报告"按钮</div>
|
||
<div>4. 填写报告内容并保存</div>
|
||
</el-collapse-item>
|
||
<el-collapse-item title="如何进行可靠性评估" name="4">
|
||
<div>1. 点击"项目交付" -> "可靠性评估"</div>
|
||
<div>2. 选择要评估的项目</div>
|
||
<div>3. 点击"生成评估报告"按钮</div>
|
||
<div>4. 查看评估结果并导出报告</div>
|
||
</el-collapse-item>
|
||
</el-collapse>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="关于系统" name="about">
|
||
<div style="text-align: center; margin: 30px 0;">
|
||
<h3>风电叶片检查智能管理平台</h3>
|
||
<p style="margin: 20px 0; color: #606266;">版本: 2.1.0</p>
|
||
<p style="margin: 20px 0; color: #606266;">© 2023 风电科技股份有限公司 版权所有</p>
|
||
<img src="https://via.placeholder.com/200x100?text=Company+Logo" style="max-width: 200px;">
|
||
</div>
|
||
|
||
<div style="margin-top: 30px;">
|
||
<h4>系统依赖</h4>
|
||
<el-table :data="dependencies" border style="width: 100%">
|
||
<el-table-column prop="name" label="名称" width="200"></el-table-column>
|
||
<el-table-column prop="version" label="版本" width="120"></el-table-column>
|
||
<el-table-column prop="license" label="许可证"></el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 图片预览对话框 -->
|
||
<el-dialog :visible.sync="imagePreviewDialogVisible" class="image-preview-dialog">
|
||
<img :src="previewImageUrl" class="full-image">
|
||
</el-dialog>
|
||
</div>
|
||
|
||
<script>
|
||
new Vue({
|
||
el: '#app',
|
||
data() {
|
||
return {
|
||
isCollapse: false,
|
||
activeModule: 'dashboard',
|
||
dashboardTab: 'tasks',
|
||
standardTab: 'defect',
|
||
lifecycleTab: 'turbine',
|
||
reportReviewTab: 'pending',
|
||
othersTab: 'settings',
|
||
activeDataType: 'image',
|
||
storageStep: 0,
|
||
activeHelpItems: ['1'],
|
||
|
||
// 用户信息
|
||
userInfo: {
|
||
name: '张工程师',
|
||
role: '施工组长'
|
||
},
|
||
|
||
// 工作台数据
|
||
myTasks: [
|
||
{ name: 'A风场1-5号机组检查', project: 'A风场2023年检查', progress: 65, status: 'success', deadline: '2023-11-15' },
|
||
{ name: 'B风场缺陷修复', project: 'B风场维修项目', progress: 30, status: 'exception', deadline: '2023-11-20' },
|
||
{ name: 'C风场数据整理', project: 'C风场年度检查', progress: 90, status: 'success', deadline: '2023-11-10' }
|
||
],
|
||
recentDefects: [
|
||
{ type: '前缘腐蚀', position: '1号机组-2号叶片-叶尖', severity: '高', time: '2023-11-05 14:30' },
|
||
{ type: '后缘开裂', position: '2号机组-3号叶片-中部', severity: '中', time: '2023-11-06 09:15' },
|
||
{ type: '表面划痕', position: '3号机组-1号叶片-根部', severity: '低', time: '2023-11-07 16:45' }
|
||
],
|
||
notifications: [
|
||
{ title: '新任务分配', content: '您有新的检查任务: D风场初步检查', time: '2023-11-08 08:00', action: '查看' },
|
||
{ title: '报告审核通过', content: '您提交的A风场检查报告已通过审核', time: '2023-11-07 17:30' },
|
||
{ title: '系统更新', content: '系统将于今晚23:00进行维护更新,预计耗时2小时', time: '2023-11-07 15:20' }
|
||
],
|
||
|
||
// 项目列表数据
|
||
projectSearch: '',
|
||
projects: [
|
||
{ id: 1, name: 'A风场2023年检查', turbineCount: 15, startDate: '2023-10-01', endDate: '2023-12-31', status: '进行中', progress: 65 },
|
||
{ id: 2, name: 'B风场维修项目', turbineCount: 8, startDate: '2023-09-15', endDate: '2023-11-30', status: '进行中', progress: 45 },
|
||
{ id: 3, name: 'C风场年度检查', turbineCount: 20, startDate: '2023-08-01', endDate: '2023-10-31', status: '已完成', progress: 100 },
|
||
{ id: 4, name: 'D风场初步检查', turbineCount: 12, startDate: '2023-11-10', endDate: '2023-12-15', status: '未开始', progress: 0 }
|
||
],
|
||
|
||
// 数据入库
|
||
currentBlade: {
|
||
position: '1号机组',
|
||
type: 'A型'
|
||
},
|
||
fileList: [],
|
||
uploadedData: [
|
||
{ name: 'IMG_20231105_1430.jpg', type: 'image', size: '3.2MB', time: '2023-11-05 14:32', status: '成功' },
|
||
{ name: 'VID_20231106_0915.mp4', type: 'video', size: '45.6MB', time: '2023-11-06 09:18', status: '成功' },
|
||
{ name: 'IMG_20231107_1645.jpg', type: 'image', size: '2.8MB', time: '2023-11-07 16:48', status: '成功' }
|
||
],
|
||
|
||
// 缺陷检测算法
|
||
detectionRunning: false,
|
||
detectionProgress: 0,
|
||
detectionStatus: '正在初始化...',
|
||
defectDetectionResults: [
|
||
{
|
||
type: '前缘腐蚀',
|
||
position: '1号机组-2号叶片-叶尖',
|
||
size: '15x8mm',
|
||
severity: '高',
|
||
images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+1', full: 'https://via.placeholder.com/800x600?text=Defect+1' },
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+2', full: 'https://via.placeholder.com/800x600?text=Defect+2' }
|
||
]
|
||
},
|
||
{
|
||
type: '后缘开裂',
|
||
position: '2号机组-3号叶片-中部',
|
||
size: '32x5mm',
|
||
severity: '中',
|
||
images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+3', full: 'https://via.placeholder.com/800x600?text=Defect+3' }
|
||
]
|
||
}
|
||
],
|
||
|
||
// 树状可视化管理
|
||
treeSearch: '',
|
||
treeData: [
|
||
{
|
||
id: 1,
|
||
label: 'A风场',
|
||
type: 'farm',
|
||
children: [
|
||
{
|
||
id: 101,
|
||
label: '1号机组',
|
||
type: 'turbine',
|
||
status: '正常',
|
||
lastInspection: '2023-11-05',
|
||
defects: 2,
|
||
children: [
|
||
{ id: 1011, label: '1号叶片', type: 'blade', status: '正常', images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Blade+1', full: 'https://via.placeholder.com/800x600?text=Blade+1' }
|
||
]},
|
||
{ id: 1012, label: '2号叶片', type: 'blade', status: '缺陷', images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Blade+2', full: 'https://via.placeholder.com/800x600?text=Blade+2' },
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Blade+3', full: 'https://via.placeholder.com/800x600?text=Blade+3' }
|
||
]},
|
||
{ id: 1013, label: '3号叶片', type: 'blade', status: '正常', images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Blade+4', full: 'https://via.placeholder.com/800x600?text=Blade+4' }
|
||
]}
|
||
]
|
||
},
|
||
{
|
||
id: 102,
|
||
label: '2号机组',
|
||
type: 'turbine',
|
||
status: '正常',
|
||
lastInspection: '2023-11-06',
|
||
defects: 1,
|
||
children: [
|
||
{ id: 1021, label: '1号叶片', type: 'blade', status: '正常' },
|
||
{ id: 1022, label: '2号叶片', type: 'blade', status: '正常' },
|
||
{ id: 1023, label: '3号叶片', type: 'blade', status: '缺陷' }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 2,
|
||
label: 'B风场',
|
||
type: 'farm',
|
||
children: [
|
||
{
|
||
id: 201,
|
||
label: '1号机组',
|
||
type: 'turbine',
|
||
status: '维修中',
|
||
lastInspection: '2023-10-28',
|
||
defects: 3,
|
||
children: [
|
||
{ id: 2011, label: '1号叶片', type: 'blade', status: '缺陷' },
|
||
{ id: 2012, label: '2号叶片', type: 'blade', status: '维修中' },
|
||
{ id: 2013, label: '3号叶片', type: 'blade', status: '正常' }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
],
|
||
treeProps: {
|
||
label: 'label',
|
||
children: 'children'
|
||
},
|
||
selectedTreeNode: null,
|
||
|
||
// 标准信息库
|
||
defectStandards: [
|
||
{ code: 'DEF001', name: '前缘腐蚀', category: '腐蚀类', severity: '高', description: '叶片前缘因风沙侵蚀导致的材料损失' },
|
||
{ code: 'DEF002', name: '后缘开裂', category: '裂纹类', severity: '中', description: '叶片后缘出现的结构性裂纹' },
|
||
{ code: 'DEF003', name: '表面划痕', category: '损伤类', severity: '低', description: '叶片表面因外力导致的划痕' }
|
||
],
|
||
inspectionStandards: [
|
||
{ code: 'INS001', name: '前缘检查标准', category: '前缘', method: '目视+无人机', description: '前缘腐蚀、损伤的检查标准' },
|
||
{ code: 'INS002', name: '后缘检查标准', category: '后缘', method: '目视+敲击', description: '后缘开裂、分层的检查标准' }
|
||
],
|
||
repairStandards: [
|
||
{ code: 'REP001', name: '前缘腐蚀修复', defectType: '前缘腐蚀', method: '打磨+补漆', description: '前缘腐蚀的标准修复流程', material: '环氧树脂,玻璃纤维布' },
|
||
{ code: 'REP002', name: '后缘开裂修复', defectType: '后缘开裂', method: '注胶+加压', description: '后缘开裂的标准修复流程', material: '结构胶,夹具' }
|
||
],
|
||
|
||
// 报告生成
|
||
reportList: [
|
||
{ name: 'A风场1号机组检查报告', project: 'A风场2023年检查', turbine: 'A-001', date: '2023-11-05', status: '已发布' },
|
||
{ name: 'A风场2号机组检查报告', project: 'A风场2023年检查', turbine: 'A-002', date: '2023-11-06', status: '待审核' },
|
||
{ name: 'B风场1号机组检查报告', project: 'B风场维修项目', turbine: 'B-001', date: '2023-10-28', status: '已发布' }
|
||
],
|
||
currentReport: null,
|
||
reportPreviewDialogVisible: false,
|
||
|
||
// 全生命周期管理
|
||
turbineSearch: '',
|
||
bladeSearch: '',
|
||
turbines: [
|
||
{ code: 'A-001', name: 'A风场1号机组', type: '2.5MW', location: 'A风场东区', installDate: '2020-05-15', status: '运行中', totalPower: '12500000' },
|
||
{ code: 'A-002', name: 'A风场2号机组', type: '2.5MW', location: 'A风场东区', installDate: '2020-05-20', status: '运行中', totalPower: '11800000' },
|
||
{ code: 'B-001', name: 'B风场1号机组', type: '3.0MW', location: 'B风场西区', installDate: '2019-08-10', status: '维修中', totalPower: '9800000' }
|
||
],
|
||
blades: [
|
||
{ code: 'A-001-1', turbine: 'A-001', position: '1号', type: 'B58', manufacturer: '风电科技', status: '正常' },
|
||
{ code: 'A-001-2', turbine: 'A-001', position: '2号', type: 'B58', manufacturer: '风电科技', status: '缺陷' },
|
||
{ code: 'A-001-3', turbine: 'A-001', position: '3号', type: 'B58', manufacturer: '风电科技', status: '正常' },
|
||
{ code: 'B-001-1', turbine: 'B-001', position: '1号', type: 'C62', manufacturer: '绿色能源', status: '维修中' }
|
||
],
|
||
currentTurbine: null,
|
||
turbineLifecycleDialogVisible: false,
|
||
turbineLifecycleEvents: [
|
||
{ time: '2023-11-05', type: '检查', title: '年度例行检查', description: '发现2号叶片前缘腐蚀,需后续维修', images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Inspection+1', full: 'https://via.placeholder.com/800x600?text=Inspection+1' }
|
||
]},
|
||
{ time: '2023-08-12', type: '维修', title: '齿轮箱更换', description: '更换故障齿轮箱,耗时3天', images: [] },
|
||
{ time: '2022-11-20', type: '检查', title: '年度例行检查', description: '机组运行状态良好,无重大缺陷', images: [] },
|
||
{ time: '2020-05-15', type: '投运', title: '机组投运', description: '新机组安装完成并投入运行', images: [] }
|
||
],
|
||
|
||
// 报告修改审核
|
||
pendingReports: [
|
||
{ name: 'A风场2号机组检查报告', project: 'A风场2023年检查', turbine: 'A-002', submitter: '张工程师', submitTime: '2023-11-06 14:30' },
|
||
{ name: 'B风场2号机组检查报告', project: 'B风场维修项目', turbine: 'B-002', submitter: '李技术员', submitTime: '2023-11-07 09:15' }
|
||
],
|
||
reviewedReports: [
|
||
{ name: 'A风场1号机组检查报告', project: 'A风场2023年检查', turbine: 'A-001', submitter: '张工程师', reviewer: '王经理', reviewTime: '2023-11-05 16:45', status: '通过' },
|
||
{ name: 'C风场1号机组检查报告', project: 'C风场年度检查', turbine: 'C-001', submitter: '赵工程师', reviewer: '王经理', reviewTime: '2023-10-30 11:20', status: '驳回' }
|
||
],
|
||
currentReviewReport: null,
|
||
reportReviewDialogVisible: false,
|
||
reviewComments: '',
|
||
|
||
// 塔下检测视频
|
||
videoSearch: '',
|
||
videos: [
|
||
{ name: 'A-001塔下检测', project: 'A风场2023年检查', turbine: 'A-001', date: '2023-11-05', duration: '12:34', size: '156MB', url: 'https://example.com/videos/a001.mp4' },
|
||
{ name: 'A-002塔下检测', project: 'A风场2023年检查', turbine: 'A-002', date: '2023-11-06', duration: '15:20', size: '198MB', url: 'https://example.com/videos/a002.mp4' },
|
||
{ name: 'B-001塔下检测', project: 'B风场维修项目', turbine: 'B-001', date: '2023-10-28', duration: '18:45', size: '245MB', url: 'https://example.com/videos/b001.mp4' }
|
||
],
|
||
currentVideo: null,
|
||
videoPlayerDialogVisible: false,
|
||
|
||
// 可靠性评估
|
||
selectedProject: null,
|
||
reliabilityData: null,
|
||
|
||
// 数据质量评估
|
||
qualityData: null,
|
||
|
||
// 质量入库
|
||
storageCheckResults: [
|
||
{ item: '检查数据完整性', status: '通过', message: '所有必填字段均已填写' },
|
||
{ item: '图片质量检查', status: '通过', message: '所有图片清晰可辨' },
|
||
{ item: '视频质量检查', status: '通过', message: '视频完整且清晰' },
|
||
{ item: '报告一致性检查', status: '通过', message: '报告与数据一致' }
|
||
],
|
||
storageForm: {
|
||
qualityScore: 4,
|
||
notes: '',
|
||
storageLocation: 'main'
|
||
},
|
||
|
||
// 其他-系统设置
|
||
settingsForm: {
|
||
themeColor: '#409EFF',
|
||
notificationMethods: ['站内消息', '电子邮件'],
|
||
autoBackup: true,
|
||
backupFrequency: 'weekly'
|
||
},
|
||
helpSearch: '',
|
||
dependencies: [
|
||
{ name: 'Vue.js', version: '2.6.14', license: 'MIT' },
|
||
{ name: 'Element UI', version: '2.15.9', license: 'MIT' },
|
||
{ name: 'ECharts', version: '5.3.2', license: 'Apache-2.0' }
|
||
],
|
||
|
||
// 图片预览
|
||
previewImageUrl: '',
|
||
imagePreviewDialogVisible: false
|
||
}
|
||
},
|
||
computed: {
|
||
filteredProjects() {
|
||
if (!this.projectSearch) return this.projects;
|
||
return this.projects.filter(project =>
|
||
project.name.toLowerCase().includes(this.projectSearch.toLowerCase())
|
||
);
|
||
},
|
||
filteredTurbines() {
|
||
if (!this.turbineSearch) return this.turbines;
|
||
return this.turbines.filter(turbine =>
|
||
turbine.code.toLowerCase().includes(this.turbineSearch.toLowerCase()) ||
|
||
turbine.name.toLowerCase().includes(this.turbineSearch.toLowerCase())
|
||
);
|
||
},
|
||
filteredBlades() {
|
||
if (!this.bladeSearch) return this.blades;
|
||
return this.blades.filter(blade =>
|
||
blade.code.toLowerCase().includes(this.bladeSearch.toLowerCase()) ||
|
||
blade.turbine.toLowerCase().includes(this.bladeSearch.toLowerCase())
|
||
);
|
||
},
|
||
filteredVideos() {
|
||
if (!this.videoSearch) return this.videos;
|
||
return this.videos.filter(video =>
|
||
video.name.toLowerCase().includes(this.videoSearch.toLowerCase()) ||
|
||
video.project.toLowerCase().includes(this.videoSearch.toLowerCase()) ||
|
||
video.turbine.toLowerCase().includes(this.videoSearch.toLowerCase())
|
||
);
|
||
},
|
||
canProceedToNextStep() {
|
||
return this.storageCheckResults.every(item => item.status === '通过');
|
||
}
|
||
},
|
||
mounted() {
|
||
this.initCharts();
|
||
},
|
||
watch: {
|
||
treeSearch(val) {
|
||
this.$refs.tree.filter(val);
|
||
}
|
||
},
|
||
methods: {
|
||
toggleSidebar() {
|
||
this.isCollapse = !this.isCollapse;
|
||
},
|
||
switchModule(module) {
|
||
this.activeModule = module;
|
||
},
|
||
logout() {
|
||
this.$confirm('确定要退出登录吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.$message({
|
||
type: 'success',
|
||
message: '已退出登录'
|
||
});
|
||
// 实际应用中这里应该跳转到登录页面
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消退出'
|
||
});
|
||
});
|
||
},
|
||
|
||
// 工作台方法
|
||
initCharts() {
|
||
// 任务进度图表
|
||
const taskChart = echarts.init(this.$refs.taskChart);
|
||
taskChart.setOption({
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'shadow'
|
||
}
|
||
},
|
||
legend: {
|
||
data: ['已完成', '进行中', '未开始']
|
||
},
|
||
grid: {
|
||
left: '3%',
|
||
right: '4%',
|
||
bottom: '3%',
|
||
containLabel: true
|
||
},
|
||
xAxis: {
|
||
type: 'value'
|
||
},
|
||
yAxis: {
|
||
type: 'category',
|
||
data: ['A风场', 'B风场', 'C风场', 'D风场']
|
||
},
|
||
series: [
|
||
{
|
||
name: '已完成',
|
||
type: 'bar',
|
||
stack: 'total',
|
||
label: {
|
||
show: true
|
||
},
|
||
emphasis: {
|
||
focus: 'series'
|
||
},
|
||
data: [320, 120, 200, 0],
|
||
itemStyle: {
|
||
color: '#67C23A'
|
||
}
|
||
},
|
||
{
|
||
name: '进行中',
|
||
type: 'bar',
|
||
stack: 'total',
|
||
label: {
|
||
show: true
|
||
},
|
||
emphasis: {
|
||
focus: 'series'
|
||
},
|
||
data: [80, 180, 0, 0],
|
||
itemStyle: {
|
||
color: '#409EFF'
|
||
}
|
||
},
|
||
{
|
||
name: '未开始',
|
||
type: 'bar',
|
||
stack: 'total',
|
||
label: {
|
||
show: true
|
||
},
|
||
emphasis: {
|
||
focus: 'series'
|
||
},
|
||
data: [0, 0, 0, 400],
|
||
itemStyle: {
|
||
color: '#909399'
|
||
}
|
||
}
|
||
]
|
||
});
|
||
|
||
// 缺陷统计图表
|
||
const defectChart = echarts.init(this.$refs.defectChart);
|
||
defectChart.setOption({
|
||
tooltip: {
|
||
trigger: 'item'
|
||
},
|
||
legend: {
|
||
top: '5%',
|
||
left: 'center'
|
||
},
|
||
series: [
|
||
{
|
||
name: '缺陷类型',
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
avoidLabelOverlap: false,
|
||
itemStyle: {
|
||
borderRadius: 10,
|
||
borderColor: '#fff',
|
||
borderWidth: 2
|
||
},
|
||
label: {
|
||
show: false,
|
||
position: 'center'
|
||
},
|
||
emphasis: {
|
||
label: {
|
||
show: true,
|
||
fontSize: '18',
|
||
fontWeight: 'bold'
|
||
}
|
||
},
|
||
labelLine: {
|
||
show: false
|
||
},
|
||
data: [
|
||
{ value: 12, name: '前缘腐蚀' },
|
||
{ value: 8, name: '后缘开裂' },
|
||
{ value: 5, name: '表面划痕' },
|
||
{ value: 3, name: '雷击损伤' },
|
||
{ value: 2, name: '其他缺陷' }
|
||
]
|
||
}
|
||
]
|
||
});
|
||
},
|
||
viewTaskDetail(task) {
|
||
this.$message(`查看任务: ${task.name}`);
|
||
},
|
||
viewDefectDetail(defect) {
|
||
this.$message(`查看缺陷: ${defect.type} (${defect.position})`);
|
||
},
|
||
handleNotification(notification) {
|
||
this.$message(`处理通知: ${notification.title}`);
|
||
},
|
||
|
||
// 项目列表方法
|
||
showProjectDialog() {
|
||
this.$message('显示新建项目对话框');
|
||
},
|
||
refreshProjects() {
|
||
this.$message('刷新项目列表');
|
||
},
|
||
viewProjectDetail(project) {
|
||
this.$message(`查看项目: ${project.name}`);
|
||
},
|
||
editProject(project) {
|
||
this.$message(`编辑项目: ${project.name}`);
|
||
},
|
||
|
||
// 数据入库方法
|
||
handleFileChange(file, fileList) {
|
||
this.fileList = fileList;
|
||
},
|
||
beforeUpload(file) {
|
||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||
if (!isLt10M) {
|
||
this.$message.error('上传文件大小不能超过 10MB!');
|
||
}
|
||
return isLt10M;
|
||
},
|
||
handleRemove(file, fileList) {
|
||
this.fileList = fileList;
|
||
},
|
||
submitUpload() {
|
||
if (this.fileList.length === 0) {
|
||
this.$message.warning('请先选择要上传的文件');
|
||
return;
|
||
}
|
||
|
||
this.$message.success('开始上传文件');
|
||
// 模拟上传进度
|
||
let progress = 0;
|
||
const interval = setInterval(() => {
|
||
progress += Math.random() * 10;
|
||
if (progress >= 100) {
|
||
clearInterval(interval);
|
||
this.$message.success('文件上传成功');
|
||
// 添加到已上传数据列表
|
||
this.fileList.forEach(file => {
|
||
this.uploadedData.unshift({
|
||
name: file.name,
|
||
type: this.activeDataType,
|
||
size: (file.size / 1024 / 1024).toFixed(1) + 'MB',
|
||
time: new Date().toLocaleString(),
|
||
status: '成功'
|
||
});
|
||
});
|
||
this.fileList = [];
|
||
}
|
||
}, 300);
|
||
},
|
||
clearFiles() {
|
||
this.fileList = [];
|
||
},
|
||
showBatchImportDialog() {
|
||
this.$message('显示批量导入对话框');
|
||
},
|
||
previewFile(file) {
|
||
this.$message(`预览文件: ${file.name}`);
|
||
},
|
||
deleteFile(file) {
|
||
this.$confirm(`确定要删除文件 ${file.name} 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.uploadedData = this.uploadedData.filter(item => item.name !== file.name);
|
||
this.$message({
|
||
type: 'success',
|
||
message: '删除成功!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消删除'
|
||
});
|
||
});
|
||
},
|
||
|
||
// 缺陷检测算法方法
|
||
runDefectDetection() {
|
||
this.detectionRunning = true;
|
||
this.detectionProgress = 0;
|
||
this.detectionStatus = '正在初始化...';
|
||
|
||
const statusMessages = [
|
||
'加载图像数据...',
|
||
'预处理图像...',
|
||
'运行缺陷检测算法...',
|
||
'分析检测结果...',
|
||
'生成报告...'
|
||
];
|
||
|
||
const interval = setInterval(() => {
|
||
this.detectionProgress += Math.random() * 10;
|
||
if (this.detectionProgress >= 100) {
|
||
clearInterval(interval);
|
||
this.detectionStatus = '检测完成';
|
||
setTimeout(() => {
|
||
this.detectionRunning = false;
|
||
this.$message.success('缺陷检测完成');
|
||
}, 500);
|
||
} else {
|
||
const statusIndex = Math.min(
|
||
Math.floor(this.detectionProgress / 20),
|
||
statusMessages.length - 1
|
||
);
|
||
this.detectionStatus = statusMessages[statusIndex];
|
||
}
|
||
}, 500);
|
||
},
|
||
showDetectionSettings() {
|
||
this.$message('显示检测设置对话框');
|
||
},
|
||
exportDetectionResults() {
|
||
this.$message('导出检测结果');
|
||
},
|
||
previewDefectImages(defect) {
|
||
this.previewImageUrl = defect.images[0].full;
|
||
this.imagePreviewDialogVisible = true;
|
||
},
|
||
markAsFalseAlarm(defect) {
|
||
this.$confirm(`确定要将 ${defect.type} 标记为误报吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.defectDetectionResults = this.defectDetectionResults.filter(item => item !== defect);
|
||
this.$message({
|
||
type: 'success',
|
||
message: '已标记为误报!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消操作'
|
||
});
|
||
});
|
||
},
|
||
|
||
// 树状可视化管理方法
|
||
filterTreeNode(value, data) {
|
||
if (!value) return true;
|
||
return data.label.indexOf(value) !== -1;
|
||
},
|
||
handleTreeNodeClick(data) {
|
||
this.selectedTreeNode = data;
|
||
},
|
||
previewImage(url) {
|
||
this.previewImageUrl = url;
|
||
this.imagePreviewDialogVisible = true;
|
||
},
|
||
|
||
// 标准信息库方法
|
||
showAddStandardDialog(type) {
|
||
this.$message(`显示新增${type === 'defect' ? '缺陷' : type === 'inspection' ? '检查' : '维修'}标准对话框`);
|
||
},
|
||
exportStandards(type) {
|
||
this.$message(`导出${type === 'defect' ? '缺陷' : type === 'inspection' ? '检查' : '维修'}标准`);
|
||
},
|
||
editStandard(standard) {
|
||
this.$message(`编辑标准: ${standard.name}`);
|
||
},
|
||
deleteStandard(standard) {
|
||
this.$confirm(`确定要删除标准 ${standard.name} 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
if (this.standardTab === 'defect') {
|
||
this.defectStandards = this.defectStandards.filter(item => item.code !== standard.code);
|
||
} else if (this.standardTab === 'inspection') {
|
||
this.inspectionStandards = this.inspectionStandards.filter(item => item.code !== standard.code);
|
||
} else {
|
||
this.repairStandards = this.repairStandards.filter(item => item.code !== standard.code);
|
||
}
|
||
this.$message({
|
||
type: 'success',
|
||
message: '删除成功!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消删除'
|
||
});
|
||
});
|
||
},
|
||
|
||
// 报告生成方法
|
||
generateNewReport() {
|
||
this.$message('生成新报告');
|
||
},
|
||
refreshReportsList() {
|
||
this.$message('刷新报告列表');
|
||
},
|
||
exportAllReports() {
|
||
this.$message('导出全部报告');
|
||
},
|
||
viewReport(report) {
|
||
this.currentReport = {
|
||
name: report.name,
|
||
project: report.project,
|
||
turbine: report.turbine,
|
||
date: report.date,
|
||
inspector: '张工程师',
|
||
summary: '本次检查共发现3处缺陷,其中1处为严重缺陷,需要尽快处理。',
|
||
defects: [
|
||
{
|
||
code: 'DEF001',
|
||
name: '前缘腐蚀',
|
||
severity: '高',
|
||
description: '叶片前缘有明显腐蚀痕迹,面积约15x8mm',
|
||
images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+1', full: 'https://via.placeholder.com/800x600?text=Defect+1' }
|
||
]
|
||
},
|
||
{
|
||
code: 'DEF002',
|
||
name: '后缘开裂',
|
||
severity: '中',
|
||
description: '叶片后缘有细小裂纹,长度约32mm',
|
||
images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+2', full: 'https://via.placeholder.com/800x600?text=Defect+2' }
|
||
]
|
||
}
|
||
],
|
||
conclusion: '机组整体状况良好,但存在两处需要关注的缺陷。',
|
||
recommendations: '建议在下次停机时对1号叶片前缘腐蚀进行修复处理,并持续观察2号叶片后缘开裂情况。'
|
||
};
|
||
this.reportPreviewDialogVisible = true;
|
||
},
|
||
editReport(report) {
|
||
this.$message(`编辑报告: ${report.name}`);
|
||
},
|
||
publishReport(report) {
|
||
this.$confirm(`确定要发布报告 ${report.name} 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
report.status = '已发布';
|
||
this.$message({
|
||
type: 'success',
|
||
message: '报告已发布!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消发布'
|
||
});
|
||
});
|
||
},
|
||
deleteReport(report) {
|
||
this.$confirm(`确定要删除报告 ${report.name} 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.reportList = this.reportList.filter(item => item.name !== report.name);
|
||
this.$message({
|
||
type: 'success',
|
||
message: '删除成功!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消删除'
|
||
});
|
||
});
|
||
},
|
||
downloadReport(report) {
|
||
this.$message(`下载报告: ${report.name}`);
|
||
this.reportPreviewDialogVisible = false;
|
||
},
|
||
|
||
// 全生命周期管理方法
|
||
viewTurbineLifecycle(turbine) {
|
||
this.currentTurbine = turbine;
|
||
this.turbineLifecycleDialogVisible = true;
|
||
},
|
||
viewBladeLifecycle(blade) {
|
||
this.$message(`查看叶片生命周期: ${blade.code}`);
|
||
},
|
||
|
||
// 报告修改审核方法
|
||
reviewReport(report) {
|
||
this.currentReviewReport = {
|
||
name: report.name,
|
||
project: report.project,
|
||
turbine: report.turbine,
|
||
date: report.date,
|
||
inspector: '张工程师',
|
||
defects: [
|
||
{
|
||
code: 'DEF001',
|
||
name: '前缘腐蚀',
|
||
severity: '高',
|
||
description: '叶片前缘有明显腐蚀痕迹,面积约15x8mm',
|
||
images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+1', full: 'https://via.placeholder.com/800x600?text=Defect+1' }
|
||
]
|
||
},
|
||
{
|
||
code: 'DEF002',
|
||
name: '后缘开裂',
|
||
severity: '中',
|
||
description: '叶片后缘有细小裂纹,长度约32mm',
|
||
images: [
|
||
{ thumbnail: 'https://via.placeholder.com/100x100?text=Defect+2', full: 'https://via.placeholder.com/800x600?text=Defect+2' }
|
||
]
|
||
}
|
||
]
|
||
};
|
||
this.reportReviewDialogVisible = true;
|
||
},
|
||
approveReport(report) {
|
||
this.$confirm(`确定要通过报告 ${report.name} 的审核吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.pendingReports = this.pendingReports.filter(item => item.name !== report.name);
|
||
this.reviewedReports.unshift({
|
||
name: report.name,
|
||
project: report.project,
|
||
turbine: report.turbine,
|
||
submitter: '张工程师',
|
||
reviewer: this.userInfo.name,
|
||
reviewTime: new Date().toLocaleString(),
|
||
status: '通过'
|
||
});
|
||
this.reportReviewDialogVisible = false;
|
||
this.$message({
|
||
type: 'success',
|
||
message: '报告审核通过!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消操作'
|
||
});
|
||
});
|
||
},
|
||
rejectReport(report) {
|
||
this.$confirm(`确定要驳回报告 ${report.name} 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.pendingReports = this.pendingReports.filter(item => item.name !== report.name);
|
||
this.reviewedReports.unshift({
|
||
name: report.name,
|
||
project: report.project,
|
||
turbine: report.turbine,
|
||
submitter: '张工程师',
|
||
reviewer: this.userInfo.name,
|
||
reviewTime: new Date().toLocaleString(),
|
||
status: '驳回'
|
||
});
|
||
this.reportReviewDialogVisible = false;
|
||
this.$message({
|
||
type: 'success',
|
||
message: '报告已驳回!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消操作'
|
||
});
|
||
});
|
||
},
|
||
viewReviewComments(report) {
|
||
this.$message(`查看审核备注: ${report.name}`);
|
||
},
|
||
|
||
// 塔下检测视频方法
|
||
playVideo(video) {
|
||
this.currentVideo = video;
|
||
this.videoPlayerDialogVisible = true;
|
||
},
|
||
analyzeVideo(video) {
|
||
this.$message(`分析视频: ${video.name}`);
|
||
},
|
||
deleteVideo(video) {
|
||
this.$confirm(`确定要删除视频 ${video.name} 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.videos = this.videos.filter(item => item.name !== video.name);
|
||
this.$message({
|
||
type: 'success',
|
||
message: '删除成功!'
|
||
});
|
||
}).catch(() => {
|
||
this.$message({
|
||
type: 'info',
|
||
message: '已取消删除'
|
||
});
|
||
});
|
||
},
|
||
|
||
// 可靠性评估方法
|
||
generateReliabilityReport() {
|
||
if (!this.selectedProject) {
|
||
this.$message.warning('请先选择项目');
|
||
return;
|
||
}
|
||
|
||
this.reliabilityData = {
|
||
project: this.projects.find(p => p.id === this.selectedProject).name,
|
||
score: 82,
|
||
details: [
|
||
{ turbine: 'A-001', score: 85, defectCount: 2, severity: '中', recommendation: '建议在下次停机时修复前缘腐蚀' },
|
||
{ turbine: 'A-002', score: 90, defectCount: 1, severity: '低', recommendation: '持续观察后缘开裂情况' },
|
||
{ turbine: 'A-003', score: 95, defectCount: 0, severity: '无', recommendation: '机组状况良好,无需特别处理' }
|
||
]
|
||
};
|
||
|
||
// 初始化图表
|
||
this.$nextTick(() => {
|
||
const chart = echarts.init(this.$refs.reliabilityChart);
|
||
chart.setOption({
|
||
title: {
|
||
text: '机组可靠性评分',
|
||
left: 'center'
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'shadow'
|
||
}
|
||
},
|
||
grid: {
|
||
left: '3%',
|
||
right: '4%',
|
||
bottom: '3%',
|
||
containLabel: true
|
||
},
|
||
xAxis: {
|
||
type: 'value',
|
||
max: 100,
|
||
axisLabel: {
|
||
formatter: '{value} 分'
|
||
}
|
||
},
|
||
yAxis: {
|
||
type: 'category',
|
||
data: this.reliabilityData.details.map(item => item.turbine)
|
||
},
|
||
series: [
|
||
{
|
||
name: '可靠性评分',
|
||
type: 'bar',
|
||
data: this.reliabilityData.details.map(item => ({
|
||
value: item.score,
|
||
itemStyle: {
|
||
color: item.score >= 90 ? '#67C23A' : item.score >= 70 ? '#409EFF' : '#F56C6C'
|
||
}
|
||
})),
|
||
label: {
|
||
show: true,
|
||
position: 'right',
|
||
formatter: '{c} 分'
|
||
}
|
||
}
|
||
]
|
||
});
|
||
});
|
||
},
|
||
exportReliabilityReport() {
|
||
this.$message('导出可靠性评估报告');
|
||
},
|
||
printReliabilityReport() {
|
||
this.$message('打印可靠性评估报告');
|
||
},
|
||
|
||
// 数据质量评估方法
|
||
generateQualityReport() {
|
||
if (!this.selectedProject) {
|
||
this.$message.warning('请先选择项目');
|
||
return;
|
||
}
|
||
|
||
this.qualityData = {
|
||
project: this.projects.find(p => p.id === this.selectedProject).name,
|
||
score: 88,
|
||
metrics: [
|
||
{ name: '数据完整性', score: 95, description: '所有必填字段均已填写' },
|
||
{ name: '数据准确性', score: 90, description: '数据与实际情况基本一致' },
|
||
{ name: '数据一致性', score: 85, description: '各数据源之间无明显矛盾' },
|
||
{ name: '数据及时性', score: 80, description: '数据采集和录入略有延迟' },
|
||
{ name: '数据可用性', score: 90, description: '数据可直接用于分析和决策' }
|
||
],
|
||
suggestions: `
|
||
<p><strong>改进建议:</strong></p>
|
||
<ul>
|
||
<li>加强数据采集的及时性,尽量在检查完成后24小时内完成数据录入</li>
|
||
<li>对检查人员进行数据一致性培训,减少不同人员记录方式的差异</li>
|
||
<li>建立数据质量检查机制,在数据入库前进行自动校验</li>
|
||
</ul>
|
||
`
|
||
};
|
||
|
||
// 初始化图表
|
||
this.$nextTick(() => {
|
||
const chart = echarts.init(this.$refs.qualityChart);
|
||
chart.setOption({
|
||
title: {
|
||
text: '数据质量评估雷达图',
|
||
left: 'center'
|
||
},
|
||
tooltip: {},
|
||
radar: {
|
||
indicator: this.qualityData.metrics.map(item => ({
|
||
name: item.name,
|
||
max: 100
|
||
})),
|
||
radius: '65%'
|
||
},
|
||
series: [{
|
||
type: 'radar',
|
||
data: [{
|
||
value: this.qualityData.metrics.map(item => item.score),
|
||
name: '数据质量评分',
|
||
areaStyle: {
|
||
color: 'rgba(64, 158, 255, 0.5)'
|
||
}
|
||
}]
|
||
}]
|
||
});
|
||
});
|
||
},
|
||
exportQualityReport() {
|
||
this.$message('导出数据质量评估报告');
|
||
},
|
||
printQualityReport() {
|
||
this.$message('打印数据质量评估报告');
|
||
},
|
||
|
||
// 质量入库方法
|
||
checkProjectData() {
|
||
if (!this.selectedProject) {
|
||
this.$message.warning('请先选择项目');
|
||
return;
|
||
}
|
||
|
||
this.storageStep = 1;
|
||
},
|
||
completeStorage() {
|
||
this.storageStep = 3;
|
||
this.$message.success('项目数据入库成功');
|
||
},
|
||
viewStoredData() {
|
||
this.$message('查看入库数据');
|
||
this.storageStep = 0;
|
||
},
|
||
|
||
// 系统设置方法
|
||
saveSettings() {
|
||
this.$message.success('系统设置已保存');
|
||
},
|
||
resetSettings() {
|
||
this.settingsForm = {
|
||
themeColor: '#409EFF',
|
||
notificationMethods: ['站内消息', '电子邮件'],
|
||
autoBackup: true,
|
||
backupFrequency: 'weekly'
|
||
};
|
||
this.$message.success('已恢复默认设置');
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|