Commit 4059f610 by zhaopanyu

zpy

parent a673af2c
...@@ -251,7 +251,7 @@ export const constantRoutes = [ ...@@ -251,7 +251,7 @@ export const constantRoutes = [
component: () => component: () =>
import("@/views/wellDesign/components/BitDesignRecommendation"), import("@/views/wellDesign/components/BitDesignRecommendation"),
name: "BitDesignRecommendation", name: "BitDesignRecommendation",
meta: { title: "钻头设计推荐方案", icon: "tool", noCache: true }, meta: { title: "钻头设计参数推荐", icon: "tool", noCache: true },
}, },
{ {
path: "bit-matching", path: "bit-matching",
......
<template> <template>
<div class="drilling-chart-container"> <div class="drilling-chart-container">
<div class="chart-wrapper">
<el-button type="primary" icon="el-icon-download" size="small" class="export-btn" @click="exportChart"
:disabled="!myChart">
导出图片
</el-button>
<div id="drillingEfficiencyChartdj" class="chart"></div> <div id="drillingEfficiencyChartdj" class="chart"></div>
</div>
<!-- <div class="optimal-values"> <!-- <div class="optimal-values">
<div class="optimal-item"> <div class="optimal-item">
<span class="label">机速最优:</span> <span class="label">机速最优:</span>
...@@ -107,6 +113,13 @@ export default { ...@@ -107,6 +113,13 @@ export default {
// 折线数据必须为数组格式:[[钻速, 进尺], ...] // 折线数据必须为数组格式:[[钻速, 进尺], ...]
const targetLine = targetLineData.map(item => [item.speed, item.depth]); const targetLine = targetLineData.map(item => [item.speed, item.depth]);
const drillTypes = [...new Set(scatterData.map(item => item.drillType))]; const drillTypes = [...new Set(scatterData.map(item => item.drillType))];
// 定义颜色数组,为不同钻头型号分配不同颜色
const colorPalette = [
'#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de',
'#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#ff9f7f',
'#ffdb5c', '#c4ccd3', '#4ea397', '#22c3aa', '#7bd9a5',
'#d0648a', '#f0a1a8', '#f7c369', '#4d79a4', '#e15b64'
];
// 十字线及中心点配置 // 十字线及中心点配置
const crosshairLines = []; const crosshairLines = [];
const crosshairCenter = []; const crosshairCenter = [];
...@@ -169,7 +182,7 @@ export default { ...@@ -169,7 +182,7 @@ export default {
} }
}, },
legend: { legend: {
data: ['指标', '钻速均值', '进尺均值', '优化曲线',], data: ['优化曲线', '钻速均值', '进尺均值'],
top: '10%', top: '10%',
right: '5%' right: '5%'
}, },
...@@ -185,10 +198,10 @@ export default { ...@@ -185,10 +198,10 @@ export default {
type: 'value', type: 'value',
min: axisRange.xAxis.min, min: axisRange.xAxis.min,
max: axisRange.xAxis.max, max: axisRange.xAxis.max,
interval: axisRange.xAxis.interval, // interval: axisRange.xAxis.interval,
axisLabel: { formatter: '{value} m/h' }, axisLabel: { formatter: '{value} m/h' },
nameLocation: 'center', nameLocation: 'center',
nameGap: 30, nameGap: 50,
axisTick: { show: true }, axisTick: { show: true },
axisLine: { show: true } axisLine: { show: true }
}, },
...@@ -196,7 +209,7 @@ export default { ...@@ -196,7 +209,7 @@ export default {
name: '进尺m', name: '进尺m',
type: 'value', type: 'value',
min: axisRange.yAxis.min, min: axisRange.yAxis.min,
interval: axisRange.yAxis.interval, // interval: axisRange.yAxis.interval,
nameLocation: 'center', nameLocation: 'center',
nameGap: 40, nameGap: 40,
axisTick: { show: true }, axisTick: { show: true },
...@@ -232,17 +245,19 @@ export default { ...@@ -232,17 +245,19 @@ export default {
}, },
...crosshairLines, ...crosshairLines,
...crosshairCenter, ...crosshairCenter,
...drillTypes.map(type => ({ ...drillTypes.map((type, index) => {
const color = colorPalette[index % colorPalette.length];
return {
name: type, name: type,
type: 'scatter', type: 'scatter',
data: scatter.filter(item => item[2] === type), data: scatter.filter(item => item[2] === type),
symbolSize: 12, symbolSize: 12,
itemStyle: { itemStyle: {
color: 'blue', color: color,
borderColor: 'red', borderColor: color,
borderWidth: 3, borderWidth: 2,
shadowColor: 'red', shadowColor: color,
shadowBlur: 8 shadowBlur: 6
}, },
label: { label: {
show: true, show: true,
...@@ -251,7 +266,8 @@ export default { ...@@ -251,7 +266,8 @@ export default {
fontSize: 10, fontSize: 10,
color: '#333' color: '#333'
} }
})) };
})
] ]
}; };
...@@ -261,6 +277,34 @@ export default { ...@@ -261,6 +277,34 @@ export default {
window.addEventListener('resize', this.resizeHandler); window.addEventListener('resize', this.resizeHandler);
}, },
exportChart() {
if (!this.myChart) {
this.$message.warning('图表未初始化,无法导出');
return;
}
try {
// 获取图表的 base64 图片数据
const url = this.myChart.getDataURL({
type: 'png',
pixelRatio: 2, // 提高图片清晰度
backgroundColor: '#fff'
});
// 创建下载链接
const link = document.createElement('a');
link.href = url;
link.download = `钻头钻进能效分析_${this.jh}_${new Date().getTime()}.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('图片导出成功');
} catch (error) {
console.error('导出图片失败:', error);
this.$message.error('导出图片失败,请重试');
}
},
cleanup() { cleanup() {
if (this.myChart) { if (this.myChart) {
this.myChart.dispose(); this.myChart.dispose();
...@@ -396,12 +440,26 @@ export default { ...@@ -396,12 +440,26 @@ export default {
opacity: 0.3; opacity: 0.3;
} }
.chart { .chart-wrapper {
position: relative;
width: 100%; width: 100%;
height: calc(100vh - 220px); height: calc(100vh - 220px);
min-height: 600px; min-height: 600px;
} }
.chart {
width: 100%;
height: 100%;
}
.export-btn {
position: absolute;
top: 10px;
right: 10px;
z-index: 100;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.data-table { .data-table {
width: 100%; width: 100%;
margin-top: 20px; margin-top: 20px;
......
...@@ -3,7 +3,13 @@ ...@@ -3,7 +3,13 @@
<div class="chart-layout"> <div class="chart-layout">
<div id="mainzftdj" class="chart" ref="chartRef"></div> <div id="mainzftdj" class="chart" ref="chartRef"></div>
<aside v-if="legendItems && legendItems.length" class="strata-legend"> <aside v-if="legendItems && legendItems.length" class="strata-legend">
<div class="legend-header">层位图例</div> <div class="legend-header">
<span>层位图例</span>
<el-button class="export-btn" @click="exportChart" :disabled="loading || !myChart" title="导出图表为图片"
icon="el-icon-download" size="small">
导出
</el-button>
</div>
<div class="legend-list"> <div class="legend-list">
<div v-for="(item, index) in legendItems" :key="item.name || index" class="legend-item"> <div v-for="(item, index) in legendItems" :key="item.name || index" class="legend-item">
<div class="legend-icon" :style="getLegendSwatchStyle(item)"></div> <div class="legend-icon" :style="getLegendSwatchStyle(item)"></div>
...@@ -460,7 +466,7 @@ export default { ...@@ -460,7 +466,7 @@ export default {
} }
}, },
grid: { grid: {
top: 10, top: 20,
left: "2%", left: "2%",
right: "3%", right: "3%",
bottom: "10%", bottom: "10%",
...@@ -610,10 +616,10 @@ export default { ...@@ -610,10 +616,10 @@ export default {
data: xAxisLabels, data: xAxisLabels,
axisLabel: { axisLabel: {
interval: 0, interval: 0,
rotate: 0, rotate: -90,
margin: 12, margin: 30,
align: "center", align: "center",
fontSize: 13, fontSize: 12,
color: colors.text, color: colors.text,
fontWeight: 500, fontWeight: 500,
formatter: formatLabel formatter: formatLabel
...@@ -691,7 +697,7 @@ export default { ...@@ -691,7 +697,7 @@ export default {
color: colors.text, color: colors.text,
fontSize: 13, fontSize: 13,
fontWeight: 600, fontWeight: 600,
padding: [0, 8, 0, 0] padding: [0, 8, 0, 55]
}, },
min: chartConfig.yAxis2.min, min: chartConfig.yAxis2.min,
max: chartConfig.yAxis2.max, max: chartConfig.yAxis2.max,
...@@ -1088,7 +1094,7 @@ export default { ...@@ -1088,7 +1094,7 @@ export default {
return; return;
} }
const midX = (pxStart + pxEnd) / 2; const midX = (pxStart + pxEnd) / 2;
let topY = yTopPx - 30; // 再上移,避免遮挡 let topY = yTopPx - 80; // 再上移,提升显示位置
// 估算标签宽度用于避免与上一个重叠 // 估算标签宽度用于避免与上一个重叠
const fontSize = 12; const fontSize = 12;
...@@ -1185,11 +1191,11 @@ export default { ...@@ -1185,11 +1191,11 @@ export default {
} }
const yTopPx = Math.min(yMinPx, yMaxPx); const yTopPx = Math.min(yMinPx, yMaxPx);
const yBottomPx = Math.max(yMinPx, yMaxPx); const yBottomPx = Math.max(yMinPx, yMaxPx);
// 只在上方画短竖线:长度占绘图区高度的 12%,并限制在 30-120 像素 // 只在上方画短竖线:长度占绘图区高度的 6%,并限制在 15-60 像素
const plotHeight = Math.abs(yBottomPx - yTopPx); const plotHeight = Math.abs(yBottomPx - yTopPx);
const stemLen = Math.max(30, Math.min(120, plotHeight * 0.12)); const stemLen = Math.max(15, Math.min(60, plotHeight * 0.06));
// 仅保留上方的线:整段都在 top 之上 // 仅保留上方的线:整段都在 top 之上
const extraHead = Math.max(10, Math.min(60, plotHeight * 0.05)); const extraHead = Math.max(6, Math.min(30, plotHeight * 0.03));
const yStemStart = yTopPx - (extraHead + stemLen); const yStemStart = yTopPx - (extraHead + stemLen);
const yStemEnd = yTopPx - 1; const yStemEnd = yTopPx - 1;
...@@ -1247,36 +1253,6 @@ export default { ...@@ -1247,36 +1253,6 @@ export default {
zlevel: 10 zlevel: 10
}); });
// 顶部段标签:第一个段使用第一个 x 标签,之后每个段用对应中心的标签
const boundaries = [firstEdge];
for (let i = 0; i < centers.length - 1; i++) {
boundaries.push((centers[i] + centers[i + 1]) / 2);
}
const labelY = yStemStart - 8;
for (let i = 0; i < boundaries.length - 1; i++) {
const midX = (boundaries[i] + boundaries[i + 1]) / 2;
const label = String(xAxisLabels[i] ?? '');
const displayLabel = this.formatXAxisLabel(label);
graphics.push({
type: 'text',
position: [midX, labelY],
style: {
text: displayLabel,
fontSize: 12,
fontWeight: 600,
fill: '#333',
backgroundColor: 'rgba(255,255,255,0.85)',
padding: [2, 4],
borderRadius: 4,
align: 'center',
verticalAlign: 'bottom'
},
z: 121,
zlevel: 10,
silent: true,
bounding: 'raw'
});
}
} }
const prev = Array.isArray(this.currentGraphicElements) ? this.currentGraphicElements : []; const prev = Array.isArray(this.currentGraphicElements) ? this.currentGraphicElements : [];
...@@ -1411,6 +1387,41 @@ export default { ...@@ -1411,6 +1387,41 @@ export default {
this.myChart.setOption({ graphic: { elements: merged } }, { replaceMerge: ['graphic'] }); this.myChart.setOption({ graphic: { elements: merged } }, { replaceMerge: ['graphic'] });
} }
}); });
},
// 导出图表为图片
exportChart() {
if (!this.myChart) {
this.$message.warning('图表尚未加载完成,请稍候再试');
return;
}
try {
// 获取图表图片数据
const dataURL = this.myChart.getDataURL({
type: 'png',
pixelRatio: 2, // 提高图片清晰度
backgroundColor: '#fff'
});
// 创建下载链接
const link = document.createElement('a');
const fileName = this.jh ? `直方图_${this.jh}_${new Date().getTime()}.png` : `直方图_${new Date().getTime()}.png`;
link.href = dataURL;
link.download = fileName;
link.style.display = 'none';
// 触发下载
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('图表导出成功');
} catch (error) {
console.error('导出图表失败:', error);
this.$message.error('导出图表失败,请稍候再试');
}
} }
}, },
}; };
...@@ -1460,6 +1471,10 @@ export default { ...@@ -1460,6 +1471,10 @@ export default {
color: #1f2937; color: #1f2937;
border-bottom: 1px solid rgba(15, 23, 42, 0.08); border-bottom: 1px solid rgba(15, 23, 42, 0.08);
padding-bottom: 8px; padding-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
} }
.legend-list { .legend-list {
...@@ -1516,6 +1531,41 @@ export default { ...@@ -1516,6 +1531,41 @@ export default {
opacity: 0.9; opacity: 0.9;
} }
/* 导出按钮样式 */
::v-deep .export-btn {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
color: #fff !important;
border: none !important;
border-radius: 6px !important;
padding: 6px 14px !important;
font-size: 13px !important;
font-weight: 500 !important;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3) !important;
transition: all 0.3s ease !important;
}
::v-deep .export-btn:hover:not(:disabled) {
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%) !important;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4) !important;
transform: translateY(-1px) !important;
}
::v-deep .export-btn:active:not(:disabled) {
transform: translateY(0) !important;
box-shadow: 0 2px 6px rgba(59, 130, 246, 0.3) !important;
}
::v-deep .export-btn:disabled {
background: #9ca3af !important;
cursor: not-allowed !important;
opacity: 0.6 !important;
box-shadow: none !important;
}
::v-deep .export-btn .el-icon-download {
color: #fff !important;
}
.well-number-display:hover { .well-number-display:hover {
opacity: 1; opacity: 1;
} }
...@@ -1602,6 +1652,11 @@ export default { ...@@ -1602,6 +1652,11 @@ export default {
min-height: 300px; min-height: 300px;
border-radius: 12px; border-radius: 12px;
} }
.export-btn {
padding: 4px 8px;
font-size: 12px;
}
} }
/* 深色模式支持 */ /* 深色模式支持 */
......
<template> <template>
<div class="drilling-chart-container" v-loading="loading" element-loading-text="加载中..." <div class="drilling-chart-container" v-loading="loading" element-loading-text="加载中..."
element-loading-background="rgba(255, 255, 255, 0.7)"> element-loading-background="rgba(255, 255, 255, 0.7)">
<div class="chart-wrapper">
<el-button type="primary" icon="el-icon-download" size="small" class="export-btn" @click="exportChart"
:disabled="!myChart">
导出图片
</el-button>
<div id="drillingEfficiencyChartdj" class="chart"></div> <div id="drillingEfficiencyChartdj" class="chart"></div>
</div>
<!-- <div class="optimal-values"> <!-- <div class="optimal-values">
<div class="optimal-item"> <div class="optimal-item">
<span class="label">机速最优:</span> <span class="label">机速最优:</span>
<span class="value">{{ (chartData && chartData.jxzszy) || '--' }}</span> <span class="value">{{ (chartData && chartData.jxzszy) || '--' }}</span>
</div> </div>
<div class="optimal-item"> <div class="optimal-item"></div>
<span class="label">进尺最优:</span> <span class="label">进尺最优:</span>
<span class="value">{{ (chartData && chartData.jczy) || '--' }}</span> <span class="value">{{ (chartData && chartData.jczy) || '--' }}</span>
</div> </div>
...@@ -147,6 +153,11 @@ export default { ...@@ -147,6 +153,11 @@ export default {
// 折线数据必须为数组格式:[[钻速, 进尺], ...] // 折线数据必须为数组格式:[[钻速, 进尺], ...]
const targetLine = targetLineData.map(item => [item.speed, item.depth]); const targetLine = targetLineData.map(item => [item.speed, item.depth]);
const drillTypes = [...new Set(scatterData.map(item => item.drillType))]; const drillTypes = [...new Set(scatterData.map(item => item.drillType))];
const colorPalette = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#14b8a6', '#ec4899', '#6366f1', '#f97316', '#0ea5e9'];
const typeColorMap = drillTypes.reduce((acc, type, index) => {
acc[type] = colorPalette[index % colorPalette.length];
return acc;
}, {});
// 十字线及中心点配置 // 十字线及中心点配置
const crosshairLines = []; const crosshairLines = [];
const crosshairCenter = []; const crosshairCenter = [];
...@@ -224,7 +235,7 @@ export default { ...@@ -224,7 +235,7 @@ export default {
type: 'value', type: 'value',
min: axisRange.xAxis.min, min: axisRange.xAxis.min,
max: axisRange.xAxis.max, max: axisRange.xAxis.max,
interval: axisRange.xAxis.interval, // interval: axisRange.xAxis.interval,
axisLabel: { formatter: '{value} m/h' }, axisLabel: { formatter: '{value} m/h' },
nameLocation: 'center', nameLocation: 'center',
nameGap: 30, nameGap: 30,
...@@ -235,7 +246,7 @@ export default { ...@@ -235,7 +246,7 @@ export default {
name: '进尺m', name: '进尺m',
type: 'value', type: 'value',
min: axisRange.yAxis.min, min: axisRange.yAxis.min,
interval: axisRange.yAxis.interval, // interval: axisRange.yAxis.interval,
nameLocation: 'center', nameLocation: 'center',
nameGap: 40, nameGap: 40,
axisTick: { show: true }, axisTick: { show: true },
...@@ -271,16 +282,18 @@ export default { ...@@ -271,16 +282,18 @@ export default {
}, },
...crosshairLines, ...crosshairLines,
...crosshairCenter, ...crosshairCenter,
...drillTypes.map(type => ({ ...drillTypes.map(type => {
const color = typeColorMap[type];
return {
name: type, name: type,
type: 'scatter', type: 'scatter',
data: scatter.filter(item => item[2] === type), data: scatter.filter(item => item[2] === type),
symbolSize: 12, symbolSize: 12,
itemStyle: { itemStyle: {
color: 'blue', color,
borderColor: 'red', borderColor: color,
borderWidth: 3, borderWidth: 3,
shadowColor: 'red', shadowColor: color,
shadowBlur: 8 shadowBlur: 8
}, },
label: { label: {
...@@ -288,9 +301,10 @@ export default { ...@@ -288,9 +301,10 @@ export default {
position: 'top', position: 'top',
formatter: type, formatter: type,
fontSize: 10, fontSize: 10,
color: '#333' color
} }
})) };
})
] ]
}; };
...@@ -300,6 +314,34 @@ export default { ...@@ -300,6 +314,34 @@ export default {
window.addEventListener('resize', this.resizeHandler); window.addEventListener('resize', this.resizeHandler);
}, },
exportChart() {
if (!this.myChart) {
this.$message.warning('图表未初始化,无法导出');
return;
}
try {
// 获取图表的 base64 图片数据
const url = this.myChart.getDataURL({
type: 'png',
pixelRatio: 2, // 提高图片清晰度
backgroundColor: '#fff'
});
// 创建下载链接
const link = document.createElement('a');
link.href = url;
link.download = `钻头钻进能效分析_${this.jh}_${new Date().getTime()}.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('图片导出成功');
} catch (error) {
console.error('导出图片失败:', error);
this.$message.error('导出图片失败,请重试');
}
},
cleanup() { cleanup() {
if (this.myChart) { if (this.myChart) {
this.myChart.dispose(); this.myChart.dispose();
...@@ -454,12 +496,26 @@ export default { ...@@ -454,12 +496,26 @@ export default {
opacity: 0.3; opacity: 0.3;
} }
.chart { .chart-wrapper {
position: relative;
width: 100%; width: 100%;
height: calc(100vh - 220px); height: calc(100vh - 220px);
min-height: 600px; min-height: 600px;
} }
.chart {
width: 100%;
height: 100%;
}
.export-btn {
position: absolute;
top: 10px;
right: 10px;
z-index: 100;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.table-section { .table-section {
margin-top: 20px; margin-top: 20px;
padding: 20px; padding: 20px;
......
...@@ -4,8 +4,14 @@ ...@@ -4,8 +4,14 @@
<span class="well-label">井号:</span> <span class="well-label">井号:</span>
<span class="well-number">{{ jh }}</span> <span class="well-number">{{ jh }}</span>
</div> </div>
<div class="chart-wrapper">
<el-button type="primary" icon="el-icon-download" size="small" class="export-btn" @click="exportChart"
:disabled="!myChart">
导出图片
</el-button>
<div id="drillingEfficiencyChart" class="chart"></div> <div id="drillingEfficiencyChart" class="chart"></div>
</div> </div>
</div>
</template> </template>
<script> <script>
...@@ -75,6 +81,11 @@ export default { ...@@ -75,6 +81,11 @@ export default {
// 折线数据必须为数组格式:[[钻速, 进尺], ...] // 折线数据必须为数组格式:[[钻速, 进尺], ...]
const targetLine = targetLineData.map(item => [item.speed, item.depth]); const targetLine = targetLineData.map(item => [item.speed, item.depth]);
const drillTypes = [...new Set(scatterData.map(item => item.drillType))]; const drillTypes = [...new Set(scatterData.map(item => item.drillType))];
const colorPalette = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#14b8a6', '#ec4899', '#6366f1', '#f97316', '#0ea5e9'];
const typeColorMap = drillTypes.reduce((acc, type, index) => {
acc[type] = colorPalette[index % colorPalette.length];
return acc;
}, {});
// 十字线及中心点配置 // 十字线及中心点配置
const crosshairLines = []; const crosshairLines = [];
...@@ -199,16 +210,18 @@ export default { ...@@ -199,16 +210,18 @@ export default {
}, },
...crosshairLines, ...crosshairLines,
...crosshairCenter, ...crosshairCenter,
...drillTypes.map(type => ({ ...drillTypes.map(type => {
const color = typeColorMap[type];
return {
name: type, name: type,
type: 'scatter', type: 'scatter',
data: scatter.filter(item => item[2] === type), data: scatter.filter(item => item[2] === type),
symbolSize: 12, symbolSize: 12,
itemStyle: { itemStyle: {
color: 'blue', color,
borderColor: 'red', borderColor: color,
borderWidth: 3, borderWidth: 3,
shadowColor: 'red', shadowColor: color,
shadowBlur: 8 shadowBlur: 8
}, },
label: { label: {
...@@ -216,9 +229,10 @@ export default { ...@@ -216,9 +229,10 @@ export default {
position: 'top', position: 'top',
formatter: type, formatter: type,
fontSize: 10, fontSize: 10,
color: '#333' color
} }
})) };
})
] ]
}; };
...@@ -227,6 +241,34 @@ export default { ...@@ -227,6 +241,34 @@ export default {
window.addEventListener('resize', this.resizeHandler); window.addEventListener('resize', this.resizeHandler);
}, },
exportChart() {
if (!this.myChart) {
this.$message.warning('图表未初始化,无法导出');
return;
}
try {
// 获取图表的 base64 图片数据
const url = this.myChart.getDataURL({
type: 'png',
pixelRatio: 2, // 提高图片清晰度
backgroundColor: '#fff'
});
// 创建下载链接
const link = document.createElement('a');
link.href = url;
link.download = `钻头钻进能效分析_${this.jh}_${new Date().getTime()}.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('图片导出成功');
} catch (error) {
console.error('导出图片失败:', error);
this.$message.error('导出图片失败,请重试');
}
},
cleanup() { cleanup() {
if (this.myChart) { if (this.myChart) {
this.myChart.dispose(); this.myChart.dispose();
...@@ -384,12 +426,26 @@ export default { ...@@ -384,12 +426,26 @@ export default {
opacity: 0.3; opacity: 0.3;
} }
.chart { .chart-wrapper {
position: relative;
width: 100%; width: 100%;
height: calc(100vh - 230px); height: calc(100vh - 230px);
min-height: 600px; min-height: 600px;
} }
.chart {
width: 100%;
height: 100%;
}
.export-btn {
position: absolute;
top: 10px;
right: 10px;
z-index: 100;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
/* 井号显示样式 */ /* 井号显示样式 */
.well-number-display { .well-number-display {
position: absolute; position: absolute;
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
<span class="well-label">井号:</span> <span class="well-label">井号:</span>
<span class="well-number">{{ jh }}</span> <span class="well-number">{{ jh }}</span>
</div> </div>
<div class="export-button-container">
<el-button class="export-btn" @click="exportChart" :disabled="loading || !myChart" title="导出图表为图片"
icon="el-icon-download">
导出
</el-button>
</div>
<div class="chart-layout"> <div class="chart-layout">
<div id="mainzft" class="chart" ref="chartRef"></div> <div id="mainzft" class="chart" ref="chartRef"></div>
<aside v-if="legendItems && legendItems.length" class="strata-legend"> <aside v-if="legendItems && legendItems.length" class="strata-legend">
...@@ -1117,4 +1123,53 @@ export default { ...@@ -1117,4 +1123,53 @@ export default {
transform: translateY(0); transform: translateY(0);
} }
} }
/* 导出按钮样式 */
.export-button-container {
position: absolute;
top: 16px;
right: 16px;
z-index: 5;
}
.export-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
color: #fff;
border: none;
border-radius: 8px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.export-btn:hover:not(:disabled) {
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
transform: translateY(-1px);
}
.export-btn:active:not(:disabled) {
transform: translateY(0);
box-shadow: 0 2px 6px rgba(59, 130, 246, 0.3);
}
.export-btn:disabled {
background: #9ca3af;
cursor: not-allowed;
opacity: 0.6;
box-shadow: none;
}
.export-btn svg {
width: 16px;
height: 16px;
stroke: currentColor;
}
</style> </style>
\ No newline at end of file
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
:jh="queryParams.jh" :key="`drillingCurve-${queryParams.jh}`" /> :jh="queryParams.jh" :key="`drillingCurve-${queryParams.jh}`" />
</keep-alive> </keep-alive>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="录井钻时图" name="drillingTimeChart">
<DrillingTimeChart v-if="activeTab === 'drillingTimeChart'" :jh="queryParams.jh"
:key="`drillingTimeChart-${queryParams.jh}`" />
</el-tab-pane>
<el-tab-pane label="井眼轨迹" name="wellboreTrajectory"> <el-tab-pane label="井眼轨迹" name="wellboreTrajectory">
<WellboreTrajectory v-if="activeTab === 'wellboreTrajectory'" :jh="queryParams.jh" <WellboreTrajectory v-if="activeTab === 'wellboreTrajectory'" :jh="queryParams.jh"
:key="`wellboreTrajectory-${queryParams.jh}`" /> :key="`wellboreTrajectory-${queryParams.jh}`" />
...@@ -51,6 +55,7 @@ import LoggingData from './components/LoggingData.vue'; ...@@ -51,6 +55,7 @@ import LoggingData from './components/LoggingData.vue';
import LoggingCurve from './components/LoggingCurve.vue'; import LoggingCurve from './components/LoggingCurve.vue';
import DrillingData from './components/DrillingData.vue'; import DrillingData from './components/DrillingData.vue';
import DrillingCurve from './components/DrillingCurve.vue'; import DrillingCurve from './components/DrillingCurve.vue';
import DrillingTimeChart from './components/DrillingTimeChart.vue';
import WellboreTrajectory from './components/WellboreTrajectory.vue'; import WellboreTrajectory from './components/WellboreTrajectory.vue';
import WellDepthStructure from './components/WellDepthStructure.vue'; import WellDepthStructure from './components/WellDepthStructure.vue';
...@@ -64,6 +69,7 @@ export default { ...@@ -64,6 +69,7 @@ export default {
LoggingCurve, LoggingCurve,
DrillingData, DrillingData,
DrillingCurve, DrillingCurve,
DrillingTimeChart,
WellboreTrajectory, WellboreTrajectory,
WellDepthStructure WellDepthStructure
}, },
......
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
<el-form-item label="生产厂家"> <el-form-item label="生产厂家">
<el-input v-model="queryParams.sccj" placeholder="请输入生产厂家" clearable style="width: 150px;" /> <el-input v-model="queryParams.sccj" placeholder="请输入生产厂家" clearable style="width: 150px;" />
</el-form-item> </el-form-item>
<el-form-item label="钻头编号"> <!-- <el-form-item label="钻头编号">
<el-input v-model="queryParams.ztbh" placeholder="请输入钻头编号" clearable style="width: 150px;" /> <el-input v-model="queryParams.ztbh" placeholder="请输入钻头编号" clearable style="width: 150px;" />
</el-form-item> </el-form-item> -->
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSearch" size="mini">查询</el-button> <el-button type="primary" @click="onSearch" size="mini">查询</el-button>
<el-button @click="onReset" size="mini">重置</el-button> <el-button @click="onReset" size="mini">重置</el-button>
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
<el-table :data="tableData" style="width: 100%;" :height="tableHeight" stripe highlight-current-row border <el-table :data="tableData" style="width: 100%;" :height="tableHeight" stripe highlight-current-row border
v-loading="loading" @selection-change="handleSelectionChange"> v-loading="loading" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column prop="ztbh" label="钻头编号" width="100" align="center" /> <!-- <el-table-column prop="ztbh" label="钻头编号" width="100" align="center" /> -->
<el-table-column prop="ztcc" label="钻头尺寸mm" align="center" /> <el-table-column prop="ztcc" label="钻头尺寸mm" align="center" />
<el-table-column prop="ztxh" label="钻头型号" align="center" /> <el-table-column prop="ztxh" label="钻头型号" align="center" />
<el-table-column prop="ztlb" label="钻头类别" align="center" /> <el-table-column prop="ztlb" label="钻头类别" align="center" />
...@@ -84,11 +84,11 @@ ...@@ -84,11 +84,11 @@
<div class="dialog-card"> <div class="dialog-card">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <!-- <el-col :span="12">
<el-form-item label="钻头编号" prop="ztbh"> <el-form-item label="钻头编号" prop="ztbh">
<el-input v-model="form.ztbh" /> <el-input v-model="form.ztbh" />
</el-form-item> </el-form-item>
</el-col> </el-col> -->
<el-col :span="12"> <el-col :span="12">
<el-form-item label="钻头尺寸" prop="ztcc"> <el-form-item label="钻头尺寸" prop="ztcc">
<el-input v-model="form.ztcc" /> <el-input v-model="form.ztcc" />
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<div class="test-buttons"> <div class="test-buttons">
<el-button size="small" type="primary" @click="goToBitDesign">钻头设计参数推荐</el-button> <el-button size="small" type="primary" @click="goToBitDesign">钻头设计参数推荐</el-button>
<el-button size="small" type="success" @click="goToRecommendation">钻头设计推荐方案</el-button> <el-button size="small" type="success" @click="goToRecommendation">钻头设计参数推荐</el-button>
<el-button size="small" type="warning" @click="goToMatching">钻头匹配</el-button> <el-button size="small" type="warning" @click="goToMatching">钻头匹配</el-button>
<el-button size="small" type="info" @click="goToSelectionInfo">查看选型信息</el-button> <el-button size="small" type="info" @click="goToSelectionInfo">查看选型信息</el-button>
</div> </div>
......
...@@ -1757,7 +1757,7 @@ export default { ...@@ -1757,7 +1757,7 @@ export default {
const endDepth = kcData ? kcData.jsjs : 0; const endDepth = kcData ? kcData.jsjs : 0;
console.log(startDepth, 'startDepth'); console.log(startDepth, 'startDepth');
console.log(endDepth, 'endDepth'); console.log(endDepth, 'endDepth');
// 跳转到钻头设计推荐方案页面,传递开次信息 // 跳转到钻头设计参数推荐页面,传递开次信息
this.$router.push({ this.$router.push({
name: 'BitDesignRecommendation', name: 'BitDesignRecommendation',
query: { query: {
...@@ -1780,9 +1780,9 @@ export default { ...@@ -1780,9 +1780,9 @@ export default {
console.log('开次信息渲染完成'); console.log('开次信息渲染完成');
}, },
// 跳转到钻头设计推荐方案页面 // 跳转到钻头设计参数推荐页面
goToRecommendation() { goToRecommendation() {
console.log('跳转到钻头设计推荐方案页面') console.log('跳转到钻头设计参数推荐页面')
// 使用路由跳转到推荐方案页面 // 使用路由跳转到推荐方案页面
this.$router.push({ this.$router.push({
name: 'BitDesignRecommendation', name: 'BitDesignRecommendation',
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<BitDesign v-if="currentPage === 'main'" @show-recommendation="showRecommendation" <BitDesign v-if="currentPage === 'main'" @show-recommendation="showRecommendation"
@show-matching="showMatching" @show-selection-info="showSelectionInfo" /> @show-matching="showMatching" @show-selection-info="showSelectionInfo" />
<!-- 钻头设计推荐方案页面 --> <!-- 钻头设计参数推荐页面 -->
<BitDesignRecommendation v-if="currentPage === 'recommendation'" @match-bit="showMatching" @back="goBack" /> <BitDesignRecommendation v-if="currentPage === 'recommendation'" @match-bit="showMatching" @back="goBack" />
<!-- 钻头匹配页面 --> <!-- 钻头匹配页面 -->
...@@ -57,7 +57,7 @@ export default { ...@@ -57,7 +57,7 @@ export default {
// 显示推荐方案页面 // 显示推荐方案页面
showRecommendation() { showRecommendation() {
this.currentPage = 'recommendation' this.currentPage = 'recommendation'
this.updateBreadcrumb('钻头设计推荐方案') this.updateBreadcrumb('钻头设计参数推荐')
this.addToHistory('recommendation') this.addToHistory('recommendation')
}, },
...@@ -99,7 +99,7 @@ export default { ...@@ -99,7 +99,7 @@ export default {
updateBreadcrumb(pageName) { updateBreadcrumb(pageName) {
const breadcrumbMap = { const breadcrumbMap = {
'main': '钻头设计参数推荐', 'main': '钻头设计参数推荐',
'recommendation': '钻头设计推荐方案', 'recommendation': '钻头设计参数推荐',
'matching': '钻头匹配', 'matching': '钻头匹配',
'selection-info': '查看选型信息' 'selection-info': '查看选型信息'
} }
...@@ -117,7 +117,7 @@ export default { ...@@ -117,7 +117,7 @@ export default {
updateBreadcrumbFromHistory() { updateBreadcrumbFromHistory() {
const breadcrumbMap = { const breadcrumbMap = {
'main': '钻头设计参数推荐', 'main': '钻头设计参数推荐',
'recommendation': '钻头设计推荐方案', 'recommendation': '钻头设计参数推荐',
'matching': '钻头匹配', 'matching': '钻头匹配',
'selection-info': '查看选型信息' 'selection-info': '查看选型信息'
} }
......
...@@ -25,11 +25,11 @@ ...@@ -25,11 +25,11 @@
<!-- 上方推荐方案 --> <!-- 上方推荐方案 -->
<div class="recommendation-section"> <div class="recommendation-section">
<div class="recommendation-panel"> <div class="recommendation-panel">
<h3>钻头设计推荐方案</h3> <h3>钻头设计参数推荐</h3>
<el-table :data="[recommendationData]" border style="width: 100%"> <el-table :data="[recommendationData]" border style="width: 100%">
<el-table-column prop="bladeCount" label="刀翼数" min-width="120px" align="center" /> <el-table-column prop="bladeCount" label="刀翼数" min-width="120px" align="center" />
<el-table-column prop="density" label="布齿密度" min-width="120px" align="center" /> <el-table-column prop="density" label="布齿密度" min-width="120px" align="center" />
<el-table-column prop="toothSize" label="切削齿尺寸" min-width="120px" align="center" /> <el-table-column prop="toothSize" label="切削齿尺寸mm" min-width="120px" align="center" />
<el-table-column prop="negativeAngle" label="切削齿后倾角°" min-width="120px" align="center" /> <el-table-column prop="negativeAngle" label="切削齿后倾角°" min-width="120px" align="center" />
<el-table-column prop="crownProfile" label="冠状轮廓" min-width="120px" align="center" /> <el-table-column prop="crownProfile" label="冠状轮廓" min-width="120px" align="center" />
<el-table-column label="操作" align="center" fixed="right" width="250px" <el-table-column label="操作" align="center" fixed="right" width="250px"
......
...@@ -2,60 +2,34 @@ ...@@ -2,60 +2,34 @@
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="厂家名称" prop="mc"> <el-form-item label="厂家名称" prop="mc">
<el-input <el-input v-model="queryParams.mc" placeholder="请输入厂家名称" clearable @keyup.enter.native="handleQuery" />
v-model="queryParams.mc"
placeholder="请输入厂家名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
type="primary" v-hasPermi="['system:ztxxCj:add']">新增</el-button>
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:ztxxCj:add']"
>新增</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-table v-loading="loading" :data="ztxxCjList" @selection-change="handleSelectionChange"> <el-table border v-loading="loading" :data="ztxxCjList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="厂家名称" align="center" prop="mc" /> <el-table-column label="厂家名称" align="center" prop="mc" />
<el-table-column label="排序" align="center" prop="px" /> <el-table-column label="排序" align="center" prop="px" />
<el-table-column label="备注" align="center" prop="remark" /> <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">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
size="mini" v-hasPermi="['system:ztxxCj:edit']">修改</el-button>
type="text" <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
icon="el-icon-edit" v-hasPermi="['system:ztxxCj:remove']">删除</el-button>
@click="handleUpdate(scope.row)"
v-hasPermi="['system:ztxxCj:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:ztxxCj:remove']"
>删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
v-show="total>0" @pagination="getList" />
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改厂家信息对话框 --> <!-- 添加或修改厂家信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
...@@ -160,7 +134,7 @@ export default { ...@@ -160,7 +134,7 @@ export default {
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.id) this.ids = selection.map(item => item.id)
this.single = selection.length!==1 this.single = selection.length !== 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
...@@ -202,12 +176,12 @@ export default { ...@@ -202,12 +176,12 @@ export default {
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ids = row.id || this.ids; const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除厂家信息编号为"' + ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除厂家信息编号为"' + ids + '"的数据项?').then(function () {
return delZtxxCj(ids); return delZtxxCj(ids);
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.$modal.msgSuccess("删除成功"); this.$modal.msgSuccess("删除成功");
}).catch(() => {}); }).catch(() => { });
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment