This commit is contained in:
2025-09-15 10:00:46 +08:00
23 changed files with 1274 additions and 103 deletions

View File

@ -18,6 +18,9 @@ VITE_APP_BASE_API = 'http://192.168.110.180:8899'
# VITE_APP_BASE_API = 'http://192.168.110.149:8899'
#曾涛
# VITE_APP_BASE_API = 'http://192.168.110.171:8899'
# 屈展航
# VITE_APP_BASE_API = 'http://192.168.110.210:8899'
# ws
VITE_APP_BASE_WS_API = 'ws://192.168.110.149:8899/resource/websocket'

BIN
public/assets/demo/czzl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
public/assets/demo/glsc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/assets/demo/sjjk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -61,3 +61,26 @@ export const delSafetyInspection = (id: string | number | Array<string | number>
method: 'delete'
});
};
/**
*
* 新增安全巡检工单复查
* @param data
*/
export const addSafetyInspectionReview = (data: any) => {
return request({
url: '/safety/safetyInspection/review',
method: 'post',
data: data
});
}
/**
* 新增安全巡检工单整改
* @param data
*/
export const addSafetyInspectionRectification = (data: any) => {
return request({
url: '/safety/safetyInspection/rectification',
method: 'post',
data: data
});
}

View File

@ -1,4 +1,9 @@
export interface SafetyInspectionVO {
/**
* 整改单位名称
*/
rectificationName: string;
/**
* 主键ID
*/

View File

@ -61,3 +61,18 @@ export const delTeamMeeting = (id: string | number | Array<string | number>) =>
method: 'delete'
});
};
// 查询项目班组下的成员列表
export const listProjectTeamMember = (data: any) => {
return request({
url: '/project/projectTeamMember/list',
method: 'get',
data
});
};
// 根据 id 查询项目以及项目下的分包公司、班组列表
export const getProjectContractorTeamList = (id: string | number) => {
return request({
url: '/project/project/contractorTeamList/' + id,
method: 'get'
});
};

View File

@ -58,6 +58,10 @@ export interface TeamMeetingVO {
}
export interface TeamMeetingForm extends BaseEntity {
/**
* 班会主题
*/
meetingTheme?: string;
/**
* 主键id
*/

View File

@ -61,3 +61,23 @@ export const delViolationRecord = (id: string | number | Array<string | number>)
method: 'delete'
});
};
/**
* 新增违规记录复查
*/
export const addSafetyInspectionReview = (data: any) => {
return request({
url: '/safety/violationRecord/review',
method: 'post',
data: data
});
}
/**
* 新增违规记录整改
*/
export const addSafetyInspectionRectification = (data: any) => {
return request({
url: '/safety/violationRecord/rectification',
method: 'post',
data: data
});
}

View File

@ -1,10 +1,8 @@
<template>
<el-row>
<el-row style="padding: 0 20px;">
<el-col>
<div
style="color: rgba(0, 30, 59, 1); font-family: 'Alibaba-PuHuiTi-Bold'; margin: 10px 0 0 0"
:style="{ fontSize: fontLevelMap[props.fontLevel] }"
>
<div style="color: rgba(0, 30, 59, 1); font-family: 'Alibaba-PuHuiTi-Bold'; margin: 10px 0 0 0"
:style="{ fontSize: fontLevelMap[props.fontLevel] }">
{{ props.title }}
</div>
</el-col>

View File

@ -0,0 +1,38 @@
<template>
<div style="display: flex;align-items: center;">
<div class="icon">
<img :src="`/assets/demo/${icon}.png`" alt="图片" />
</div>
<div class="subtitle">
{{ subtitle }}
</div>
</div>
</template>
<script setup>
const { subtitle, icon } = defineProps({
subtitle: {
type: String,
default: ''
},
icon: {
type: String,
default: ''
}
})
</script>
<style scoped>
.subtitle {
font-family: Alibaba-PuHuiTi-Bold;
font-size: 18px;
font-weight: 400;
letter-spacing: 0px;
line-height: 21.6px;
color: rgba(0, 30, 59, 1);
text-align: left;
vertical-align: top;
}
img {
width: 30px;
}
</style>

View File

@ -0,0 +1,226 @@
<template>
<div class="operation-log-container">
<!-- 页面标题 -->
<div class="page-title">
<el-icon class="title-icon">
<DocumentChecked />
</el-icon>
<h1>操作指令记录</h1>
</div>
<!-- 搜索和操作区域 -->
<div class="search-bar">
<el-select v-model="selectedCommandType" placeholder="输入操作指令..." class="search-select" clearable>
<el-option v-for="type in commandTypes" :key="type.value" :label="type.label" :value="type.value" />
</el-select>
<el-button type="primary" class="send-btn">
<el-icon>
<Paperclip />
</el-icon>
发送
</el-button>
<el-button type="primary" :plain="true" class="export-btn">
<el-icon>
<Download />
</el-icon>
导出
</el-button>
</div>
<!-- 表格区域 -->
<el-table :data="tableData" border stripe class="log-table">
<el-table-column type="selection" width="50" />
<el-table-column prop="commandType" label="指令类型" width="120" />
<el-table-column prop="operationContent" label="操作内容" min-width="200" />
<el-table-column prop="device" label="设备" width="100" />
<el-table-column prop="status" label="状态" width="120" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === 'SUCCESS' ? 'success' : 'danger'" effect="light"
class="status-tag">
<el-icon :class="scope.row.status === 'SUCCESS' ? 'success-icon' : 'error-icon'">
<Check v-if="scope.row.status === 'SUCCESS'" />
<Close v-else />
</el-icon>
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="time" label="时间" width="140" />
</el-table>
<!-- 分页区域 -->
<div class="pagination-container">
<div class="record-info">
显示第1到7条共54条记录
</div>
<el-pagination v-model:current-page="currentPage" :page-size="pageSize" :page-count="totalPages"
layout="prev, pager, next" @current-change="handlePageChange" />
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import {
DocumentChecked,
Paperclip,
Download,
Check,
Close
} from '@element-plus/icons-vue';
// 指令类型选项
const commandTypes = [
{ label: '系统自检', value: 'system_check' },
{ label: '闭合馈线开关', value: 'close_feeder_switch' },
{ label: '闭合保护开关', value: 'close_protection_switch' },
{ label: '断开馈线开关', value: 'open_feeder_switch' },
];
// 选中的指令类型
const selectedCommandType = ref('');
// 表格数据
const tableData = ref([
{
commandType: '系统自检',
operationContent: '系统进入正常供电模式.',
device: '主系统',
status: 'SUCCESS',
time: '09:51:24'
},
{
commandType: '闭合馈线开关',
operationContent: '馈线开关A已闭合负载A.',
device: '主系统',
status: 'SUCCESS',
time: '09:41:20'
},
{
commandType: '闭合保护开关',
operationContent: '闭合母线开关',
device: '主系统',
status: 'ERROR',
time: '09:21:24'
},
{
commandType: '系统自检',
operationContent: '母线电压稳定在110KV',
device: '主系统',
status: 'SUCCESS',
time: '09:11:24'
},
{
commandType: '断开馈线开关',
operationContent: '闭合馈线开关',
device: '主系统',
status: 'SUCCESS',
time: '09:02:24'
},
{
commandType: '断开馈线开关',
operationContent: '闭合馈线开关',
device: '主系统',
status: 'SUCCESS',
time: '09:02:24'
},
{
commandType: '断开馈线开关',
operationContent: '闭合馈线开关',
device: '主系统',
status: 'SUCCESS',
time: '09:02:24'
}
]);
// 分页相关
const currentPage = ref(3);
const pageSize = ref(7);
const totalPages = ref(20);
// 处理页码变化
const handlePageChange = (page) => {
currentPage.value = page;
// 实际应用中这里会根据页码加载对应的数据
console.log(`切换到第${page}`);
};
</script>
<style scoped>
.operation-log-container {
max-width: 1200px;
margin: 20px auto;
padding: 0 20px;
}
.page-title {
display: flex;
align-items: center;
margin-bottom: 20px;
color: #333;
}
.title-icon {
margin-right: 8px;
color: #409eff;
}
.search-bar {
display: flex;
gap: 10px;
margin-bottom: 20px;
align-items: center;
}
.search-select {
flex: 0 1 300px;
}
.send-btn,
.export-btn {
white-space: nowrap;
}
.log-table {
width: 100%;
margin-bottom: 20px;
}
.status-tag {
display: flex;
align-items: center;
gap: 4px;
}
.success-icon {
color: #67c23a;
}
.error-icon {
color: #f56c6c;
}
.pagination-container {
display: flex;
justify-content: space-between;
align-items: center;
color: #606266;
font-size: 14px;
}
.record-info {
color: #606266;
}
.el-pagination {
--el-pagination-active-color: #409eff;
}
</style>

View File

@ -0,0 +1,349 @@
<template>
<el-card style="width: 100%;">
<div class="circuit-container">
<!-- 状态指示器 -->
<div class="status-indicators">
<div class="status-item">
<span class="status-dot closed"></span>
<span>闭合</span>
</div>
<div class="status-item">
<span class="status-dot open"></span>
<span>断开</span>
</div>
<div class="status-item">
<span class="status-dot running"></span>
<span>运行中</span>
</div>
</div>
<!-- 控制按钮 -->
<div class="control-buttons">
<button v-for="(device, index) in devices" :key="index" @click="toggleDevice(device.id)"
:class="{ 'btn-active': device.status === 'closed' }">
{{ device.name }}: {{ device.statusText }}
</button>
</div>
<!-- 电路图 SVG -->
<svg class="circuit-svg" viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
<!-- 背景网格 -->
<pattern id="grid" width="50" height="50" patternUnits="userSpaceOnUse">
<path d="M 50 0 L 0 0 0 50" fill="none" stroke="#f0f0f0" stroke-width="1" />
</pattern>
<rect width="100%" height="100%" fill="url(#grid)" />
<!-- 主线路径 -->
<!-- 发电站到主开关 -->
<line x1="100" y1="200" x2="180" y2="200" stroke="#22c55e" stroke-width="4" />
<!-- 主开关到变压器 -->
<line x1="220" y1="200" x2="280" y2="200" stroke="#22c55e" stroke-width="4" />
<!-- 变压器到母线开关 -->
<line x1="360" y1="200" x2="420" y2="200" stroke="#22c55e" stroke-width="4" />
<!-- 母线开关到分支点 -->
<line x1="460" y1="200" x2="500" y2="200" stroke="#22c55e" stroke-width="4" />
<!-- 分支点到馈线开关A -->
<line x1="500" y1="200" x2="500" y2="100" stroke="#22c55e" stroke-width="4" />
<line x1="500" y1="100" x2="580" y2="100" stroke="#22c55e" stroke-width="4" />
<!-- 分支点到馈线开关B -->
<line x1="500" y1="200" x2="500" y2="300" stroke="#ef4444" stroke-width="4" stroke-dasharray="5,5" />
<line x1="500" y1="300" x2="580" y2="300" stroke="#ef4444" stroke-width="4" stroke-dasharray="5,5" />
<!-- 馈线开关B到保护开关 -->
<line x1="620" y1="300" x2="700" y2="300" stroke="#ef4444" stroke-width="4" stroke-dasharray="5,5" />
<!-- 发电站 -->
<circle cx="100" cy="200" r="30" fill="#3b82f6" stroke="#1e40af" stroke-width="2" />
<text x="100" y="205" text-anchor="middle" fill="white" font-weight="bold">发电站</text>
<!-- 主开关 -->
<g :class="{ 'switch-closed': devices[0].status === 'closed' }">
<circle cx="200" cy="200" r="15" :fill="devices[0].status === 'closed' ? '#10b981' : '#ef4444'" />
<text x="200" y="250" text-anchor="middle" font-size="12">主开关</text>
<text x="200" y="270" text-anchor="middle" font-size="10" fill="#666">220kV</text>
<text x="200" y="285" text-anchor="middle" font-size="10"
:fill="devices[0].status === 'closed' ? '#10b981' : '#ef4444'">
{{ devices[0].statusText }}
</text>
</g>
<!-- 变压器 -->
<g>
<rect x="300" y="170" width="60" height="60" fill="white" stroke="#666" stroke-width="2" />
<line x1="315" y1="190" x2="345" y2="190" stroke="#666" stroke-width="2" />
<line x1="315" y1="210" x2="345" y2="210" stroke="#666" stroke-width="2" />
<line x1="315" y1="230" x2="345" y2="230" stroke="#666" stroke-width="2" />
<text x="330" y="285" text-anchor="middle" font-size="10" fill="#10b981">已完成</text>
</g>
<!-- 母线开关 -->
<g :class="{ 'switch-closed': devices[1].status === 'closed' }">
<circle cx="440" cy="200" r="15" :fill="devices[1].status === 'closed' ? '#10b981' : '#ef4444'" />
<text x="440" y="250" text-anchor="middle" font-size="12">母线开关</text>
<text x="440" y="270" text-anchor="middle" font-size="10" fill="#666">110kV</text>
<text x="440" y="285" text-anchor="middle" font-size="10"
:fill="devices[1].status === 'closed' ? '#10b981' : '#ef4444'">
{{ devices[1].statusText }}
</text>
</g>
<!-- 分支点 -->
<circle cx="500" cy="200" r="8" fill="#666" />
<!-- 馈线开关A -->
<g :class="{ 'switch-closed': devices[2].status === 'closed' }">
<circle cx="600" cy="100" r="15" :fill="devices[2].status === 'closed' ? '#10b981' : '#ef4444'" />
<text x="600" y="60" text-anchor="middle" font-size="12">馈线开关A</text>
<text x="600" y="80" text-anchor="middle" font-size="10"
:fill="devices[2].status === 'closed' ? '#10b981' : '#ef4444'">
{{ devices[2].statusText }}
</text>
</g>
<!-- 负载A -->
<circle cx="680" cy="100" r="20" fill="#3b82f6" stroke="#1e40af" stroke-width="2" />
<text x="680" y="105" text-anchor="middle" fill="white" font-size="12">负载A</text>
<text x="680" y="135" text-anchor="middle" font-size="10" fill="#10b981">已完成</text>
<!-- 馈线开关B -->
<g :class="{ 'switch-closed': devices[3].status === 'closed' }">
<circle cx="600" cy="300" r="15" :fill="devices[3].status === 'closed' ? '#10b981' : '#ef4444'" />
<text x="600" y="340" text-anchor="middle" font-size="12">馈线开关B</text>
<text x="600" y="360" text-anchor="middle" font-size="10"
:fill="devices[3].status === 'closed' ? '#10b981' : '#ef4444'">
{{ devices[3].statusText }}
</text>
</g>
<!-- 保护开关 -->
<g :class="{ 'switch-closed': devices[4].status === 'closed' }">
<circle cx="720" cy="300" r="15" :fill="devices[4].status === 'closed' ? '#10b981' : '#ef4444'" />
<text x="720" y="340" text-anchor="middle" font-size="12">保护开关</text>
<text x="720" y="360" text-anchor="middle" font-size="10"
:fill="devices[4].status === 'closed' ? '#10b981' : '#ef4444'">
{{ devices[4].statusText }}
</text>
</g>
</svg>
<!-- WebSocket 连接状态 -->
<div class="connection-status">
<span>WebSocket 连接状态:</span>
<span :class="wsConnected ? 'connected' : 'disconnected'">
{{ wsConnected ? '已连接' : '未连接' }}
</span>
</div>
</div>
</el-card>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
// 设备状态数据
const devices = ref([
{ id: 'main-switch', name: '主开关', status: 'closed', statusText: '已完成' },
{ id: 'bus-switch', name: '母线开关', status: 'closed', statusText: '已完成' },
{ id: 'feeder-a', name: '馈线开关A', status: 'closed', statusText: '已完成' },
{ id: 'feeder-b', name: '馈线开关B', status: 'open', statusText: '未完成' },
{ id: 'protection-switch', name: '保护开关', status: 'open', statusText: '未完成' }
]);
// WebSocket 连接状态
const wsConnected = ref(false);
let ws = null;
// 切换设备状态
const toggleDevice = (deviceId) => {
const device = devices.value.find(d => d.id === deviceId);
if (device) {
// 切换状态
device.status = device.status === 'closed' ? 'open' : 'closed';
device.statusText = device.status === 'closed' ? '已完成' : '未完成';
// 发送状态到服务器
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'status-update',
deviceId,
status: device.status
}));
}
}
};
// 连接 WebSocket
const connectWebSocket = () => {
// 实际应用中替换为真实的 WebSocket 服务器地址
const wsUrl = 'ws://localhost:8080/ws/circuit';
// 关闭现有连接
if (ws) {
ws.close();
}
// 创建新连接
ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('WebSocket 连接已建立');
wsConnected.value = true;
// 发送当前状态
ws.send(JSON.stringify({
type: 'initial-status',
status: devices.value.reduce((acc, device) => {
acc[device.id] = device.status;
return acc;
}, {})
}));
};
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('收到消息:', data);
// 处理状态更新
if (data.type === 'status-update' && data.deviceId && data.status) {
const device = devices.value.find(d => d.id === data.deviceId);
if (device) {
device.status = data.status;
device.statusText = data.status === 'closed' ? '已完成' : '未完成';
}
}
} catch (error) {
console.error('解析 WebSocket 消息失败:', error);
}
};
ws.onclose = () => {
console.log('WebSocket 连接已关闭');
wsConnected.value = false;
// 5秒后尝试重连
setTimeout(connectWebSocket, 5000);
};
ws.onerror = (error) => {
console.error('WebSocket 错误:', error);
};
};
// 组件挂载时连接 WebSocket
onMounted(() => {
connectWebSocket();
});
// 组件卸载时关闭 WebSocket 连接
onUnmounted(() => {
if (ws) {
ws.close();
}
});
</script>
<style scoped>
.circuit-container {
font-family: Arial, sans-serif;
padding: 20px;
max-width: 1000px;
margin: 0 auto;
}
.status-indicators {
display: flex;
gap: 20px;
margin-bottom: 15px;
padding: 10px;
background-color: #f9f9f9;
border-radius: 5px;
}
.status-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-dot {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
}
.status-dot.closed {
background-color: #10b981;
}
.status-dot.open {
background-color: #ef4444;
}
.status-dot.running {
background-color: #eab308;
}
.control-buttons {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
}
.control-buttons button {
padding: 8px 16px;
background-color: #f0f0f0;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}
.control-buttons button.btn-active {
background-color: #10b981;
color: white;
border-color: #059669;
}
.control-buttons button:hover {
background-color: #e0e0e0;
}
.control-buttons button.btn-active:hover {
background-color: #059669;
}
.circuit-svg {
width: 100%;
height: auto;
border: 1px solid #ddd;
border-radius: 5px;
background-color: white;
}
.connection-status {
margin-top: 15px;
padding: 10px;
background-color: #f9f9f9;
border-radius: 5px;
display: flex;
gap: 10px;
}
.connection-status .connected {
color: #10b981;
font-weight: bold;
}
.connection-status .disconnected {
color: #ef4444;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<div>
<RightTitle subtitle="功率输出趋势" icon="glsc" />
</div>
<div ref="chartRef" style="width: 100%; height: 400px;"></div>
</template>
<script setup>
import * as echarts from 'echarts';
import { ref, onMounted } from 'vue';
import RightTitle from './RightTitle.vue';
// 创建对 chart DOM 的引用
const chartRef = ref(null);
// 初始化图表并设置配置
onMounted(() => {
const chart = echarts.init(chartRef.value); // 初始化图表
const option = {
tooltip: {
trigger: 'axis',
},
legend: {
data: ['发电机1', '发电机2'],
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
},
yAxis: {
type: 'value',
min: 10,
max: 20,
interval: 2,
},
series: [
{
name: '发电机1',
type: 'line',
data: [14, 16, 14, 15, 16, 14, 16, 15, 16, 17, 16],
smooth: true,
color: '#3366FF',
areaStyle: {
opacity: 0.2,
},
},
{
name: '发电机2',
type: 'line',
data: [16, 17, 15, 16, 18, 16, 17, 17, 18, 19, 18],
smooth: true,
color: '#FFCC00',
areaStyle: {
opacity: 0.2,
},
},
],
};
// 设置图表的配置
chart.setOption(option);
});
</script>
<style scoped>
/* Optional styling */
</style>

View File

@ -1,5 +1,5 @@
<template>
<el-card>
<el-card style="width: 100%;">
<div class="container">
<div class="item">
<div class="top">
@ -31,7 +31,7 @@
<img src="/assets/demo/sb2.png" alt="">
</div>
<div class="content">
<p class="t1">128小时</p>
<p class="t1" style="font-size: 21px;">128小时</p>
<p class="t2">运行时长</p>
</div>
</div>
@ -99,9 +99,8 @@
<span class="t2">(30 days)</span>
</div>
</div>
<div class="back">
<span>34522</span>
<span>已安全运行</span>
<div class="item day">
<span class="text">34522</span>
</div>
</div>
</el-card>
@ -113,14 +112,40 @@
.container {
display: flex;
justify-content: space-around;
gap: 20px;
}
.day {
flex: 1.5 !important;
margin: 0 !important;
padding: 0 !important;
background-color: transparent !important;
background-image: url('/assets/demo/dayImg.png');
background-size: contain;
background-repeat: no-repeat;
background-position: 100% 50%;
position: relative;
width: 120px;
.text {
position: absolute;
bottom: 60px;
color: rgba(24, 109, 245, 1);
font-weight: bold;
font-size: 25px;
margin-left: 10px;
left: 50%;
transform: translateX(-50%);
}
}
.item {
background-color: rgba(240, 249, 255, 1);
padding: 20px 40px 20px 20px;
padding: 30px 15px;
border-radius: 20px;
text-align: center;
flex: 1;
margin: 75px 0;
.top {
display: flex;
@ -177,8 +202,16 @@
}
.back {
position: relative;
:deep(.el-card__body) {
padding: 0 !important;
}
.box {
display: flex;
height: 100%;
}
</style>
<script setup>

View File

@ -0,0 +1,136 @@
<template>
<RightTitle subtitle="实时数据监控" icon="sjjk" />
<div class="sjjk-container">
<div class="chart-container">
<div id="chart" class="echarts-wrapper" style="width: 800px; height: 200px;"></div>
</div>
</div>
</template>
<script setup>
import RightTitle from './RightTitle.vue';
import * as echarts from 'echarts';
import { onMounted } from 'vue';
onMounted(() => {
// 初始化图表
const myChart = echarts.init(document.getElementById('chart'));
// 图表配置项
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {
data: ['电压(kv)', '电流(A)', '功率(MW)'],
},
grid: {
top: '15%',
left: '12%',
right: '12%',
bottom: '20%',
containLabel: true,
show: false
},
xAxis: {
type: 'category',
data: ['发电机1', '发电机2', '发电机3', '发电机4', '发电机5', '发电机6'],
axisLabel: {
interval: 0,
rotate: 45
}
},
yAxis: [
{
type: 'value',
name: '电压(kv)/电流(A)',
splitLine: {
show: false
}
},
{
type: 'value',
name: '功率(MW)',
splitLine: {
show: false
}
},
],
series: [
{
name: '电压(kv)',
type: 'bar',
data: [80, 70, 55, 80, 80, 80],
},
{
name: '电流(A)',
type: 'bar',
data: [65, 80, 65, 65, 65, 65],
},
{
name: '功率(MW)',
type: 'bar',
yAxisIndex: 1,
data: [58, 80, 80, 58, 58, 58],
},
],
};
// 渲染图表
myChart.setOption(option);
// 窗口大小变化时,图表自适应
window.addEventListener('resize', () => {
myChart.resize();
});
});
</script>
<style scoped>
:deep(.el-card__body) {
padding: 0;
}
.sjjk-container {
width: 100%;
height: 100%;
background: #ffffff;
border-radius: 8px;
/* padding: 20px; */
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
width: 100%;
max-width: 800px;
}
.chart-container {
width: 100%;
max-width: 800px;
height: 400px;
display: flex;
justify-content: center;
align-items: center;
}
.echarts-wrapper {
width: 100%;
height: 100%;
min-height: 400px;
border-radius: 4px;
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
}
</style>

View File

@ -2,10 +2,26 @@
<div style="padding: 20px;">
<el-row>
<el-col :span="15">
<TitleComponent title="设备情况" subtitle="电站一次监控数据" />
<sbqk />
<el-row>
<TitleComponent title="设备情况" subtitle="电站一次监控数据" />
<sbqk />
</el-row>
<el-row>
<TitleComponent title="电站一次系统图" subtitle="电站一次监控数据" />
<dzt />
</el-row>
<el-row>
<TitleComponent title="运行步骤日志" subtitle="实时更新中" />
<!-- <sbqk /> -->
</el-row>
</el-col>
<el-col :span="8">
<el-col :span="8" :push="1">
<TitleComponent title="运行步骤日志" subtitle="实时更新中" />
<el-card style="padding: 0;">
<sjjk />
<glsc />
<czzljl />
</el-card>
</el-col>
</el-row>
</div>
@ -19,5 +35,8 @@
<script setup>
import TitleComponent from '@/views/demo/components/TitleComponent.vue';
import sbqk from './components/sbqk.vue';
</script>
import sjjk from './components/sjjk.vue';
import glsc from './components/glsc.vue';
import czzljl from './components/czzljl.vue';
import dzt from './components/dzt.vue';
</script>

View File

@ -2,35 +2,41 @@
<!-- <el-card v-loading="loading" body-class="printMe"> -->
<div class="w75% m-a">
<div id="printMe" class="pos-relative">
<div class="resultIcon"><img :src="'../../../../../src/assets/icons/svg/' + inspectionType + '.png'" alt="" /></div>
<div class="resultIcon"><img :src="'../../../../../src/assets/icons/svg/' + inspectionType + '.png'" alt="" />
</div>
<h2 style="text-align: center; margin-top: 5px; font-weight: bold">安全生产监督检查通知书</h2>
<el-row>
<el-col :span="12" style="text-align: left">填报人{{ safetyInspectionDetail?.creatorName }}</el-col>
<el-col :span="12" style="text-align: right">填报时间{{ safetyInspectionDetail?.createTime }}</el-col>
</el-row>
<el-descriptions :column="2" border style="margin-top: 8px" label-width="160px" size="large">
<el-descriptions-item label-align="center" label="检查项目" :span="2" class-name="zebra">{{ currentProject?.name }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="检查项目" :span="2" class-name="zebra">{{ currentProject?.name }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="检查类型" label-class-name="white">
<dict-tag :options="safety_inspection_check_type" :value="safetyInspectionDetail?.checkType" />
</el-descriptions-item>
<el-descriptions-item label-align="center" label="违章类型" label-class-name="white">
<dict-tag :options="safety_inspection_violation_type" :value="safetyInspectionDetail?.violationType" />
</el-descriptions-item>
<el-descriptions-item label-align="center" label="检查时间" class-name="zebra">{{ safetyInspectionDetail?.checkTime }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="检查人" class-name="zebra">{{ safetyInspectionDetail?.creatorName }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="整改人" label-class-name="white"
>{{ safetyInspectionDetail?.correctorName }}
<el-descriptions-item label-align="center" label="检查时间" class-name="zebra">{{ safetyInspectionDetail?.checkTime
}} </el-descriptions-item>
<el-descriptions-item label-align="center" label="检查人" class-name="zebra">{{ safetyInspectionDetail?.creatorName
}} </el-descriptions-item>
<el-descriptions-item label-align="center" label="整改人" label-class-name="white">{{
safetyInspectionDetail?.correctorName }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="要求整改期限" label-class-name="white">
{{ dayjs(safetyInspectionDetail?.rectificationDeadline).format('YYYY 年 MM 月 DD 日') }}
<span v-if="safetyInspectionDetail?.rectificationDeadline">{{
dayjs(safetyInspectionDetail?.rectificationDeadline).format('YYYY MM DD ') }}</span>
<span v-else></span>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border direction="vertical" size="large">
<el-descriptions-item label-align="center" label="巡检结果" class-name="none"></el-descriptions-item>
</el-descriptions>
<el-descriptions :column="2" border label-width="160px" size="large">
<el-descriptions-item label-align="center" label="内容" :span="2" label-class-name="white"
>{{ safetyInspectionDetail?.hiddenDanger }}
<el-descriptions-item label-align="center" label="内容" :span="2" label-class-name="white">{{
safetyInspectionDetail?.hiddenDanger }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="检查附件" :span="2" label-class-name="white">
<el-space wrap>
@ -56,11 +62,11 @@
<el-descriptions-item label-align="center" label="整改情况" class-name="none"></el-descriptions-item>
</el-descriptions>
<el-descriptions :column="2" border label-width="160px" size="large">
<el-descriptions-item label-align="center" label="班组" label-class-name="white"
>{{ safetyInspectionDetail?.teamName }}
<el-descriptions-item label-align="center" label="班组" label-class-name="white">{{
safetyInspectionDetail?.rectificationName }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="整改日期" label-class-name="white"
>{{ safetyInspectionDetail?.rectificationTime }}
<el-descriptions-item label-align="center" label="整改日期" label-class-name="white">{{
safetyInspectionDetail?.rectificationTime }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="整改措施及完成情况" :span="2" label-class-name="white">
{{ safetyInspectionDetail?.measure }}
@ -84,14 +90,14 @@
<el-descriptions-item label-align="center" label="复查结果" class-name="none"></el-descriptions-item>
</el-descriptions>
<el-descriptions :column="2" border label-width="160px" size="large">
<el-descriptions-item label-align="center" label="复查人" label-class-name="white"
>{{ safetyInspectionDetail?.creatorName }}
<el-descriptions-item label-align="center" label="复查人" label-class-name="white">{{
safetyInspectionDetail?.creatorName }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="复查日期" label-class-name="white"
>{{ safetyInspectionDetail?.reviewTime }}
<el-descriptions-item label-align="center" label="复查日期" label-class-name="white">{{
safetyInspectionDetail?.reviewTime }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="复查情况" :span="2" label-class-name="white"
>{{ safetyInspectionDetail?.review }}
<el-descriptions-item label-align="center" label="复查情况" :span="2" label-class-name="white">{{
safetyInspectionDetail?.review }}
</el-descriptions-item>
</el-descriptions>
</div>
@ -236,6 +242,7 @@ watch(
z-index: 10;
width: 105px;
height: 105px;
img {
width: 105px;
}

View File

@ -1,22 +1,26 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="检查类型" prop="checkType">
<el-select v-model="queryParams.checkType" placeholder="全部" clearable>
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="违章类型" prop="violationType">
<el-select v-model="queryParams.violationType" placeholder="全部" clearable>
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="处理状态" prop="status">
<el-select v-model="queryParams.status" placeholder="全部" clearable>
<el-option v-for="dict in safety_inspection_type" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-option v-for="dict in safety_inspection_type" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
@ -32,15 +36,18 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['safety:safetyInspection:add']"> 新增 </el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['safety:safetyInspection:add']">
新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['safety:safetyInspection:remove']">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
v-hasPermi="['safety:safetyInspection:remove']">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['safety:safetyInspection:export']">导出 </el-button>
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['safety:safetyInspection:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
@ -93,11 +100,21 @@
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220">
<template #default="scope">
<el-space>
<el-button link type="primary" icon="View" @click="handleShowDialog(scope.row)" v-hasPermi="['safety:safetyInspection:query']">
<el-button link type="primary" icon="View" @click="handleShowDialog(scope.row)"
v-hasPermi="['safety:safetyInspection:query']">
详情
</el-button>
<el-button link type="success" v-if="scope.row.status === '1'" icon="Pointer"
@click="handleDialog(scope.row)" v-hasPermi="['safety:safetyInspection:rectification']">
整改
</el-button>
<el-button link type="warning" icon="SuccessFilled" v-if="scope.row.status === '2'"
@click="handleDialog(scope.row)" v-hasPermi="['safety:safetyInspection:review']">
复查
</el-button>
<!-- <el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['safety:safetyInspection:edit']">修改 </el-button> -->
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['safety:safetyInspection:remove']">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['safety:safetyInspection:remove']">
删除
</el-button>
</el-space>
@ -105,7 +122,8 @@
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改安全巡检工单对话框 -->
@ -116,12 +134,14 @@
</el-form-item>
<el-form-item label="检查类型" prop="checkType">
<el-select v-model="form.checkType" placeholder="请选择检查类型">
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="违章类型" prop="violationType">
<el-select v-model="form.violationType" placeholder="请选择违章类型">
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="巡检结果" prop="inspectionResult">
@ -129,12 +149,14 @@
</el-form-item>
<el-form-item label="工单整改单位" prop="rectificationUnit">
<el-select v-model="form.rectificationUnit" placeholder="请选择整改单位类型">
<el-option v-for="dict in rectification_unit_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option v-for="dict in rectification_unit_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="整改班组" prop="teamId">
<el-select v-model="form.teamId" placeholder="请选择整改班组">
<el-option v-for="item in teamOpt" :key="item.value" :label="item.label" :value="item.value" @click="changeForeman(item.value)" />
<el-option v-for="item in teamOpt" :key="item.value" :label="item.label" :value="item.value"
@click="changeForeman(item.value)" />
</el-select>
</el-form-item>
<el-form-item label="整改人" prop="correctorId">
@ -152,17 +174,20 @@
<el-form-item label="问题隐患" prop="hiddenDanger">
<el-input v-model="form.hiddenDanger" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="整改措施" prop="measure">
<!-- <el-form-item label="整改措施" prop="measure">
<el-input v-model="form.measure" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form-item> -->
<el-form-item label="要求整改期限" prop="checkTime">
<el-date-picker clearable v-model="form.rectificationDeadline" type="date" value-format="YYYY-MM-DD" placeholder="选择要求整改期限" />
<el-date-picker clearable v-model="form.rectificationDeadline" type="date" value-format="YYYY-MM-DD"
placeholder="选择要求整改期限" />
</el-form-item>
<el-form-item label="检查附件" prop="checkFile">
<file-upload v-model="form.checkFile" :file-size="20" :file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
<file-upload v-model="form.checkFile" :file-size="20"
:file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
</el-form-item>
<el-form-item label="整改附件" prop="rectificationFile">
<file-upload v-model="form.rectificationFile" :file-size="20" :file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
<file-upload v-model="form.rectificationFile" :file-size="20"
:file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
@ -178,6 +203,29 @@
<el-dialog title="巡检工单详情" v-model="showDetailDialog" width="60vw">
<safety-inspection-detail-dialog :safety-inspection-id="currentSafetyInspectionId" />
</el-dialog>
<el-dialog :title="handleType === 'rectification' ? '处理整改工单' : '处理复查工单'" v-model="handleDialogVisible"
width="500px">
<el-form ref="handleFormRef" :model="handleForm" :rules="rules" label-width="120px">
<el-form-item label="整改措施" prop="measure" v-if="handleType === 'rectification'">
<el-input v-model="handleForm.measure" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="整改附件" prop="rectificationFile" v-if="handleType === 'rectification'">
<image-upload v-model="handleForm.rectificationFile" />
</el-form-item>
<el-form-item label="复查情况" prop="review" v-if="handleType === 'review'">
<el-input v-model="handleForm.review" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="复查类型" prop="reviewType" v-if="handleType === 'review'">
<el-select v-model="handleForm.reviewType" placeholder="请选择复查类型">
<el-option v-for="dict in review_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit"> </el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
@ -187,7 +235,9 @@ import {
delSafetyInspection,
getSafetyInspection,
listSafetyInspection,
updateSafetyInspection
updateSafetyInspection,
addSafetyInspectionReview,
addSafetyInspectionRectification,
} from '@/api/safety/safetyInspection';
import { SafetyInspectionForm, SafetyInspectionQuery, SafetyInspectionVO } from '@/api/safety/safetyInspection/types';
import { useUserStoreHook } from '@/store/modules/user';
@ -225,7 +275,14 @@ const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const handleForm = ref({
id: undefined,
measure: undefined,
rectificationFile: undefined,
review: undefined,
reviewType: undefined,
remark: undefined,
})
const initFormData: SafetyInspectionForm = {
id: undefined,
pid: undefined,
@ -293,6 +350,10 @@ const { queryParams, form, rules } = toRefs(data);
const teamOpt = ref([]);
const foremanOpt = ref([]);
const teamList = ref<ProjectTeamForemanResp[]>();
const handleType = ref("")
/** 查询安全巡检工单列表 */
const getList = async () => {
loading.value = true;
@ -318,16 +379,48 @@ const changeForeman = (value: string | number) => {
}));
form.value.correctorId = '';
};
/** 处理安全巡查工单 */
const handleSubmit = async () => {
let flag = false;
if (handleType.value == "rectification") {
const { code } = await addSafetyInspectionRectification(handleForm.value)
if (code == 200) flag = true
} else {
const { code } = await addSafetyInspectionReview(handleForm.value)
if (code == 200) flag = true
}
if (flag) {
ElMessage.success("处理成功")
handleDialogVisible.value = false;
getList()
reset()
} else {
ElMessage.error("处理失败")
}
}
/** 展开安全巡检工单详情对话框操作 */
const currentSafetyInspectionId = ref<string | number>();
const showDetailDialog = ref<boolean>(false);
const handleDialogVisible = ref<boolean>(false);
const handleShowDialog = (row?: SafetyInspectionVO) => {
currentSafetyInspectionId.value = row.id;
showDetailDialog.value = true;
};
/**打开整改/复查对话框操作*/
const handleDialog = (row?: SafetyInspectionVO) => {
if (row.status == '1') {
handleType.value = "rectification"
} else {
handleType.value = "review"
}
handleForm.value.id = row.id;
handleDialogVisible.value = true;
};
/** 取消按钮 */
const cancel = () => {
reset();

View File

@ -7,12 +7,13 @@
</el-descriptions-item>
<el-descriptions-item label="班组名称">{{ teamMeetingDetail?.teamName }}</el-descriptions-item>
<el-descriptions-item label="施工单位">{{ teamMeetingDetail?.contractorName }}</el-descriptions-item>
<el-descriptions-item label="开会时间">{{ dayjs(teamMeetingDetail?.meetingDate).format('YYYY 年 MM 月 DD 日') }}</el-descriptions-item>
<el-descriptions-item label="开会时间">{{ dayjs(teamMeetingDetail?.meetingDate).format('YYYY 年 MM 月 DD 日')
}}</el-descriptions-item>
<el-descriptions-item label="上传时间">{{ teamMeetingDetail?.createTime }}</el-descriptions-item>
<el-descriptions-item :span="2" label="班会内容">{{ teamMeetingDetail?.content }}</el-descriptions-item>
<el-descriptions-item :span="2" label="班会图片">
<el-descriptions-item :span="2" label="班会图片" v-if="teamMeetingDetail?.pictureUrlList">
<el-space wrap>
<span :key="item" v-for="item in teamMeetingDetail?.pictureUrlList">
<span :key="item" v-for="item in teamMeetingDetail?.pictureUrlList?.split(',')">
<image-preview :src="item" width="200px" />
</span>
</el-space>

View File

@ -1,11 +1,13 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="开会时间" prop="meetingDate">
<el-date-picker clearable v-model="queryParams.meetingDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择开会时间" />
<el-date-picker clearable v-model="queryParams.meetingDate" type="date" value-format="YYYY-MM-DD"
placeholder="请选择开会时间" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@ -19,11 +21,13 @@
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['safety:teamMeeting:add']"> 新增 </el-button>
</el-col> -->
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['safety:teamMeeting:remove']">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['safety:teamMeeting:add']"> 新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
v-hasPermi="['safety:teamMeeting:remove']">
删除
</el-button>
</el-col>
@ -59,11 +63,13 @@
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space>
<el-button link type="primary" icon="View" @click="handleShowDrawer(scope.row)" v-hasPermi="['safety:teamMeeting:query']">
<el-button link type="primary" icon="View" @click="handleShowDrawer(scope.row)"
v-hasPermi="['safety:teamMeeting:query']">
详情
</el-button>
<!-- <el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['safety:teamMeeting:edit']"> 修改 </el-button> -->
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['safety:teamMeeting:remove']">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['safety:teamMeeting:remove']">
删除
</el-button>
</el-space>
@ -71,13 +77,40 @@
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改站班会对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-dialog :title="dialog.title" v-model="dialog.visible" width="50%" append-to-body>
<el-form ref="teamMeetingFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="开会时间" prop="meetingDate">
<el-date-picker clearable v-model="form.meetingDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择开会时间" />
<el-date-picker clearable v-model="form.meetingDate" type="date" value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开会时间" />
</el-form-item>
<el-form-item label="班组名称" prop="teamId">
<el-select v-model="form.teamId" placeholder="请选择班组">
<el-option v-for="item in teamList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="施工单位" prop="contractorId">
<el-select v-model="form.contractorId" placeholder="请选择施工单位">
<el-option v-for="item in contractorList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="宣讲人" prop="compereId">
<el-select v-model="form.compereId" placeholder="请选择宣讲人">
<el-option v-for="item in compereList" :key="item.memberId" :label="item.memberName"
:value="item.memberId" />
</el-select>
</el-form-item>
<el-form-item label="参与人" prop="participantIdList">
<el-select v-model="form.participantIdList" placeholder="请选择参与人" multiple>
<el-option v-for="item in participantList" :key="item.memberId" :label="item.memberName"
:value="item.memberId" />
</el-select>
</el-form-item>
<el-form-item label="班会主题" prop="meetingTheme">
<el-input v-model="form.meetingTheme" placeholder="请输入班会主题" />
</el-form-item>
<el-form-item label="班会内容">
<editor v-model="form.content" :min-height="192" />
@ -105,7 +138,7 @@
<script setup name="TeamMeeting" lang="ts">
console.log(111);
import { addTeamMeeting, delTeamMeeting, getTeamMeeting, listTeamMeeting, updateTeamMeeting } from '@/api/safety/teamMeeting';
import { addTeamMeeting, delTeamMeeting, getTeamMeeting, listTeamMeeting, updateTeamMeeting, listProjectTeamMember, getProjectContractorTeamList } from '@/api/safety/teamMeeting';
import { TeamMeetingForm, TeamMeetingQuery, TeamMeetingVO } from '@/api/safety/teamMeeting/types';
import { useUserStoreHook } from '@/store/modules/user';
import TeamMeetingDetailDrawer from '@/views/safety/teamMeeting/component/TeamMeetingDetailDrawer.vue';
@ -124,6 +157,12 @@ const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const teamList = ref<any>([]);
const contractorList = ref<any>([]);
const compereList = ref<any>([]);
const participantList = ref<any>([]);
const queryFormRef = ref<ElFormInstance>();
const teamMeetingFormRef = ref<ElFormInstance>();
@ -143,7 +182,8 @@ const initFormData: TeamMeetingForm = {
participantIdList: undefined,
content: undefined,
pictureList: undefined,
remark: undefined
remark: undefined,
meetingTheme: undefined
};
const data = reactive<PageData<TeamMeetingForm, TeamMeetingQuery>>({
form: { ...initFormData },
@ -284,9 +324,28 @@ onUnmounted(() => {
listeningProject();
});
console.log(11);
const getTeamAndContractor = async () => {
const projectId = currentProject.value?.id;
const { data: { teamList: teamListRes, contractorList: contractorListRes } } = await getProjectContractorTeamList(projectId);
console.log(teamListRes, contractorListRes);
teamList.value = teamListRes;
contractorList.value = contractorListRes;
};
const getUsers = async () => {
const { rows } = await listProjectTeamMember({
projectId: currentProject.value?.id
})
compereList.value = rows.filter(item => item.postId == 1)
participantList.value = rows.filter(item => item.postId == 0)
};
const getData = async () => {
await getTeamAndContractor()
await getUsers()
};
onMounted(() => {
console.log(122);
getList();
getData();
});
</script>

View File

@ -1,6 +1,7 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
@ -8,7 +9,8 @@
<el-input v-model="queryParams.id" placeholder="请输入工单号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="违章时间" prop="violationTime">
<el-date-picker clearable v-model="queryParams.violationTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择违章时间" />
<el-date-picker clearable v-model="queryParams.violationTime" type="date" value-format="YYYY-MM-DD"
placeholder="请选择违章时间" />
</el-form-item>
<el-form-item>
@ -24,9 +26,8 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['safety:violationRecord:remove']"
>删除</el-button
>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
v-hasPermi="['safety:violationRecord:remove']">删除</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
@ -38,7 +39,8 @@
<el-table-column label="违章等级" align="center" prop="levelVo" width="180">
<template #default="scope">
<div class="flex justify-center">
{{ scope.row.levelVo.violationLevel }}<dict-tag :options="risk_level_type" :value="scope.row.levelVo.riskType" />
{{ scope.row.levelVo.violationLevel }}<dict-tag :options="risk_level_type"
:value="scope.row.levelVo.riskType" />
</div>
</template>
</el-table-column>
@ -77,28 +79,37 @@
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240">
<template #default="scope">
<el-tooltip content="详情" placement="top">
<el-button
link
type="primary"
icon="View"
@click="handleShowDialog(scope.row)"
v-hasPermi="['safety:violationRecord:view']"
></el-button>
</el-tooltip>
<el-tooltip content="违章处理人" placement="top">
<el-button link type="primary" icon="User" @click="handleUpdate(scope.row)" v-hasPermi="['safety:violationRecord:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['safety:violationRecord:remove']"></el-button>
</el-tooltip>
<el-space>
<el-tooltip content="详情" placement="top">
<el-button link type="primary" icon="View" @click="handleShowDialog(scope.row)"
v-hasPermi="['safety:violationRecord:view']"></el-button>
</el-tooltip>
<el-tooltip content="违章处理人" placement="top">
<el-button link type="primary" icon="User" @click="handleUpdate(scope.row)"
v-hasPermi="['safety:violationRecord:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['safety:violationRecord:remove']"></el-button>
</el-tooltip>
<el-tooltip content="整改" placement="top" v-if="scope.row.status == 1">
<el-button link type="success" icon="Pointer" @click="handleDialog(scope.row)"
v-hasPermi="['safety:violationRecord:rectification']">整改</el-button>
</el-tooltip>
<el-tooltip content="复查" placement="top" v-if="scope.row.status == 2">
<el-button link type="warning" icon="SuccessFilled" @click="handleDialog(scope.row)"
v-hasPermi="['safety:violationRecord:review']">复查</el-button>
</el-tooltip>
</el-space>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改违规记录对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
@ -107,7 +118,8 @@
<el-input v-model="form.handlerId" placeholder="请输入违章处理人" />
</el-form-item>
<el-form-item label="处理期限" prop="disposeDeadline">
<el-date-picker clearable v-model="form.disposeDeadline" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择处理期限">
<el-date-picker clearable v-model="form.disposeDeadline" type="datetime" value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择处理期限">
</el-date-picker>
</el-form-item>
<el-form-item label="备注" prop="remark">
@ -124,17 +136,40 @@
<el-dialog title="违规记录详情" v-model="showDetailDialog" width="60vw">
<ViolationRecordDetailDialog :violation-record-id="currentViolationRecordId" />
</el-dialog>
<el-dialog :title="handleType === 'rectification' ? '处理整改工单' : '处理复查工单'" v-model="handleDialogVisible"
width="500px">
<el-form ref="handleFormRef" :model="handleForm" :rules="rules" label-width="120px">
<el-form-item label="整改措施" prop="measure" v-if="handleType === 'rectification'">
<el-input v-model="handleForm.measure" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="整改附件" prop="rectificationFile" v-if="handleType === 'rectification'">
<image-upload v-model="handleForm.rectificationFile" />
</el-form-item>
<el-form-item label="复查情况" prop="review" v-if="handleType === 'review'">
<el-input v-model="handleForm.review" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="复查类型" prop="reviewType" v-if="handleType === 'review'">
<el-select v-model="handleForm.reviewType" placeholder="请选择复查类型">
<el-option v-for="dict in review_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit"> </el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script setup name="ViolationRecord" lang="ts">
import { listViolationRecord, getViolationRecord, delViolationRecord, addViolationRecord, updateViolationRecord } from '@/api/safety/violationRecord';
import { listViolationRecord, getViolationRecord, delViolationRecord, addViolationRecord, updateViolationRecord, addSafetyInspectionReview, addSafetyInspectionRectification } from '@/api/safety/violationRecord';
import { ViolationRecordVO, ViolationRecordQuery, ViolationRecordForm } from '@/api/safety/violationRecord/types';
import ViolationRecordDetailDialog from './component/violationRecordDetailDialog.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { violation_level_type, risk_level_type, safety_inspection_type } = toRefs<any>(
proxy?.useDict('violation_level_type', 'risk_level_type', 'safety_inspection_type')
const { violation_level_type, risk_level_type, safety_inspection_type, review_type } = toRefs<any>(
proxy?.useDict('violation_level_type', 'risk_level_type', 'safety_inspection_type', 'review_type')
);
const violationRecordList = ref<ViolationRecordVO[]>([]);
@ -150,7 +185,11 @@ const showDetailDialog = ref(false);
const queryFormRef = ref<ElFormInstance>();
const violationRecordFormRef = ref<ElFormInstance>();
const handleType = ref<string>('');
const handleForm = ref({
id: undefined,
})
const handleDialogVisible = ref(false);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
@ -208,6 +247,29 @@ const data = reactive<PageData<ViolationRecordForm, ViolationRecordQuery>>({
const { queryParams, form, rules } = toRefs(data);
/** 处理安全巡查工单 */
const handleSubmit = async () => {
let flag = false;
if (handleType.value == "rectification") {
const { code } = await addSafetyInspectionRectification(handleForm.value)
if (code == 200) flag = true
} else {
const { code } = await addSafetyInspectionReview(handleForm.value)
if (code == 200) flag = true
}
if (flag) {
ElMessage.success("处理成功")
handleDialogVisible.value = false;
getList()
reset()
} else {
ElMessage.error("处理失败")
}
}
/** 查询违规记录列表 */
const getList = async () => {
loading.value = true;
@ -217,6 +279,17 @@ const getList = async () => {
loading.value = false;
};
const handleDialog = (row) => {
if (row.status == '1') {
handleType.value = "rectification"
} else {
handleType.value = "review"
}
handleForm.value.id = row.id;
handleDialogVisible.value = true;
};
/** 取消按钮 */
const cancel = () => {
reset();