You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

636 lines
22 KiB
Vue

1 month ago
<!--
智能井位推荐参数设置
author: RYG
date: 2025年6月25日09:37:38
-->
<template>
<div class="scrollable-form">
<el-form v-model="propertyParam.wellParamSettings" label-position="right" label-width="100px">
<!-- 标题设置 -->
<div name="wellParamSettings" class="well-param">
<el-divider content-position="left">井平台参数设置</el-divider>
<el-form-item label="断裂图件" label-position="right" class="well-param-item">
<el-select v-model="propertyParam.wellParamSettings.selectedOption" placeholder="请选择断裂文件"
class="well-param-input">
<el-option v-for="item in fractureFileData" :key="item.MapID" :label="item.MapName" :value="item.MapID"
@click="handleOptionClick(item)"></el-option>
</el-select>
</el-form-item>
<el-form-item label="边界图层" label-position="right" class="well-param-item">
<el-input v-model="propertyParam.wellParamSettings.boundaryLayer" placeholder="选择边界图层"
class="well-param-input" @click="showBoundaryLayerData"></el-input>
</el-form-item>
<el-form-item label="断层图层" label-position="right" class="well-param-item">
<el-input v-model="propertyParam.wellParamSettings.faultLayer" placeholder="选择断层图层" class="well-param-input"
@click="showFractureLayerData"></el-input>
</el-form-item>
<el-form-item label="井名" label-position="right" class="well-param-item">
<el-input v-model="propertyParam.wellParamSettings.WellNamePrefix" placeholder="输入井名"
class="well-param-input"></el-input>
</el-form-item>
<el-form-item label="井支数" class="well-param-item">
<el-input-number v-model="propertyParam.wellParamSettings.BranchCount" placeholder="井支数"
class="well-param-input"></el-input-number>
</el-form-item>
<el-form-item label="靶前距" class="well-param-item">
<el-input-number v-model="propertyParam.wellParamSettings.BranchOffset" placeholder="靶前距"
class="well-param-input"></el-input-number>
</el-form-item>
<el-form-item label="水平段长度" class="well-param-item">
<el-input-number v-model="propertyParam.wellParamSettings.BranchLength" placeholder="水平段长度"
class="well-param-input"></el-input-number>
</el-form-item>
<el-form-item label="井支间距" class="well-param-item">
<el-input-number v-model="propertyParam.wellParamSettings.BranchSpace" placeholder="井支间距"
class="well-param-input"></el-input-number>
</el-form-item>
<div class="other-form-item-nolabel">
<el-checkbox v-model="propertyParam.wellParamSettings.DeploySide2"></el-checkbox><el-checkbox
v-model="propertyParam.wellParamSettings.DeploySide1">单侧布井</el-checkbox>
</div>
<div class="other-form-item-nolabel">
<el-checkbox v-model="propertyParam.wellParamSettings.DeployAgain"></el-checkbox>
</div>
</div>
</el-form>
<el-form label-width="100px" :model="propertyParam.calcParamSettings">
<!-- 坐标轴设置 -->
<div name="calcParamSettings" class="well-param">
<el-divider content-position="left">计算参数设置</el-divider>
<el-form-item label="井平台间距" class="well-param-item">
<el-input-number v-model="propertyParam.calcParamSettings.WellsSpace" placeholder="井平台间距"
class="well-param-input"></el-input-number>
</el-form-item>
<el-form-item label="突变率" class="well-param-item">
<el-input-number v-model="propertyParam.calcParamSettings.MutationRate" placeholder="突变率" :min="0.1"
:max="0.9" class="well-param-input" :step="0.1"></el-input-number>
</el-form-item>
<el-form-item label="旋转次数" class="well-param-item">
<el-input-number v-model="propertyParam.calcParamSettings.Rotations" placeholder="旋转次数"
class="well-param-input"></el-input-number>
</el-form-item>
<el-form-item label="角度范围" class="well-param-item">
<el-input v-model="propertyParam.calcParamSettings.AngleStart" placeholder="角度范围最小值" class="well-param-input"
style="width: 60px"></el-input>
&nbsp; ~ &nbsp;
<el-input v-model="propertyParam.calcParamSettings.AngleEnd" placeholder="角度范围最大值" class="well-param-input"
style="width: 60px"></el-input>
</el-form-item>
<el-form-item label="指定角度" class="well-param-item">
<div class="other-form-item">
<el-checkbox v-model="propertyParam.calcParamSettings.SpecifyAngles" placeholder="指定角度"></el-checkbox>
<el-input v-model="propertyParam.calcParamSettings.SpeciaAngles" placeholder="指定角度范围"
:disabled="!propertyParam.calcParamSettings.SpecifyAngles" class="well-param-input"></el-input>
</div>
</el-form-item>
<el-form-item label="忽略小断裂" class="well-param-item">
<div class="other-form-item">
<el-checkbox class="left-label" v-model="propertyParam.calcParamSettings.IgnoreMiniFault"
placeholder="忽略小断裂"></el-checkbox>
<el-input v-model="propertyParam.calcParamSettings.MiniFaultLength" placeholder="断裂值"
:disabled="!propertyParam.calcParamSettings.IgnoreMiniFault" class="well-param-input"
style="width: 80px"></el-input>
</div>
</el-form-item>
</div>
</el-form>
<div class="button-container">
<el-button type="primary" @click="handleStartCalc" :disabled="smartWellButton">计算</el-button>
1 month ago
<el-button type="primary" @click="handleStopCalc(true)" :disabled="smartWellButtonStop">停止</el-button>
1 month ago
</div>
1 month ago
<el-dialog v-model="showLayer" title="请选择层位数据" style="width: 270px; height: 600px; z-index: 30" @close="handleClose"
:close-on-click-modal="false">
1 month ago
<div class="img-layer">
<ClientOnly>
1 month ago
<LayerTree :isPopup="true" class="popup-tree" :show-oper="true" :token-key="currentTokenKey" />
1 month ago
</ClientOnly>
</div>
</el-dialog>
1 month ago
<ProgressTracker ref="progressRef" v-model="progressVisible" title="计算进度" :initialProgress="currentProgress"
:message="progressMessage" @complete="onComplete" @manual-close="onManualClose" />
1 month ago
</div>
</template>
<script setup>
1 month ago
import { ref, onMounted, onBeforeUnmount } from "vue";
1 month ago
import {
fractureFileList,
startSmartWellCalc,
stopSmartWellCalc,
getWellRecommend
} from "@/services/wellRecommandService";
import { emitter } from "~/utils/eventBus";
import { checkEmpty } from "@/utils/objHelper";
1 month ago
import { EMIT_COMMAND } from '~/utils/commandTypes';
1 month ago
import { useSignalR } from "~/composables/useSignalR";
1 month ago
import { STORAGE_KEYS } from "~/utils/storageKeys"
// 当前页图件token的 key
const currentTokenKey = STORAGE_KEYS.WELL_RECOMMAND_TOKEN;
1 month ago
// 消息提示(自动隐藏)
const { $toastMessage } = useNuxtApp();
const { connect, connectionId, sigMsg, sendMessage, on } = useSignalR();
// 进度条显示状态
const progressVisible = ref(false);
1 month ago
const progressRef = ref(null);
const currentToken = computed(() => localStorage.getItem(currentTokenKey));
1 month ago
// 当前进度
const currentProgress = ref(0);
// 当前进度的消息
const progressMessage = ref('');
// 任务是否已经开始,用于按钮状态控制、任务状态监听
const taskStarted = ref(false);
// 任务ID
const taskId = ref("");
1 month ago
const emit = defineEmits(['openFile'])
1 month ago
// 配置参数
const propertyParam = reactive({
// 井平台参数设置
wellParamSettings: {
selectedOption: "",
fractureFile: "",
boundaryLayer: "",
faultLayer: "",
WellNamePrefix: "井",
BranchCount: 6,
BranchOffset: 500,
BranchLength: 1800,
BranchSpace: 300,
DeploySide2: true,
DeploySide1: true,
DeployAgain: false,
},
// 计算参数设置
calcParamSettings: {
WellsSpace: 500,
MutationRate: 0.5, // 0.1-0.9之间
Rotations: 8,
AngleStart: 30,
AngleEnd: 90,
SpecifyAngles: false,
SpeciaAngles: ["0", "0", "90", "0", "0", "270", "180", "180", "180"],
IgnoreMiniFault: true,
MiniFaultLength: 1000,
},
});
// 图层顶层
const boundaryLayerData = reactive([
{
id: 0,
parentId: 0,
name: "图层",
status: 0,
children: [],
},
]);
// 计算按钮状态
const smartWellButton = computed(() => taskStarted.value);
// 停止按钮状态
const smartWellButtonStop = computed(() => !taskStarted.value);
// 二次布井时用到的数据Id
const DeployAgainId = ref('');
const fractureFileData = ref([]);
/** 标识选择的是边界还是断层0边界1断层 */
const inputType = ref(-1);
// 图层显示切换属性
const showLayer = ref(false);
watchEffect(() => {
if (!sigMsg.value) {
return;
}
const msg = JSON.parse(sigMsg.value);
const prog = msg.progress;
const smsg = msg.msg;
currentProgress.value = prog;
progressMessage.value = smsg;
updateCalcInfo(prog, smsg, true);
emitMsg({
type: "calcRedraw",
1 month ago
cmdID: currentTokenKey,
1 month ago
data: JSON.stringify({ msg: '重新绘制' }),
});
1 month ago
emitRefresh();
1 month ago
});
// 处理选择断裂图件
const handleOptionClick = (item) => {
1 month ago
emitter.emit(EMIT_COMMAND.SOURCE_CHANGED);
// emitMsg({
// type: EMIT_COMMAND.OPEN_FILE,
// cmdID: currentTokenKey,
// data: JSON.stringify({ fileName: item.MapName }),
// });
// doOpenFile(item.MapName, currentTokenKey);
console.log("打开图件:handleOptionClick=", item.MapName)
emit('openFile', item.MapName);
// 如果选择了断裂图件就表示要计算新的
// if (DeployAgainId.value === 0) {
propertyParam.wellParamSettings.fractureFile = item.MapName;
// 清空之前选择的图层数据
boundaryLayerData[0].children = [];
propertyParam.wellParamSettings.boundaryLayer = "";
propertyParam.wellParamSettings.faultLayer = "";
// }
1 month ago
};
1 month ago
1 month ago
1 month ago
// 显示边界图层数据的逻辑
const showBoundaryLayerData = () => {
if (!propertyParam.wellParamSettings.selectedOption) {
1 month ago
$toastMessage.warning("您还没有选择断裂分布图!");
1 month ago
return;
}
// 检查boundaryLayerData是否正确定义
if (!boundaryLayerData || !boundaryLayerData[0] || !boundaryLayerData[0].children) {
console.error("boundaryLayerData结构不正确");
$toastMessage.error("图层数据结构初始化失败!");
return;
}
inputType.value = 0;
// 显示选择框
showLayer.value = true;
};
// 显示断层图层数据的逻辑
const showFractureLayerData = () => {
if (!propertyParam.wellParamSettings.selectedOption) {
1 month ago
$toastMessage.warning("您还没有选择断裂分布图!");
1 month ago
return;
}
inputType.value = 1;
// 显示选择框
showLayer.value = true;
};
// 发送计算命令
const handleStartCalc = async () => {
try {
// 检查断裂分布图选择
let selectedChunk = null;
1 month ago
if (propertyParam.wellParamSettings.DeployAgain) {
1 month ago
// 是二次布井
selectedChunk = propertyParam.wellParamSettings.selectedOption;
} else {
let selectedValue = fractureFileData.value.find(
(chunk) => chunk.MapID === propertyParam.wellParamSettings.selectedOption
);
selectedChunk = selectedValue?.MapName;
if (checkEmpty(selectedChunk)) {
1 month ago
$toastMessage.warning("您还没有选择断裂分布图!");
1 month ago
return;
}
}
if (!selectedChunk) {
1 month ago
$toastMessage.warning("您还没有选择断裂分布图!");
1 month ago
return;
}
if (!connectionId.value) {
1 month ago
$toastMessage.warning("实时消息连接未建立,请刷新页面重试!");
1 month ago
return;
}
// 检查必要参数
if (checkEmpty(propertyParam.wellParamSettings.boundaryLayer)) {
1 month ago
$toastMessage.warning("请选择边界图层!");
1 month ago
return;
}
if (checkEmpty(propertyParam.wellParamSettings.faultLayer)) {
1 month ago
$toastMessage.warning("请选择断层图层!");
1 month ago
return;
}
// 修改按钮状态
taskStarted.value = true;
// 组装计算参数
const smartWellParam = {
DeployAgainId: DeployAgainId.value,
1 month ago
clientId: currentToken.value,
drawerId: currentToken.value,
1 month ago
connectionId: connectionId.value,
wellParamSettings: {
fractureFile: selectedChunk || propertyParam.wellParamSettings.selectedOption,
boundaryLayer: propertyParam.wellParamSettings.boundaryLayer,
faultLayer: propertyParam.wellParamSettings.faultLayer,
WellNamePrefix: propertyParam.wellParamSettings.WellNamePrefix,
BranchCount: parseInt(propertyParam.wellParamSettings.BranchCount) || 6,
BranchOffset: parseInt(propertyParam.wellParamSettings.BranchOffset) || 500,
BranchLength: parseInt(propertyParam.wellParamSettings.BranchLength) || 1800,
BranchSpace: parseInt(propertyParam.wellParamSettings.BranchSpace) || 300,
DeploySide2: propertyParam.wellParamSettings.DeploySide2,
DeploySide1: propertyParam.wellParamSettings.DeploySide1,
DeployAgain: propertyParam.wellParamSettings.DeployAgain,
},
calcParamSettings: {
WellsSpace: parseInt(propertyParam.calcParamSettings.WellsSpace) || 500,
MutationRate: parseFloat(propertyParam.calcParamSettings.MutationRate) || 0.5,
Rotations: parseInt(propertyParam.calcParamSettings.Rotations) || 8,
AngleStart: parseInt(propertyParam.calcParamSettings.AngleStart) || 30,
AngleEnd: parseInt(propertyParam.calcParamSettings.AngleEnd) || 90,
SpecifyAngles: propertyParam.calcParamSettings.SpecifyAngles,
1 month ago
SpeciaAngles: propertyParam.calcParamSettings.SpecifyAngles ? (propertyParam.calcParamSettings.SpeciaAngles ? [propertyParam.calcParamSettings.SpeciaAngles] : []) : [],
1 month ago
IgnoreMiniFault: propertyParam.calcParamSettings.IgnoreMiniFault,
MiniFaultLength:
parseInt(propertyParam.calcParamSettings.MiniFaultLength) || 1000,
},
};
1 month ago
progressVisible.value = true;
1 month ago
const response = await startSmartWellCalc(smartWellParam);
if (!response) {
taskStarted.value = false;
taskId.value = "";
$toastMessage.error("智能布井失败: 服务器未返回任务ID");
1 month ago
progressVisible.value = false;
1 month ago
return;
}
taskId.value = response;
1 month ago
1 month ago
updateCalcInfo(0, "正在初始化", true);
} catch (error) {
console.error("智能布井出错:", error);
taskId.value = null;
$toastMessage.error(
`智能布井失败: ${error.response?.data?.message || error.message || "未知错误"}`
);
localStorage.removeItem("currentTaskId");
progressVisible.value = false;
progressMessage.value = '';
}
};
const updateCalcInfo = (progress, msg, isRunning) => {
localStorage.setItem(
"currentTaskId",
JSON.stringify({
taskId: taskId.value,
progress: progress,
message: msg,
isRunning: isRunning,
})
);
}
1 month ago
// 手动关闭进度条
const onManualClose = async () => {
await handleStopCalc(false);
}
// 停止任务处理
const handleStopCalc = async (closeProgress = true) => {
1 month ago
// 停止计算的逻辑
try {
1 month ago
if (taskId.value && taskStarted.value) {
1 month ago
const response = await stopSmartWellCalc(taskId.value);
if (response) {
$toastMessage.info("成功停止计算任务");
1 month ago
// emitRefresh();
1 month ago
// localStorage.removeItem("currentTaskId");
} else {
$toastMessage.warning("停止任务失败");
}
}
} catch (error) {
console.error("停止错误:", error);
} finally {
taskId.value = null;
// 更新本地存储
updateCalcInfo(0, "任务已停止", false);
1 month ago
// 加载断裂图件
await getFractureFileList();
if (closeProgress && progressRef.value) {
progressRef.value.close();
}
// progressVisible.value = false;
1 month ago
taskStarted.value = false;
1 month ago
emitRefresh();
1 month ago
emitMsg({
type: "calcRedraw",
1 month ago
cmdID: currentTokenKey,
1 month ago
data: JSON.stringify({ msg: '重新绘制' }),
});
}
};
1 month ago
const emitRefresh = () => {
emitter.emit(EMIT_COMMAND.REFRESH_RESULT);
};
1 month ago
const emitMsg = (data) => {
1 month ago
// console.log("emitMsg", data);
emitter.emit(EMIT_COMMAND.EVT_TYPE, data);
1 month ago
};
onMounted(async () => {
// 加载断裂图件
await getFractureFileList();
listenEmitter();
});
// 监听图层选择
const listenEmitter = () => {
1 month ago
emitter.on(EMIT_COMMAND.SELECTED_LAYER, (data) => {
1 month ago
handleClose();
if (checkEmpty(data)) {
1 month ago
$toastMessage.warning("请选择图层!");
1 month ago
return;
}
switch (inputType.value) {
case 0:
propertyParam.wellParamSettings.boundaryLayer = data;
break;
case 1:
propertyParam.wellParamSettings.faultLayer = data;
break;
}
});
1 month ago
// // 二次布井事件
// emitter.on("reCalc", async (data) => {
// try {
// const response = await getWellRecommend(data.Id);
// if (!response) {
// $toastMessage.error("获取井推荐参数失败!");
// return;
// }
// DeployAgainId.value = data.Id;
// propertyParam.wellParamSettings.selectedOption = response.OutGraphicFile;
// nextTick();
// propertyParam.wellParamSettings.boundaryLayer = response.Boundary_Layer;
// propertyParam.wellParamSettings.faultLayer = response.Fault_Layer;
// propertyParam.wellParamSettings.WellNamePrefix = response.Well_Name;
// propertyParam.wellParamSettings.BranchCount = response.Well_Nums;
// propertyParam.wellParamSettings.BranchOffset = response.Target_Space;
// propertyParam.wellParamSettings.BranchLength = response.Horizon_Length;
// propertyParam.wellParamSettings.BranchSpace = response.WellBranchSpace;
// propertyParam.wellParamSettings.DeploySide2 = response.DoubleWell;
// propertyParam.wellParamSettings.DeploySide1 = response.SingleWell;
// propertyParam.wellParamSettings.DeployAgain = true; // 标记二次布井
// propertyParam.calcParamSettings.WellsSpace = response.WellSpace;
// propertyParam.calcParamSettings.MutationRate = response.MutationRate;
// propertyParam.calcParamSettings.Rotations = response.RotationTimes;
// propertyParam.calcParamSettings.AngleStart = response.AngularRangeMin;
// propertyParam.calcParamSettings.AngleEnd = response.AngularRangeMax;
// propertyParam.calcParamSettings.SpecifyAngles = response.IsAngleRange;
// // this.calcParamSettings.SpeciaAngles = response.AngleRangeValue; // 角度范围值
// propertyParam.calcParamSettings.IgnoreMiniFault = response.IsSmallFracture;
// propertyParam.calcParamSettings.MiniFaultLength = response.SmallFractureValue;
// // 调用二次布井方法
// await handleStartCalc();
// } catch (error) {
// console.error("获取智能布井计算参数时出错:", error);
// $toastMessage.error("获取智能布井计算参数出错了");
// }
// });
1 month ago
// 计算参数
1 month ago
emitter.on(EMIT_COMMAND.CALC_PROPERTY, async (data) => {
1 month ago
const response = await getWellRecommend(data.Id);
if (!response) {
$toastMessage.error("获取井推荐参数失败!");
return;
}
1 month ago
DeployAgainId.value = data.Id;
1 month ago
1 month ago
propertyParam.wellParamSettings.selectedOption = response.Fracture_FileName;
1 month ago
propertyParam.wellParamSettings.boundaryLayer = data.Boundary_Layer;
propertyParam.wellParamSettings.faultLayer = data.Fault_Layer;
propertyParam.wellParamSettings.WellNamePrefix = data.Well_Name;
propertyParam.wellParamSettings.BranchCount = data.Well_Nums;
propertyParam.wellParamSettings.BranchOffset = data.Target_Space;
propertyParam.wellParamSettings.BranchLength = data.Horizon_Length;
propertyParam.wellParamSettings.BranchSpace = data.WellBranchSpace;
propertyParam.wellParamSettings.DeploySide2 = data.DoubleWell;
propertyParam.wellParamSettings.DeploySide1 = data.SingleWell;
propertyParam.wellParamSettings.DeployAgain = false; // 标记二次布井
propertyParam.calcParamSettings.WellsSpace = data.WellSpace;
propertyParam.calcParamSettings.MutationRate = data.MutationRate;
propertyParam.calcParamSettings.Rotations = data.RotationTimes;
propertyParam.calcParamSettings.AngleStart = data.AngularRangeMin;
propertyParam.calcParamSettings.AngleEnd = data.AngularRangeMax;
propertyParam.calcParamSettings.SpecifyAngles = data.IsAngleRange;
1 month ago
propertyParam.calcParamSettings.SpeciaAngles = data.AngleRangeValue; // 角度范围值
1 month ago
propertyParam.calcParamSettings.IgnoreMiniFault = data.IsSmallFracture;
propertyParam.calcParamSettings.MiniFaultLength = data.SmallFractureValue;
});
};
onBeforeUnmount(() => {
1 month ago
emitter.off(EMIT_COMMAND.SELECTED_LAYER);
emitter.off(EMIT_COMMAND.CALC_PROPERTY);
handleStopCalc(true);
1 month ago
});
const handleClose = () => {
showLayer.value = false;
};
// 获取断裂图件
const getFractureFileList = async () => {
let response = await fractureFileList();
if (response) {
fractureFileData.value = response;
}
1 month ago
};
const onComplete = () => {
1 month ago
};
</script>
<style scoped>
.scrollable-form {
/* max-height: 900px; */
1 month ago
min-height: 500px;
1 month ago
width: 290px;
height: 100%;
}
.well-param-item {
height: 25px;
}
.well-param-input {
width: 140px;
height: 25px;
}
.button-container {
display: flex;
justify-content: flex-end;
margin-right: 30px;
1 month ago
margin-bottom: 20px;
1 month ago
}
.other-form-item {
display: inline-flex;
flex-direction: row;
justify-content: flex-start;
gap: 10px;
}
.other-form-item-nolabel {
display: inline-flex;
flex-direction: row;
padding-left: 65px;
justify-content: flex-start;
}
.img-layer {
1 month ago
height: 500px;
1 month ago
background: #ccc;
border: 1px solid #333;
1 month ago
overflow: hidden;
1 month ago
}
.popup-tree {
1 month ago
height: 500px;
1 month ago
width: 100%;
}
</style>