|
|
@ -100,7 +100,11 @@
|
|
|
|
<dict-tag :options="dict.type.trigger_rule" :value="scope.row.triggerRule"/>
|
|
|
|
<dict-tag :options="dict.type.trigger_rule" :value="scope.row.triggerRule"/>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="触发阈值次数" align="center" prop="triggerNumber" v-if="columns[7].visible"/>
|
|
|
|
<el-table-column label="监测字段" align="center" prop="monitorField" v-if="columns[7].visible">
|
|
|
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
|
|
|
<dict-tag :options="dict.type.monitor_field" :value="scope.row.monitorField"/>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="时间范围(分)" align="center" prop="timeRange" v-if="columns[8].visible"/>
|
|
|
|
<el-table-column label="时间范围(分)" align="center" prop="timeRange" v-if="columns[8].visible"/>
|
|
|
|
<el-table-column label="触发阈值量" align="center" prop="triggerValue" v-if="columns[9].visible"/>
|
|
|
|
<el-table-column label="触发阈值量" align="center" prop="triggerValue" v-if="columns[9].visible"/>
|
|
|
|
<el-table-column label="通知用户" align="center" prop="notifyUser" v-if="columns[10].visible"/>
|
|
|
|
<el-table-column label="通知用户" align="center" prop="notifyUser" v-if="columns[10].visible"/>
|
|
|
@ -181,7 +185,7 @@
|
|
|
|
</el-radio>
|
|
|
|
</el-radio>
|
|
|
|
</el-radio-group>
|
|
|
|
</el-radio-group>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="监测字段" prop="monitorField" v-if="selectedMonitorType === 6 || selectedMonitorType === 10">
|
|
|
|
<el-form-item label="监测字段" prop="monitorField" >
|
|
|
|
<el-select v-model="form.monitorField" placeholder="请选择监测字段">
|
|
|
|
<el-select v-model="form.monitorField" placeholder="请选择监测字段">
|
|
|
|
<el-option v-for="dict in dict.type.monitor_field" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
|
|
|
<el-option v-for="dict in dict.type.monitor_field" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
@ -216,11 +220,11 @@
|
|
|
|
添加步骤
|
|
|
|
添加步骤
|
|
|
|
</el-button>
|
|
|
|
</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-if="actionStepsList.length === 0" class="empty-steps">
|
|
|
|
<div v-if="actionStepsList.length === 0" class="empty-steps">
|
|
|
|
<el-empty description="暂无处置措施,请点击添加步骤"></el-empty>
|
|
|
|
<el-empty description="暂无处置措施,请点击添加步骤"></el-empty>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-else class="steps-list">
|
|
|
|
<div v-else class="steps-list">
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
v-for="(step, index) in actionStepsList"
|
|
|
|
v-for="(step, index) in actionStepsList"
|
|
|
@ -231,26 +235,26 @@
|
|
|
|
<div class="step-header">
|
|
|
|
<div class="step-header">
|
|
|
|
<span class="step-number">步骤 {{ step.stepSequence }}</span>
|
|
|
|
<span class="step-number">步骤 {{ step.stepSequence }}</span>
|
|
|
|
<div class="step-controls">
|
|
|
|
<div class="step-controls">
|
|
|
|
<el-button
|
|
|
|
<el-button
|
|
|
|
v-if="index > 0"
|
|
|
|
v-if="index > 0"
|
|
|
|
type="text"
|
|
|
|
type="text"
|
|
|
|
size="mini"
|
|
|
|
size="mini"
|
|
|
|
icon="el-icon-top"
|
|
|
|
icon="el-icon-top"
|
|
|
|
@click="moveStepUp(index)"
|
|
|
|
@click="moveStepUp(index)"
|
|
|
|
title="上移"
|
|
|
|
title="上移"
|
|
|
|
></el-button>
|
|
|
|
></el-button>
|
|
|
|
<el-button
|
|
|
|
<el-button
|
|
|
|
v-if="index < actionStepsList.length - 1"
|
|
|
|
v-if="index < actionStepsList.length - 1"
|
|
|
|
type="text"
|
|
|
|
type="text"
|
|
|
|
size="mini"
|
|
|
|
size="mini"
|
|
|
|
icon="el-icon-bottom"
|
|
|
|
icon="el-icon-bottom"
|
|
|
|
@click="moveStepDown(index)"
|
|
|
|
@click="moveStepDown(index)"
|
|
|
|
title="下移"
|
|
|
|
title="下移"
|
|
|
|
></el-button>
|
|
|
|
></el-button>
|
|
|
|
<el-button type="danger" size="mini" icon="el-icon-delete" @click="removeActionStep(index)" circle></el-button>
|
|
|
|
<el-button type="danger" size="mini" icon="el-icon-delete" @click="removeActionStep(index)" circle></el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="step-content">
|
|
|
|
<div class="step-content">
|
|
|
|
<el-form :model="step" label-width="100px" size="small">
|
|
|
|
<el-form :model="step" label-width="100px" size="small">
|
|
|
|
<el-form-item label="步骤描述">
|
|
|
|
<el-form-item label="步骤描述">
|
|
|
@ -261,14 +265,14 @@
|
|
|
|
placeholder="请输入步骤描述"
|
|
|
|
placeholder="请输入步骤描述"
|
|
|
|
></el-input>
|
|
|
|
></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="备注">
|
|
|
|
<el-form-item label="备注">
|
|
|
|
<el-input
|
|
|
|
<el-input
|
|
|
|
v-model="step.remark"
|
|
|
|
v-model="step.remark"
|
|
|
|
placeholder="请输入备注信息"
|
|
|
|
placeholder="请输入备注信息"
|
|
|
|
></el-input>
|
|
|
|
></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="参考图片">
|
|
|
|
<el-form-item label="参考图片">
|
|
|
|
<div class="image-upload-section">
|
|
|
|
<div class="image-upload-section">
|
|
|
|
<!-- 图片上传 -->
|
|
|
|
<!-- 图片上传 -->
|
|
|
@ -286,7 +290,7 @@
|
|
|
|
<div class="el-upload__text">将图片拖到此处,或<em>点击上传</em></div>
|
|
|
|
<div class="el-upload__text">将图片拖到此处,或<em>点击上传</em></div>
|
|
|
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过2MB</div>
|
|
|
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过2MB</div>
|
|
|
|
</el-upload>
|
|
|
|
</el-upload>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 图片列表 -->
|
|
|
|
<!-- 图片列表 -->
|
|
|
|
<div v-if="step.stepImages && step.stepImages.length > 0" class="image-list">
|
|
|
|
<div v-if="step.stepImages && step.stepImages.length > 0" class="image-list">
|
|
|
|
<div
|
|
|
|
<div
|
|
|
@ -321,7 +325,7 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
<el-button type="primary" @click="saveActionSteps" :loading="actionStepsSaving">
|
|
|
|
<el-button type="primary" @click="saveActionSteps" :loading="actionStepsSaving">
|
|
|
|
保存措施
|
|
|
|
保存措施
|
|
|
@ -415,15 +419,15 @@ export default {
|
|
|
|
{ key: 4, label: `记录时间`, visible: false },
|
|
|
|
{ key: 4, label: `记录时间`, visible: false },
|
|
|
|
{ key: 5, label: `能源类型`, visible: false },
|
|
|
|
{ key: 5, label: `能源类型`, visible: false },
|
|
|
|
{ key: 6, label: `触发规则`, visible: true },
|
|
|
|
{ key: 6, label: `触发规则`, visible: true },
|
|
|
|
{ key: 7, label: `触发阈值次数`, visible: false },
|
|
|
|
{ key: 7, label: `监测字段`, visible: true },
|
|
|
|
{ key: 8, label: `时间范围(分)`, visible: false },
|
|
|
|
{ key: 8, label: `时间范围(分)`, visible: false },
|
|
|
|
{ key: 9, label: `触发阈值量`, visible: true },
|
|
|
|
{ key: 9, label: `触发阈值量`, visible: true },
|
|
|
|
{ key: 10, label: `通知用户`, visible: false },
|
|
|
|
{ key: 10, label: `通知用户`, visible: false },
|
|
|
|
{ key: 11, label: `备注`, visible: true },
|
|
|
|
{ key: 11, label: `备注`, visible: true },
|
|
|
|
{ key: 12, label: `创建人`, visible: false },
|
|
|
|
// { key: 12, label: `创建人`, visible: false },
|
|
|
|
{ key: 13, label: `创建时间`, visible: true },
|
|
|
|
// { key: 13, label: `创建时间`, visible: true },
|
|
|
|
{ key: 14, label: `更新人`, visible: false },
|
|
|
|
// { key: 14, label: `更新人`, visible: false },
|
|
|
|
{ key: 15, label: `更新时间`, visible: false }
|
|
|
|
// { key: 15, label: `更新时间`, visible: false }
|
|
|
|
],
|
|
|
|
],
|
|
|
|
actionStepsTitle: '',
|
|
|
|
actionStepsTitle: '',
|
|
|
|
actionStepsOpen: false,
|
|
|
|
actionStepsOpen: false,
|
|
|
@ -595,10 +599,10 @@ export default {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
addActionStep() {
|
|
|
|
addActionStep() {
|
|
|
|
const newSequence = this.actionStepsList.length > 0
|
|
|
|
const newSequence = this.actionStepsList.length > 0
|
|
|
|
? Math.max(...this.actionStepsList.map(s => s.stepSequence || 0)) + 1
|
|
|
|
? Math.max(...this.actionStepsList.map(s => s.stepSequence || 0)) + 1
|
|
|
|
: 1;
|
|
|
|
: 1;
|
|
|
|
|
|
|
|
|
|
|
|
const newStep = {
|
|
|
|
const newStep = {
|
|
|
|
tempId: Date.now() + Math.random(), // 临时ID
|
|
|
|
tempId: Date.now() + Math.random(), // 临时ID
|
|
|
|
ruleObjId: this.currentRuleObjId,
|
|
|
|
ruleObjId: this.currentRuleObjId,
|
|
|
@ -607,7 +611,7 @@ export default {
|
|
|
|
remark: '',
|
|
|
|
remark: '',
|
|
|
|
stepImages: []
|
|
|
|
stepImages: []
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.actionStepsList.push(newStep);
|
|
|
|
this.actionStepsList.push(newStep);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
removeActionStep(index) {
|
|
|
|
removeActionStep(index) {
|
|
|
@ -629,7 +633,7 @@ export default {
|
|
|
|
if (!step.stepImages) {
|
|
|
|
if (!step.stepImages) {
|
|
|
|
step.stepImages = [];
|
|
|
|
step.stepImages = [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从完整URL中提取相对路径,只保存相对路径到数据库
|
|
|
|
// 从完整URL中提取相对路径,只保存相对路径到数据库
|
|
|
|
let relativePath = res.url;
|
|
|
|
let relativePath = res.url;
|
|
|
|
if (res.url.startsWith('http')) {
|
|
|
|
if (res.url.startsWith('http')) {
|
|
|
@ -637,14 +641,14 @@ export default {
|
|
|
|
const urlObj = new URL(res.url);
|
|
|
|
const urlObj = new URL(res.url);
|
|
|
|
relativePath = urlObj.pathname;
|
|
|
|
relativePath = urlObj.pathname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const newImage = {
|
|
|
|
const newImage = {
|
|
|
|
tempId: Date.now() + Math.random(),
|
|
|
|
tempId: Date.now() + Math.random(),
|
|
|
|
imageUrl: relativePath, // 只存储相对路径
|
|
|
|
imageUrl: relativePath, // 只存储相对路径
|
|
|
|
imageSequence: step.stepImages.length + 1,
|
|
|
|
imageSequence: step.stepImages.length + 1,
|
|
|
|
description: ''
|
|
|
|
description: ''
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
step.stepImages.push(newImage);
|
|
|
|
step.stepImages.push(newImage);
|
|
|
|
this.$message.success('图片上传成功');
|
|
|
|
this.$message.success('图片上传成功');
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -687,14 +691,14 @@ export default {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.actionStepsSaving = true;
|
|
|
|
this.actionStepsSaving = true;
|
|
|
|
|
|
|
|
|
|
|
|
// 处理数据,移除临时ID
|
|
|
|
// 处理数据,移除临时ID
|
|
|
|
const stepsToSave = this.actionStepsList.map(step => {
|
|
|
|
const stepsToSave = this.actionStepsList.map(step => {
|
|
|
|
const stepData = { ...step };
|
|
|
|
const stepData = { ...step };
|
|
|
|
delete stepData.tempId;
|
|
|
|
delete stepData.tempId;
|
|
|
|
|
|
|
|
|
|
|
|
if (stepData.stepImages && stepData.stepImages.length > 0) {
|
|
|
|
if (stepData.stepImages && stepData.stepImages.length > 0) {
|
|
|
|
stepData.stepImages = stepData.stepImages.map(img => {
|
|
|
|
stepData.stepImages = stepData.stepImages.map(img => {
|
|
|
|
const imgData = { ...img };
|
|
|
|
const imgData = { ...img };
|
|
|
@ -702,10 +706,10 @@ export default {
|
|
|
|
return imgData;
|
|
|
|
return imgData;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return stepData;
|
|
|
|
return stepData;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
batchSaveActionSteps(this.currentRuleObjId, stepsToSave).then(response => {
|
|
|
|
batchSaveActionSteps(this.currentRuleObjId, stepsToSave).then(response => {
|
|
|
|
this.$message.success('措施步骤保存成功');
|
|
|
|
this.$message.success('措施步骤保存成功');
|
|
|
|
this.actionStepsOpen = false;
|
|
|
|
this.actionStepsOpen = false;
|
|
|
@ -748,12 +752,12 @@ export default {
|
|
|
|
// 获取完整的图片URL
|
|
|
|
// 获取完整的图片URL
|
|
|
|
getFullImageUrl(relativePath) {
|
|
|
|
getFullImageUrl(relativePath) {
|
|
|
|
if (!relativePath) return '';
|
|
|
|
if (!relativePath) return '';
|
|
|
|
|
|
|
|
|
|
|
|
// 如果已经是完整URL,直接返回(兼容历史数据)
|
|
|
|
// 如果已经是完整URL,直接返回(兼容历史数据)
|
|
|
|
if (relativePath.startsWith('http')) {
|
|
|
|
if (relativePath.startsWith('http')) {
|
|
|
|
return relativePath;
|
|
|
|
return relativePath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 动态拼接当前环境的baseURL
|
|
|
|
// 动态拼接当前环境的baseURL
|
|
|
|
const baseURL = process.env.VUE_APP_BASE_API || '';
|
|
|
|
const baseURL = process.env.VUE_APP_BASE_API || '';
|
|
|
|
return baseURL + relativePath;
|
|
|
|
return baseURL + relativePath;
|
|
|
@ -793,7 +797,7 @@ export default {
|
|
|
|
border: 1px solid #e4e7ed;
|
|
|
|
border: 1px solid #e4e7ed;
|
|
|
|
border-radius: 8px;
|
|
|
|
border-radius: 8px;
|
|
|
|
background: #fafafa;
|
|
|
|
background: #fafafa;
|
|
|
|
|
|
|
|
|
|
|
|
.step-header {
|
|
|
|
.step-header {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
justify-content: space-between;
|
|
|
@ -802,29 +806,29 @@ export default {
|
|
|
|
background: #f0f9ff;
|
|
|
|
background: #f0f9ff;
|
|
|
|
border-bottom: 1px solid #e4e7ed;
|
|
|
|
border-bottom: 1px solid #e4e7ed;
|
|
|
|
border-radius: 8px 8px 0 0;
|
|
|
|
border-radius: 8px 8px 0 0;
|
|
|
|
|
|
|
|
|
|
|
|
.step-number {
|
|
|
|
.step-number {
|
|
|
|
font-size: 16px;
|
|
|
|
font-size: 16px;
|
|
|
|
font-weight: bold;
|
|
|
|
font-weight: bold;
|
|
|
|
color: #409EFF;
|
|
|
|
color: #409EFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-controls {
|
|
|
|
.step-controls {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
gap: 5px;
|
|
|
|
gap: 5px;
|
|
|
|
|
|
|
|
|
|
|
|
.el-button--text {
|
|
|
|
.el-button--text {
|
|
|
|
color: #606266;
|
|
|
|
color: #606266;
|
|
|
|
font-size: 16px;
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
&:hover {
|
|
|
|
color: #409EFF;
|
|
|
|
color: #409EFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-content {
|
|
|
|
.step-content {
|
|
|
|
padding: 20px;
|
|
|
|
padding: 20px;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -837,44 +841,44 @@ export default {
|
|
|
|
height: 120px;
|
|
|
|
height: 120px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.image-list {
|
|
|
|
.image-list {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
gap: 15px;
|
|
|
|
gap: 15px;
|
|
|
|
margin-top: 15px;
|
|
|
|
margin-top: 15px;
|
|
|
|
|
|
|
|
|
|
|
|
.image-item {
|
|
|
|
.image-item {
|
|
|
|
width: 200px;
|
|
|
|
width: 200px;
|
|
|
|
border: 1px solid #e4e7ed;
|
|
|
|
border: 1px solid #e4e7ed;
|
|
|
|
border-radius: 6px;
|
|
|
|
border-radius: 6px;
|
|
|
|
overflow: hidden;
|
|
|
|
overflow: hidden;
|
|
|
|
background: white;
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
|
|
|
|
.image-preview {
|
|
|
|
.image-preview {
|
|
|
|
height: 150px;
|
|
|
|
height: 150px;
|
|
|
|
cursor: pointer;
|
|
|
|
cursor: pointer;
|
|
|
|
position: relative;
|
|
|
|
position: relative;
|
|
|
|
overflow: hidden;
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
|
|
img {
|
|
|
|
img {
|
|
|
|
width: 100%;
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
height: 100%;
|
|
|
|
object-fit: cover;
|
|
|
|
object-fit: cover;
|
|
|
|
transition: transform 0.3s;
|
|
|
|
transition: transform 0.3s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:hover img {
|
|
|
|
&:hover img {
|
|
|
|
transform: scale(1.05);
|
|
|
|
transform: scale(1.05);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.image-info {
|
|
|
|
.image-info {
|
|
|
|
padding: 10px;
|
|
|
|
padding: 10px;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8px;
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
.el-input {
|
|
|
|
.el-input {
|
|
|
|
flex: 1;
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -885,7 +889,7 @@ export default {
|
|
|
|
|
|
|
|
|
|
|
|
.image-preview-container {
|
|
|
|
.image-preview-container {
|
|
|
|
text-align: center;
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
|
|
img {
|
|
|
|
img {
|
|
|
|
border-radius: 6px;
|
|
|
|
border-radius: 6px;
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
|