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.

502 lines
19 KiB
Vue

1 month ago
<template>
<div class="draw-container">
<div class="oper">
<el-button type="primary" :icon="DocumentCopy" @click="ApplyParameter"></el-button>
</div>
<!-- 右侧参数栏 -->
<el-form :model="currentProject.projectParameter" style="max-width: 300px">
<el-form-item style="margin-bottom: 0px;margin-left: 5px;">
<el-col :span="5">
<el-checkbox label="井轨迹" v-model="currentProject.projectParameter.DrawTrack" />
</el-col>
<el-col :offset="1" :span="7">
<el-checkbox label="关节点" v-model="currentProject.projectParameter.DrawPoint" />
</el-col>
<el-col :offset="1" :span="10">
<el-form-item :label="currentProject.projectParameter.DrawGradient ? '曲线' : '柱子'"
:onClick="ApplyParameter">
<el-switch v-model="currentProject.projectParameter.DrawGradient" />
</el-form-item>
</el-col>
</el-form-item>
<el-form-item style="margin-bottom: 0px;margin-left: 5px;">
<el-col :span="5">
<el-checkbox label="分段" v-model="currentProject.projectParameter.DrawStage" />
</el-col>
<el-col :offset="1" :span="10">
<el-form-item label="名称大小">
<el-input-number :min="minValue" :max="maxValue"
v-model="currentProject.projectParameter.StageTextSize" size="small" :controls="false"
:tips="true" />
</el-form-item>
</el-col>
<el-col :offset="1" :span="7">
<el-form-item label="宽度">
<el-input-number :min="minValue" :max="maxValue"
v-model="currentProject.projectParameter.StageWidth" size="small" :controls="false" />
</el-form-item>
</el-col>
</el-form-item>
<el-form-item style="margin-bottom: 0px;margin-left: 5px;">
<el-col :span="5">
<el-checkbox label="参数值" v-model="currentProject.projectParameter.DrawParamText" />
</el-col>
<el-col :offset="1" :span="10">
<el-form-item label="文字大小">
<el-input-number :min="minValue" :max="maxValue"
v-model="currentProject.projectParameter.ParamTextSize" size="small" :controls="false" />
</el-form-item>
</el-col>
</el-form-item>
<el-form-item style="margin-bottom: 0px;margin-left: 5px;">
<el-col :span="11">
<el-form-item :label="(currentProject.projectParameter.DrawGradient
? '曲线'
: '柱子') + '高度'
">
<el-input-number :min="minValue" :max="maxValue"
v-model="currentProject.projectParameter.ColumnHeighFactor" size="small"
style="width: 60px;" :controls="false" />
</el-form-item>
</el-col>
<el-col :span="11" :offset="1">
<el-form-item :label="(currentProject.projectParameter.DrawGradient
? '曲线'
: '柱子') + '宽度'
" v-if="!currentProject.projectParameter.DrawGradient">
<el-input-number :min="minValue" :max="maxValue"
v-model="currentProject.projectParameter.PillarWidth" size="small" style="width: 60px"
:controls="false" v-if="!currentProject.projectParameter.DrawGradient" />
</el-form-item>
</el-col>
</el-form-item>
<!-- <el-form-item>
</el-form-item> -->
</el-form>
<el-tabs v-model="activeTab" :stretch="true">
<el-tab-pane name="fractureParam" label="压裂参数" ref="fractureParamTab">
<el-table ref="fractureParamTableRef" row-key="PillarName" :data="fractureParamDatas"
@selection-change="handleFranctureSelection" style="padding: 0;margin: 0;">
<el-table-column type="selection" width="40px"></el-table-column>
<el-table-column prop="PillarName" label="名称" width="*" show-overflow-tooltip>
<template #default="scope">
<div :style="{ padding: '0' }">{{ scope.row.PillarName }}</div>
</template>
</el-table-column>
<el-table-column Align="center" v-if="false" prop="PillarWidth" label="宽度" width="50px">
<template #default="scope">
<div :style="{ padding: '0' }">
<el-input-number style="width: 50px" :min="minValue" :max="maxValue"
v-model="scope.row.PillarWidth" size="small" :controls="false">
</el-input-number>
</div>
</template>
</el-table-column>
<el-table-column prop="Position" label="位置" width="55">
<template #default="scope">
<div :style="{ padding: '0' }">
<el-radio-group v-model="scope.row.Position">
<el-radio :value="true" size="small"></el-radio>
<el-radio :value="false" size="small"></el-radio>
</el-radio-group>
</div>
</template>
</el-table-column>
<el-table-column prop="StandValue" label="最小值" width="70">
<template #default="scope">
<div :style="{ padding: '0' }">
<el-input-number style="width: 50px" :min="minValue" :max="maxValue"
v-model="scope.row.StandValue" size="small" :controls="false">
</el-input-number>
</div>
</template>
</el-table-column>
<el-table-column prop="ColumnHeighFactor" v-if="false" label="高度" width="100">
<template #default="scope">
<el-input-number style="width: 60px" :min="minValue" :max="maxValue"
v-model="scope.row.ColumnHeighFactor" size="small" :controls="false">
</el-input-number>
</template>
</el-table-column>
<el-table-column prop="ColorValue" label="颜色" width="55">
<template #default="scope">
<div :style="{ padding: '0' }">
<el-color-picker v-model="scope.row.ColorValue" color-format="hex" />
</div>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="wellDeflectionData" label="井斜数据" ref="wellDeflectionDataTab">
<el-table ref="wellDeflectionDataTableRef" row-key="PillarName" :data="wellDeflectionDatas"
@selection-change="handleWellDeflectionDataSelection">
<el-table-column type="selection" width="40"></el-table-column>
<el-table-column prop="PillarName" label="名称" width="*" show-overflow-tooltip>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="fracturingSectiondata" label="压裂段数据" ref="fracturingSectionDataTab">
<el-table ref="fracturingSectionDataTableRef" row-key="PillarName" :data="fracturingSectionDatas"
@selection-change="handleFracturingSectionDataSelection">
<el-table-column type="selection" width="40"></el-table-column>
<el-table-column prop="PillarName" label="名称" width="*" show-overflow-tooltip>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<LoadingDialog v-model="loading" ref="loadingRef" :timeout="150000" message="正在应用参数……" @timeout="onTimeout" />
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeMount } from 'vue';
import { DocumentCopy } from "@element-plus/icons-vue";
import { emitter } from "~/utils/eventBus";
import { fetchAllWell } from '~/services/projectService'
import { fetchCalcHoriWellFracturCoord, updateParameter } from '~/services/horizontalWellService'
const { $toastMessage } = useNuxtApp();
import { STORAGE_KEYS } from "~/utils/storageKeys"
import { EMIT_COMMAND } from '~/utils/commandTypes';
// 当前页图件token的 key
const currentTokenKey = STORAGE_KEYS.HORIZONTAL_WELL_TOKEN;
const loading = ref(false);
const loadingRef = ref(null);
/** 默认项目参数 */
const defaultProjectParameter = reactive({
/** 井轨迹 */
DrawTrack: true,
/** 关节点 */
DrawPoint: true,
/** 显示方式(柱子,曲线) */
DrawGradient: false,
/** 分段 */
DrawStage: true,
/** 参数值 */
DrawParamText: true,
/** 名称大小 */
StageTextSize: 10,
/** 文字大小 */
ParamTextSize: 5,
/** 分段宽度 */
StageWidth: 20,
/** 高度 */
ColumnHeighFactor: 10,
/** 宽度 */
PillarWidth: 10,
});
const currentProject = reactive({
ID: 0,
DrawId: "",
LayerName: "",
LayerAlias: "",
DrawerFileName: "",
/** 绘制参数配置 */
projectParameter: { ...defaultProjectParameter },
});
const minValue = 1;
const maxValue = 500;
// 压裂参数
const activeTab = ref("fractureParam");
const fractureParamTab = ref(null);
const fractureParamTableRef = ref(null);
const fractureParamSelected = ref([]);
const fractureParamDatas = ref([]);
// 井斜数据
const wellDeflectionDataTab = ref(null);
const wellDeflectionDataTableRef = ref(null);
const wellDeflectionDataSelected = ref([]);
const wellDeflectionDatas = ref([]);
// 压裂段数据
const fracturingSectionDataTab = ref(null);
const fracturingSectionDataTableRef = ref(null);
const fracturingSectionDataSelected = ref([]);
const fracturingSectionDatas = ref([]);
const onTimeout = (() => {
$toastMessage.error("应用参数计算超时……");
})
const ApplyParameter = async () => {
if (currentProject.ID === undefined || currentProject.ID === 0) {
$toastMessage.warning("请选择一个项目!");
return;
}
try {
loading.value = true;
let config = currentProject.projectParameter;
let pillarParams = Array.from(
new Set(
fractureParamSelected.value.map(
(p) =>
`${p.PillarName}@${config.PillarWidth ?? 10}@${p.Position}@${p.StandValue ?? 0
}@${config.ColumnHeighFactor ?? 10}@${p.ColorValue}`
)
)
);
let displayPillarArray = [];
for (const param of fractureParamSelected.value) {
if (displayPillarArray.indexOf(param.PillarName) === -1) {
displayPillarArray.push(param.PillarName);
}
}
let displayWellArray = [];
for (const param of wellDeflectionDataSelected.value) {
if (displayWellArray.indexOf(param.PillarName) === -1) {
displayWellArray.push(param.PillarName);
}
}
config.PillarParams = pillarParams.join("|");
config.DisplayWells = displayWellArray.join(",");
config.DisplayPillars = displayPillarArray.join(",");
config.DrawId = localStorage.getItem(currentTokenKey) || generateGUID();
config.ClientID = config.DrawId;
const response = await updateParameter(config);
if (response) {
emitter.emit(EMIT_COMMAND.EVT_TYPE, { type: EMIT_COMMAND.VIEW_ALL, cmdID: currentTokenKey, data: JSON.stringify({ drawerToken: config.DrawId }) });
} else {
$toastMessage.error(`应用参数失败!`);
}
} catch (error) {
console.error(`应用参数错误:${error}`);
$toastMessage.error(`应用参数错误:${error}`);
} finally {
loadingRef.value.close();
}
};
const handleFranctureSelection = (selection) => {
fractureParamSelected.value = selection;
};
const handleWellDeflectionDataSelection = (selection) => {
wellDeflectionDataSelected.value = selection;
};
const handleFracturingSectionDataSelection = (selection) => {
fracturingSectionDataSelected.value = selection;
};
const updateParameters = async () => {
if (currentProject.projectParameter != null) {
const strParameter = currentProject.projectParameter.PillarParams;
await fetchParameters(strParameter);
if (currentProject.projectParameter.DisplayPillars) {
let displayPillars = currentProject.projectParameter.DisplayPillars
.split(",")
.filter((item) => item !== "");
fractureParamDatas.value.forEach((row) => {
if (
displayPillars.indexOf(row.PillarName) > -1 &&
fractureParamSelected.value.indexOf(row) === -1
) {
// fractureParamSelected.value.push(row);
fractureParamTableRef.value.toggleRowSelection(row);
}
});
}
if (currentProject.projectParameter.DisplayWells) {
let displayWells = currentProject.projectParameter.DisplayWells
.split(",")
.filter((item) => item !== "");
await fetchAllWellParam(2);// 参数1井斜2压裂段
fracturingSectionDatas.value.forEach((row) => {
if (
displayWells.indexOf(row.PillarName) > -1 &&
fracturingSectionDataSelected.value.indexOf(row) === -1
) {
// fracturingSectionDataSelected.value.push(row);
fracturingSectionDataTableRef.value.toggleRowSelection(row);
}
});
await fetchAllWellParam(1);
wellDeflectionDatas.value.forEach((row) => {
if (
displayWells.indexOf(row.PillarName) > -1 &&
wellDeflectionDataSelected.value.indexOf(row) === -1
) {
// fracturingSectionDataSelected.value.push(row);
wellDeflectionDataTableRef.value.toggleRowSelection(row);
}
});
}
} else {
await fetchParameters();
// await fetchAllWellParam(2);
// await fetchAllWellParam(1);
}
};
/** 获取压裂参数 */
const fetchParameters = async (strParameter) => {
fractureParamDatas.value = [];
if (strParameter) {
// 加载参数配置
const para = strParameter
.split("|")
.map((pair) => pair.split("@"))
.filter((parts) => parts.length === 6)
.map((parts) => ({
PillarName: parts[0],
PillarWidth: parseInt(parts[1]),
Position: (parts[2] + "").toLowerCase() === "true",
StandValue: parseFloat(parts[3]),
ColumnHeighFactor: parseInt(parts[4]),
ColorValue: parts[5],
}));
para.forEach((item) => {
fractureParamDatas.value.push(item);
});
return;
}
let records = await fetchCalcHoriWellFracturCoord();
if (records.length === 0) {
return;
}
let paramNames = [];
for (const item of records) {
if (paramNames.indexOf(item) == -1) {
paramNames.push(item);
}
}
for (const name of paramNames) {
fractureParamDatas.value.push({
PillarName: name,
PillarWidth: 10,
Position: true,
StandValue: 0,
ColumnHeighFactor: 10,
ColorValue: getRandomHexColor(),
});
}
};
const getRandomHexColor = () => {
// 生成随机的红色、绿色和蓝色分量
const r = Math.floor(Math.random() * 256); // 0 到 255
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
// 将十进制颜色分量转换为十六进制并拼接成颜色代码
const hexColor = `#${r.toString(16).padStart(2, "0")}${g
.toString(16)
.padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
return hexColor;
};
/** 获取井斜/压裂段数据 */
const fetchAllWellParam = async (wtype, strParameter) => {
if (strParameter) {
// 加载参数配置
const para = strParameter
.map((parts) => ({
PillarName: parts[0]
}));
switch (wtype) {
case 2:
fracturingSectionDatas.value = [];
break;
case 1:
wellDeflectionDatas.value = [];
break;
}
para.forEach((item) => {
switch (wtype) {
case 2:
fracturingSectionDatas.value.push(item);
break;
case 1:
wellDeflectionDatas.value.push(item);
break;
}
});
return;
}
let records = await fetchAllWell(wtype);
if (records.length === 0) {
return;
}
let paramNames = [];
for (const item of records) {
if (paramNames.indexOf(item) == -1) {
paramNames.push(item);
}
}
for (const name of paramNames) {
const data = {
PillarName: name
};
switch (wtype) {
case 2:
fracturingSectionDatas.value.push(data);
break;
case 1:
wellDeflectionDatas.value.push(data);
break;
}
}
};
onMounted(async () => {
listenProjectParam();
await updateParameters();
await fetchAllWellParam(2);
await fetchAllWellParam(1);
});
const listenProjectParam = (() => {
emitter.on(EMIT_COMMAND.PROJECT_PARAM, async (data) => {
currentProject.ID = data.ID;
Object.assign(currentProject.projectParameter, data.projectParameter);
await updateParameters();
});
});
onUnmounted(() => {
emitter.off(EMIT_COMMAND.PROJECT_PARAM);
});
</script>
<style scoped>
.draw-container {
background: #fff;
width: 100%;
height: calc(100vh - 62px);
overflow: auto;
}
.oper {
width: 100%;
height: 40px;
margin: 0;
padding-left: 10px;
padding-top: 10px;
}
:deep(.el-input-number .el-input__inner) {
padding-left: 0 !important;
padding-right: 0 !important;
}
</style>