Commit a8a4c625 by cat

zd 首页样式修改 缩略图弹窗显示 成果管理

parent 66a45d27
import request from '@/utils/request' import request from '@/utils/request'
// 查询成果管理列表 // 查询成果列表列表
export function listWjscqk(query) { export function listWjscqk(query) {
return request({ return request({
url: '/yscgWjscqk/wjscqk/list', url: '/yscgWjscqk/wjscqk/list',
method: 'get', method: 'get',
params: query params: query,
}) })
} }
// 查询成果管理详细 // 查询成果列表详细
export function getWjscqk(id) { export function getWjscqk(id) {
return request({ return request({
url: '/yscgWjscqk/wjscqk/' + id, url: '/yscgWjscqk/wjscqk/' + id,
method: 'get' method: 'get',
}) })
} }
// 新增成果管理 // 新增成果列表
export function addWjscqk(data) { export function addWjscqk(data) {
return request({ return request({
url: '/yscgWjscqk/wjscqk', url: '/yscgWjscqk/wjscqk',
method: 'post', method: 'post',
data: data data: data,
}) })
} }
// 修改成果管理 // 修改成果列表
export function updateWjscqk(data) { export function updateWjscqk(data) {
return request({ return request({
url: '/yscgWjscqk/wjscqk', url: '/yscgWjscqk/wjscqk',
method: 'put', method: 'put',
data: data data: data,
}) })
} }
// 删除成果管理 // 删除成果列表
export function delWjscqk(id) { export function delWjscqk(id) {
return request({ return request({
url: '/yscgWjscqk/wjscqk/' + id, url: '/yscgWjscqk/wjscqk/' + id,
method: 'delete' method: 'delete',
})
}
// 查询成果管理列表
export function listYscgList(query) {
return request({
url: '/ysqqXmxx/ysqqXmxx/yscgList',
method: 'get',
params: query,
}) })
} }
...@@ -5,7 +5,7 @@ export function listZllx(query) { ...@@ -5,7 +5,7 @@ export function listZllx(query) {
return request({ return request({
url: '/yscgZllx/zllx/list', url: '/yscgZllx/zllx/list',
method: 'get', method: 'get',
params: query params: query,
}) })
} }
...@@ -13,7 +13,7 @@ export function listZllx(query) { ...@@ -13,7 +13,7 @@ export function listZllx(query) {
export function getZllx(id) { export function getZllx(id) {
return request({ return request({
url: '/yscgZllx/zllx/' + id, url: '/yscgZllx/zllx/' + id,
method: 'get' method: 'get',
}) })
} }
...@@ -22,7 +22,7 @@ export function addZllx(data) { ...@@ -22,7 +22,7 @@ export function addZllx(data) {
return request({ return request({
url: '/yscgZllx/zllx', url: '/yscgZllx/zllx',
method: 'post', method: 'post',
data: data data: data,
}) })
} }
...@@ -31,7 +31,7 @@ export function updateZllx(data) { ...@@ -31,7 +31,7 @@ export function updateZllx(data) {
return request({ return request({
url: '/yscgZllx/zllx', url: '/yscgZllx/zllx',
method: 'put', method: 'put',
data: data data: data,
}) })
} }
...@@ -39,6 +39,14 @@ export function updateZllx(data) { ...@@ -39,6 +39,14 @@ export function updateZllx(data) {
export function delZllx(id) { export function delZllx(id) {
return request({ return request({
url: '/yscgZllx/zllx/' + id, url: '/yscgZllx/zllx/' + id,
method: 'delete' method: 'delete',
})
}
// 查询资料类型下拉选项
export function selectZllx() {
return request({
url: '/yscgZllx/zllx/selectZllx',
method: 'get',
}) })
} }

79.2 KB | W: | H:

1.65 KB | W: | H:

src/assets/images/profile.jpg
src/assets/images/profile.jpg
src/assets/images/profile.jpg
src/assets/images/profile.jpg
  • 2-up
  • Swipe
  • Onion skin
...@@ -225,17 +225,30 @@ export const dynamicRoutes = [ ...@@ -225,17 +225,30 @@ export const dynamicRoutes = [
}, },
], ],
}, },
{
path: '/yscgWjscqk/wjscqk',
component: Layout,
hidden: true,
children: [
{
path: 'index',
component: () => import('@/views/yscgWjscqk/wjscqk/index'),
name: 'WjscqkIndex',
meta: { title: '成果管理', activeMenu: '/yscgWjscqk/yscg' },
},
],
},
]; ];
// 防止连续点击多次路由报错 // 防止连续点击多次路由报错
let routerPush = Router.prototype.push; let routerPush = Router.prototype.push;
let routerReplace = Router.prototype.replace; let routerReplace = Router.prototype.replace;
// push // push
Router.prototype.push = function push(location) { Router.prototype.push = function push (location) {
return routerPush.call(this, location).catch((err) => err); return routerPush.call(this, location).catch((err) => err);
}; };
// replace // replace
Router.prototype.replace = function push(location) { Router.prototype.replace = function push (location) {
return routerReplace.call(this, location).catch((err) => err); return routerReplace.call(this, location).catch((err) => err);
}; };
......
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
<el-tab-pane label="待验收" name="pending"> <el-tab-pane label="待验收" name="pending">
<div class="card-container"> <div class="card-container">
<el-row :gutter="16" v-loading="pendingLoading"> <el-row :gutter="16" v-loading="pendingLoading">
<el-col :span="6" v-for="item in pendingList" :key="item.id" class="card-item"> <el-col :span="4" v-for="item in pendingList" :key="item.id" class="card-item">
<el-card class="project-card" shadow="hover"> <el-card class="project-card" shadow="hover">
<div class="card-header" @click="goNav2(item)" style="cursor: pointer;"> <div class="card-header" @click="goNav2(item)" style="cursor: pointer;">
<h3 class="project-title">{{ item.xmmc }}</h3> <h3 class="project-title">{{ item.xmmc }}</h3>
<el-tag type="warning" size="small">待验收</el-tag> <el-tag size="small" class="status-tag status-pending">待验收</el-tag>
</div> </div>
<div class="card-content"> <div class="card-content">
<div class="content-wrapper"> <div class="content-wrapper">
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
</div> </div>
</div> </div>
<div class="button-section"> <div class="button-section">
<el-button size="small" @click="handleComplete(item)">完成</el-button> <el-button size="mini" @click="handleComplete(item)">完成</el-button>
</div> </div>
</div> </div>
</div> </div>
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
<el-tab-pane label="已验收" name="completed"> <el-tab-pane label="已验收" name="completed">
<div class="card-container"> <div class="card-container">
<el-row :gutter="16" v-loading="completedLoading"> <el-row :gutter="16" v-loading="completedLoading">
<el-col :span="6" v-for="item in completedList" :key="item.id" class="card-item"> <el-col :span="4" v-for="item in completedList" :key="item.id" class="card-item">
<el-card class="project-card" shadow="hover"> <el-card class="project-card" shadow="hover">
<div class="card-header"> <div class="card-header">
<h3 class="project-title">{{ item.xmmc }}</h3> <h3 class="project-title">{{ item.xmmc }}</h3>
...@@ -314,6 +314,7 @@ export default { ...@@ -314,6 +314,7 @@ export default {
padding: 3px 0; padding: 3px 0;
border-radius: 4px; border-radius: 4px;
transition: background-color 0.2s ease; transition: background-color 0.2s ease;
align-items: center;
} }
.info-item:hover { .info-item:hover {
...@@ -325,6 +326,7 @@ export default { ...@@ -325,6 +326,7 @@ export default {
min-width: 70px; min-width: 70px;
flex-shrink: 0; flex-shrink: 0;
font-weight: 500; font-weight: 500;
white-space: nowrap;
} }
.value { .value {
...@@ -334,6 +336,7 @@ export default { ...@@ -334,6 +336,7 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-weight: 400; font-weight: 400;
min-width: 0;
} }
.button-section { .button-section {
...@@ -346,11 +349,47 @@ export default { ...@@ -346,11 +349,47 @@ export default {
} }
.button-section .el-button { .button-section .el-button {
width: 70px; width: 50px;
height: 28px; height: 25px;
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 500;
border-radius: 14px; border-radius: 20px;
background: linear-gradient(135deg, #409EFF 0%, #66b1ff 100%);
border: none;
color: #ffffff !important;
box-shadow: 0 1px 4px rgba(64, 158, 255, 0.2);
transition: all 0.2s ease-out;
position: relative;
overflow: hidden;
letter-spacing: 0.5px;
}
.button-section .el-button:hover {
background: linear-gradient(135deg, #337ecc 0%, #5a9eff 100%);
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.25);
transform: translateY(-0.5px);
color: #ffffff !important;
}
.button-section .el-button:active {
transform: translateY(0);
box-shadow: 0 1px 3px rgba(64, 158, 255, 0.2);
color: #ffffff !important;
}
.button-section .el-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent);
transition: left 0.3s ease-out;
}
.button-section .el-button:hover::before {
left: 100%;
} }
/* Safety: if any global rule hid buttons inside cards on non-hover, override */ /* Safety: if any global rule hid buttons inside cards on non-hover, override */
...@@ -367,6 +406,17 @@ export default { ...@@ -367,6 +406,17 @@ export default {
visibility: visible; visibility: visible;
} }
/* 状态标签:待验收(蓝色系,贴合系统主色) */
.status-tag {
border: none !important;
font-weight: 600;
}
.status-pending {
color: #1f3b64;
background: rgba(64, 158, 255, 0.12);
}
/* 分页固定在右下角 */ /* 分页固定在右下角 */
.pagination-wrapper { .pagination-wrapper {
position: fixed; position: fixed;
...@@ -377,13 +427,13 @@ export default { ...@@ -377,13 +427,13 @@ export default {
/* 默认大屏下每行5列 */ /* 默认大屏下每行5列 */
.el-col { .el-col {
width: 25% !important; width: 20% !important;
} }
/* 响应式设计 */ /* 响应式设计 */
@media (max-width: 1400px) { @media (max-width: 1400px) {
.el-col { .el-col {
width: 25% !important; width: 20% !important;
} }
} }
......
<!-- 成果列表 -->
<template> <template>
<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="项目id" prop="xmid">
<el-input
v-model="queryParams.xmid"
placeholder="请输入项目id"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> -->
<el-form-item label="文件名称" prop="wjmc"> <el-form-item label="文件名称" prop="wjmc">
<el-input v-model="queryParams.wjmc" placeholder="请输入文件名称" clearable @keyup.enter.native="handleQuery" /> <el-input v-model="queryParams.wjmc" placeholder="请输入文件名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="资料类型" prop="zllx"> <el-form-item label="资料类型" prop="zllx">
<el-input v-model="queryParams.zllx" placeholder="请输入资料类型" clearable @keyup.enter.native="handleQuery" /> <el-select v-model="queryParams.zllx" placeholder="请选择资料类型" clearable>
</el-form-item> <el-option
<!-- <el-form-item label="文件路径" prop="wjlj"> v-for="item in zllxOptions"
<el-input :key="item.id"
v-model="queryParams.wjlj" :label="item.lxmc"
placeholder="请输入文件路径" :value="item.lxmc">
clearable </el-option>
@keyup.enter.native="handleQuery" </el-select>
/>
</el-form-item>
<el-form-item label="创建人" prop="createdBy">
<el-input
v-model="queryParams.createdBy"
placeholder="请输入创建人"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable
v-model="queryParams.createdTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item label="备用1" prop="ext1">
<el-input
v-model="queryParams.ext1"
placeholder="请输入备用1"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input
v-model="queryParams.ext2"
placeholder="请输入备用2"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> </el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input
v-model="queryParams.ext3"
placeholder="请输入备用3"
clearable
@keyup.enter.native="handleQuery"
/>
</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>
...@@ -77,34 +30,12 @@ ...@@ -77,34 +30,12 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
</el-col>
<el-col :span="1.5">
</el-col>
<el-col :span="1.5">
</el-col>
<el-col :span="1.5">
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> -->
<el-table border v-loading="loading" :data="wjscqkList" @selection-change="handleSelectionChange"> <el-table border v-loading="loading" :data="wjscqkList" @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="id" />
<el-table-column label="项目id" align="center" prop="xmid" /> -->
<el-table-column label="文件名称" align="center" prop="wjmc" min-width="120" show-overflow-tooltip /> <el-table-column label="文件名称" align="center" prop="wjmc" min-width="120" show-overflow-tooltip />
<el-table-column label="资料类型" align="center" prop="zllx" min-width="100" show-overflow-tooltip /> <el-table-column label="资料类型" align="center" prop="zllx" min-width="100" show-overflow-tooltip />
<el-table-column label="文件路径" align="center" prop="wjlj" min-width="170" show-overflow-tooltip /> <el-table-column label="上传时间" align="center" prop="createdTime" min-width="170" show-overflow-tooltip />
<!-- <el-table-column label="创建人" align="center" prop="createdBy" />
<el-table-column label="创建时间" align="center" prop="createdTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createdTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="备用1" align="center" prop="ext1" />
<el-table-column label="备用2" align="center" prop="ext2" />
<el-table-column label="备用3" align="center" prop="ext3" /> -->
<el-table-column label="操作" min-width="110" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" min-width="110" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
...@@ -121,35 +52,42 @@ ...@@ -121,35 +52,42 @@
<!-- 添加或修改成果管理对话框 --> <!-- 添加或修改成果管理对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="89px"> <el-form ref="form" :model="form" :rules="rules" label-width="89px">
<!-- <el-form-item label="项目id" prop="xmid">
<el-input v-model="form.xmid" placeholder="请输入项目id" />
</el-form-item> -->
<el-form-item label="文件名称" prop="wjmc">
<el-input v-model="form.wjmc" placeholder="请输入文件名称" />
</el-form-item>
<el-form-item label="资料类型" prop="zllx"> <el-form-item label="资料类型" prop="zllx">
<el-input v-model="form.zllx" placeholder="请输入资料类型" /> <el-select v-model="form.zllx" placeholder="请选择资料类型" clearable>
</el-form-item> <el-option
<el-form-item label="文件路径" prop="wjlj"> v-for="item in zllxOptions"
<el-input v-model="form.wjlj" placeholder="请输入文件路径" /> :key="item.id"
</el-form-item> :label="item.lxmc"
<!-- <el-form-item label="创建人" prop="createdBy"> :value="item.lxmc">
<el-input v-model="form.createdBy" placeholder="请输入创建人" /> </el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.createdTime" type="date" value-format="yyyy-MM-dd" <el-form-item label="文件上传" prop="fileList">
placeholder="请选择创建时间"> <el-upload
</el-date-picker> ref="fileUpload"
</el-form-item> :action="uploadUrl"
<el-form-item label="备用1" prop="ext1"> :headers="uploadHeaders"
<el-input v-model="form.ext1" placeholder="请输入备用1" /> :file-list="fileList"
</el-form-item> :before-upload="handleBeforeUpload"
<el-form-item label="备用2" prop="ext2"> :on-success="handleUploadSuccess"
<el-input v-model="form.ext2" placeholder="请输入备用2" /> :on-error="handleUploadError"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:on-change="handleFileChange"
:data="uploadData"
drag
class="upload-dragger"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
支持 doc、docx、pdf、xls、xlsx、ppt、pptx、txt、jpg、jpeg、png、gif 格式文件,单个文件不超过50MB<br/>
<span style="color: #409EFF;">上传新文件将自动替换已有文件</span>
</div>
</el-upload>
</el-form-item> </el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button> <el-button type="primary" @click="submitForm">确 定</el-button>
...@@ -161,6 +99,8 @@ ...@@ -161,6 +99,8 @@
<script> <script>
import { listWjscqk, getWjscqk, delWjscqk, addWjscqk, updateWjscqk } from "@/api/yscgWjscqk/wjscqk" import { listWjscqk, getWjscqk, delWjscqk, addWjscqk, updateWjscqk } from "@/api/yscgWjscqk/wjscqk"
import { selectZllx } from "@/api/yscgZllx/zllx"
import { getToken } from "@/utils/auth"
export default { export default {
name: "Wjscqk", name: "Wjscqk",
...@@ -188,6 +128,7 @@ export default { ...@@ -188,6 +128,7 @@ export default {
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
id: null,
xmid: null, xmid: null,
wjmc: null, wjmc: null,
zllx: null, zllx: null,
...@@ -202,22 +143,81 @@ export default { ...@@ -202,22 +143,81 @@ export default {
form: {}, form: {},
// 表单校验 // 表单校验
rules: { rules: {
} },
// 资料类型选项
zllxOptions: [],
// 文件列表
fileList: [],
// 上传配置
uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload",
uploadHeaders: {
Authorization: "Bearer " + getToken()
},
uploadData: {}
} }
}, },
created() { created() {
// 获取路由参数中的id
if (this.$route.query.xmid) {
this.queryParams.xmid = this.$route.query.xmid
}
this.getList()
this.getZllxOptions()
},
watch: {
// 监听路由参数变化
'$route.query.xmid'(newId) {
if (newId) {
this.queryParams.xmid = newId
this.getList() this.getList()
}
}
}, },
methods: { methods: {
/** 查询成果管理列表 */ /** 查询成果管理列表 */
getList() { getList() {
console.log(this.queryParams.xmid,6666);
this.loading = true this.loading = true
listWjscqk(this.queryParams).then(response => { listWjscqk(this.queryParams).then(response => {
this.wjscqkList = response.rows const mergedRows = this.mergeRowsById(response.rows || [])
this.total = response.total this.wjscqkList = mergedRows
this.total = mergedRows.length
this.loading = false this.loading = false
}) })
}, },
/** 将相同id的记录进行合并(合并文件名与文件路径) */
mergeRowsById(rows) {
const idToRowMap = {}
const mergeCommaSeparated = (first, second) => {
const parts = []
if (first) parts.push(...String(first).split(',').filter(Boolean))
if (second) parts.push(...String(second).split(',').filter(Boolean))
const seen = new Set()
return parts.filter(item => {
if (seen.has(item)) return false
seen.add(item)
return true
}).join(',') || null
}
rows.forEach(row => {
const key = row.id
if (key == null) {
// 无id的记录直接保留为独立项
const tempKey = `__no_id__${Math.random()}_${Date.now()}`
idToRowMap[tempKey] = { ...row }
return
}
if (!idToRowMap[key]) {
idToRowMap[key] = { ...row }
} else {
const existing = idToRowMap[key]
existing.wjmc = mergeCommaSeparated(existing.wjmc, row.wjmc)
existing.wjlj = mergeCommaSeparated(existing.wjlj, row.wjlj)
// 其它字段保持首次出现的值,或可在此按需处理
}
})
return Object.values(idToRowMap)
},
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false this.open = false
...@@ -239,6 +239,7 @@ export default { ...@@ -239,6 +239,7 @@ export default {
ext2: null, ext2: null,
ext3: null ext3: null
} }
this.fileList = []
this.resetForm("form") this.resetForm("form")
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
...@@ -260,6 +261,10 @@ export default { ...@@ -260,6 +261,10 @@ export default {
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
// 设置xmid参数
if (this.queryParams.xmid) {
this.form.xmid = this.queryParams.xmid
}
this.open = true this.open = true
this.title = "添加成果管理" this.title = "添加成果管理"
}, },
...@@ -269,6 +274,19 @@ export default { ...@@ -269,6 +274,19 @@ export default {
const id = row.id || this.ids const id = row.id || this.ids
getWjscqk(id).then(response => { getWjscqk(id).then(response => {
this.form = response.data this.form = response.data
// 确保xmid参数被保持
if (this.queryParams.xmid) {
this.form.xmid = this.queryParams.xmid
}
// 如果有文件信息,加载到文件列表中(单文件)
if (this.form.wjmc && this.form.wjlj) {
this.fileList = [{
name: this.form.wjmc,
url: this.form.wjlj,
status: 'success',
uid: Date.now()
}]
}
this.open = true this.open = true
this.title = "修改成果管理" this.title = "修改成果管理"
}) })
...@@ -308,6 +326,75 @@ export default { ...@@ -308,6 +326,75 @@ export default {
this.download('yscgWjscqk/wjscqk/export', { this.download('yscgWjscqk/wjscqk/export', {
...this.queryParams ...this.queryParams
}, `wjscqk_${new Date().getTime()}.xlsx`) }, `wjscqk_${new Date().getTime()}.xlsx`)
},
/** 获取资料类型选项 */
getZllxOptions() {
selectZllx().then(response => {
this.zllxOptions = response.rows || []
}).catch(() => {
this.zllxOptions = []
})
},
/** 上传前校验 */
handleBeforeUpload(file) {
// 校验文件类型
const allowedTypes = ['doc', 'docx', 'pdf', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'jpg', 'jpeg', 'png', 'gif']
const fileExt = file.name.split('.').pop().toLowerCase()
if (!allowedTypes.includes(fileExt)) {
this.$modal.msgError('文件格式不正确,请上传支持的文件格式!')
return false
}
// 校验文件大小
const isLt50M = file.size / 1024 / 1024 < 50
if (!isLt50M) {
this.$modal.msgError('上传文件大小不能超过 50MB!')
return false
}
return true
},
/** 文件状态改变 */
handleFileChange(file, fileList) {
// 如果文件列表超过1个,只保留最新的文件
if (fileList.length > 1) {
this.fileList = [fileList[fileList.length - 1]]
} else {
this.fileList = fileList
}
this.updateFormFiles()
},
/** 上传成功 */
handleUploadSuccess(response, file, fileList) {
this.fileList = fileList
this.updateFormFiles()
this.$modal.msgSuccess('文件上传成功')
},
/** 上传失败 */
handleUploadError(err, file, fileList) {
this.$modal.msgError('文件上传失败')
},
/** 删除文件 */
handleRemove(file, fileList) {
this.fileList = fileList
this.updateFormFiles()
},
/** 文件数量超出限制 */
handleExceed(files, fileList) {
// 由于已实现自动替换,此方法不再需要显示错误提示
// 新文件会自动替换旧文件
},
/** 更新表单文件信息 */
updateFormFiles() {
if (this.fileList && this.fileList.length > 0) {
// 单文件上传,直接取第一个文件
const file = this.fileList[0]
this.form.wjmc = file.name
this.form.wjlj = file.response ? file.response.url : file.url
} else {
this.form.wjmc = null
this.form.wjlj = null
}
} }
} }
} }
......
<!-- 成果管理 -->
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="项目名称" prop="xmmc">
<el-input v-model="queryParams.xmmc" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="区块" prop="qk">
<el-input v-model="queryParams.qk" placeholder="请输入区块" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<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-form-item>
</el-form>
<el-table border v-loading="loading" :data="yscgList" :span-method="spanMethod">
<el-table-column label="项目名称" align="center" prop="xmmc" min-width="150" show-overflow-tooltip />
<el-table-column label="区块" align="center" prop="qk" min-width="120" show-overflow-tooltip />
<el-table-column label="资料类型" align="center" prop="zllxmc" min-width="120" show-overflow-tooltip />
<el-table-column label="上传情况" align="center" min-width="120">
<template slot-scope="scope">
<i :class="scope.row.zlsl > 0 ? 'el-icon-check' : 'el-icon-close'"
:style="{ color: scope.row.zlsl > 0 ? '#67C23A' : '#F56C6C', fontSize: '18px' }">
</i>
</template>
</el-table-column>
<el-table-column label="成果" align="center" prop="id" min-width="100" show-overflow-tooltip>
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">查看成果</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
</div>
</template>
<script>
import { listYscgList } from "@/api/yscgWjscqk/wjscqk"
export default {
name: "Yscg",
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 成果管理表格数据
yscgList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
xmmc: null,
qk: null
}
}
},
created() {
this.getList()
},
methods: {
/** 查询成果管理列表 */
getList() {
this.loading = true
listYscgList(this.queryParams).then(response => {
this.yscgList = response.rows
this.total = response.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
/** 成果按钮操作 */
handleView(row) {
// 跳转到成果详情页面,传id
this.$router.push({
path: '/yscgWjscqk/wjscqk/index',
query: {
xmid: row.id
}
})
},
/** 表格行合并方法 */
spanMethod({ row, column, rowIndex, columnIndex }) {
// 项目名称列(第0列)、区块列(第1列)和成果列(第3列)需要合并
if (columnIndex === 0 || columnIndex === 1 || columnIndex === 4) {
let fieldName, currentValue
if (columnIndex === 0) {
fieldName = 'xmmc'
currentValue = row[fieldName]
} else if (columnIndex === 1) {
fieldName = 'qk'
currentValue = row[fieldName]
} else if (columnIndex === 4) {
fieldName = 'id'
currentValue = row[fieldName]
}
// 如果当前值为空,不合并
if (!currentValue) {
return [1, 1]
}
// 如果当前值与上一行相同,则隐藏当前行
if (rowIndex > 0 && this.yscgList[rowIndex - 1][fieldName] === currentValue) {
return [0, 0]
}
// 计算需要合并的行数
let rowspan = 1
for (let i = rowIndex + 1; i < this.yscgList.length; i++) {
if (this.yscgList[i][fieldName] === currentValue) {
rowspan++
} else {
break
}
}
return [rowspan, 1]
}
// 其他列不合并
return [1, 1]
}
}
}
</script>
...@@ -26,7 +26,7 @@ export default { ...@@ -26,7 +26,7 @@ export default {
height: { type: Number, default: 0 }, height: { type: Number, default: 0 },
idOverride: { type: [String, Number], default: null } idOverride: { type: [String, Number], default: null }
}, },
data() { data () {
return { return {
chart: null, chart: null,
resizeObserver: null, resizeObserver: null,
...@@ -46,7 +46,7 @@ export default { ...@@ -46,7 +46,7 @@ export default {
points: [] points: []
} }
}, },
mounted() { mounted () {
// 仅使用延迟初始化,确保容器有尺寸后再 init // 仅使用延迟初始化,确保容器有尺寸后再 init
this.deferInit() this.deferInit()
window.addEventListener('resize', this.resizeChart) window.addEventListener('resize', this.resizeChart)
...@@ -69,16 +69,16 @@ export default { ...@@ -69,16 +69,16 @@ export default {
}) })
} }
}, },
created() { created () {
// 尽早触发接口调用,进入页面即发起请求 // 尽早触发接口调用,进入页面即发起请求
this.loadDht() this.loadDht()
}, },
activated() { activated () {
// 当页面被 keep-alive 缓存后再次进入时,确保尺寸和图表刷新 // 当页面被 keep-alive 缓存后再次进入时,确保尺寸和图表刷新
this.deferInit() this.deferInit()
this.resizeChart() this.resizeChart()
}, },
beforeDestroy() { beforeDestroy () {
window.removeEventListener('resize', this.resizeChart) window.removeEventListener('resize', this.resizeChart)
if (this.chart) { if (this.chart) {
this.chart.dispose() this.chart.dispose()
...@@ -91,7 +91,7 @@ export default { ...@@ -91,7 +91,7 @@ export default {
}, },
methods: { methods: {
// 等待容器有有效尺寸再初始化,避免 echarts 容器宽高为 0 报错 // 等待容器有有效尺寸再初始化,避免 echarts 容器宽高为 0 报错
deferInit() { deferInit () {
const tryInit = () => { const tryInit = () => {
const el = this.$refs.chartRef const el = this.$refs.chartRef
if (!el) return if (!el) return
...@@ -135,10 +135,10 @@ export default { ...@@ -135,10 +135,10 @@ export default {
} }
this.$nextTick(tryInit) this.$nextTick(tryInit)
}, },
resizeChart() { resizeChart () {
if (this.chart) this.chart.resize() if (this.chart) this.chart.resize()
}, },
initChart() { initChart () {
const el = this.$refs.chartRef const el = this.$refs.chartRef
if (!el) return if (!el) return
if (this.chart) { if (this.chart) {
...@@ -153,6 +153,7 @@ export default { ...@@ -153,6 +153,7 @@ export default {
// 初始渲染 // 初始渲染
this.renderChart() this.renderChart()
this.resizeChart() this.resizeChart()
this.bindChartEvents()
// 对于缩略图模式,确保渲染成功 // 对于缩略图模式,确保渲染成功
if (this.compact) { if (this.compact) {
...@@ -160,7 +161,7 @@ export default { ...@@ -160,7 +161,7 @@ export default {
} }
}, },
// 数据变化后自动刷新(确保缩略图及时绘制) // 数据变化后自动刷新(确保缩略图及时绘制)
_requestRender() { _requestRender () {
if (!this.chart) return if (!this.chart) return
this.$nextTick(() => { this.$nextTick(() => {
this.renderChart() this.renderChart()
...@@ -173,7 +174,7 @@ export default { ...@@ -173,7 +174,7 @@ export default {
}) })
}, },
// 调用地层/断层图接口(示例),优先从路由参数获取 id // 调用地层/断层图接口(示例),优先从路由参数获取 id
loadDht() { loadDht () {
if (this.loadingDht || this.dhtResult) return if (this.loadingDht || this.dhtResult) return
try { try {
const route = this.$route || {} const route = this.$route || {}
...@@ -201,7 +202,7 @@ export default { ...@@ -201,7 +202,7 @@ export default {
} }
}, },
// 将接口返回的数据应用到图表状态 // 将接口返回的数据应用到图表状态
applyDhtResult() { applyDhtResult () {
const data = this.dhtResult || {} const data = this.dhtResult || {}
// 边界 // 边界
this.xMin = data.xmin != null ? Number(data.xmin) : this.xMin this.xMin = data.xmin != null ? Number(data.xmin) : this.xMin
...@@ -247,7 +248,7 @@ export default { ...@@ -247,7 +248,7 @@ export default {
} catch (e) { } } catch (e) { }
}, },
// 生成图表配置 // 生成图表配置
buildOption() { buildOption () {
// 若未提供边界,则根据数据自动估算 // 若未提供边界,则根据数据自动估算
const allXs = [] const allXs = []
const allYs = [] const allYs = []
...@@ -321,10 +322,41 @@ export default { ...@@ -321,10 +322,41 @@ export default {
} }
}, },
// 渲染或更新图表 // 渲染或更新图表
renderChart() { renderChart () {
if (!this.chart) return if (!this.chart) return
const option = this.buildOption() const option = this.buildOption()
this.chart.setOption(option, true) this.chart.setOption(option, true)
// 确保事件绑定有效
this.bindChartEvents()
},
// 绑定点击/双击事件,把被点击的绿色线条映射为 segy 下标并上报
bindChartEvents () {
if (!this.chart) return
// 解除旧绑定避免重复
this.chart.off('click')
this.chart.off('dblclick')
const getLineIndexBySeries = (seriesIndex) => {
// 如果有井点散点,最前面占 1 个 series
const hasPoints = Array.isArray(this.points) && this.points.length > 0
const base = hasPoints ? 1 : 0
// 每条线我们 push 了两个 series:line 和一个灰色散点
if (seriesIndex < base) return -1
const offset = seriesIndex - base
// 偶数 -> 折线;奇数 -> 叠加的灰色散点
return Math.floor(offset / 2)
}
const emitPick = (params) => {
if (!params || (params.seriesType !== 'line' && params.seriesType !== 'scatter')) return
const idx = getLineIndexBySeries(params.seriesIndex)
if (idx >= 0 && idx < this.segyLines.length) {
this.$emit('segyLinePick', { index: idx })
}
}
this.chart.on('click', emitPick)
this.chart.on('dblclick', emitPick)
} }
} }
} }
......
...@@ -7,20 +7,25 @@ ...@@ -7,20 +7,25 @@
<el-button size="small" @click="setHorizontalLayout">左右结构</el-button> <el-button size="small" @click="setHorizontalLayout">左右结构</el-button>
<el-button size="small" @click="handlePrevTrace">上一道</el-button> <el-button size="small" @click="handlePrevTrace">上一道</el-button>
<el-button size="small" @click="handleNextTrace">下一道</el-button> <el-button size="small" @click="handleNextTrace">下一道</el-button>
<div ref="thumbContainer" @click="handleThumbClick"> <div ref="thumbContainer" @click="handleThumbClick" class="right-thumb">
<div class="thumb-title">缩略图</div> <div class="thumb-title">缩略图</div>
<div>1234567</div> <div ref="thumbHolder" class="thumb-holder">
<div ref="thumbHolder"> <YsgcIndex v-if="thumbReady" :key="routeId + '-' + thumbReady" :compact="true" :width="260" :height="160"
<YsgcIndex v-if="thumbReady" :key="routeId + '-' + thumbReady" :compact="true" :width="260" :id-override="routeId" />
:height="160" :id-override="routeId" />
</div> </div>
</div> </div>
<!-- 缩略图弹窗 start -->
<el-dialog title="缩略图预览" :visible.sync="showThumbDialog" width="80%" append-to-body>
<div style="height: 100%;">
<YsgcIndex :id-override="routeId" @segyLinePick="onThumbLinePick" />
</div> </div>
</el-dialog>
<!-- 缩略图弹窗 end -->
</div> </div>
<!-- 缩略图挂载到 body(右上角),不再在模板里渲染固定块 --> </div>
<!-- 添加加载状态和错误提示 --> <!-- 添加加载状态和错误提示 -->
<div v-if="loadingError" class="error-message"> <div v-if="loadingError" class="error-message">
...@@ -43,9 +48,9 @@ ...@@ -43,9 +48,9 @@
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
<toolbar-controls :plots="plots" :data-loaded="isWidgetReady" <toolbar-controls :plots="plots" :data-loaded="isWidgetReady" :show-line-style-panel="showLineStylePanel"
:show-line-style-panel="showLineStylePanel" @toggleLineStylePanel="toggleLineStylePanel" @toggleLineStylePanel="toggleLineStylePanel" @exporting="exporting = $event"
@exporting="exporting = $event" @closePrintDialog="showPrintDialog = false" /> @closePrintDialog="showPrintDialog = false" />
<el-tooltip content="绘制文本" placement="bottom" effect="light"> <el-tooltip content="绘制文本" placement="bottom" effect="light">
<el-button @click="toggleDrawText" :class="{ 'active': isDrawingText }"> <el-button @click="toggleDrawText" :class="{ 'active': isDrawingText }">
...@@ -59,8 +64,7 @@ ...@@ -59,8 +64,7 @@
</el-tooltip> </el-tooltip>
<el-tooltip :content="internalScrollbarSyncEnabled ? '内部滚动条同步已启用' : '内部滚动条同步已禁用'" placement="bottom" <el-tooltip :content="internalScrollbarSyncEnabled ? '内部滚动条同步已启用' : '内部滚动条同步已禁用'" placement="bottom"
effect="light"> effect="light">
<el-button @click="toggleInternalScrollbarSync" <el-button @click="toggleInternalScrollbarSync" :class="{ 'active': internalScrollbarSyncEnabled }">
:class="{ 'active': internalScrollbarSyncEnabled }">
<i class="el-icon-s-operation"></i> <i class="el-icon-s-operation"></i>
</el-button> </el-button>
</el-tooltip> </el-tooltip>
...@@ -153,15 +157,14 @@ ...@@ -153,15 +157,14 @@
</div> </div>
<div class="style-item"> <div class="style-item">
<span class="style-label">大小:</span> <span class="style-label">大小:</span>
<el-slider v-model="textStyle.size" :min="8" :max="60" show-input <el-slider v-model="textStyle.size" :min="8" :max="60" show-input @change="handleFontSizeChange">
@change="handleFontSizeChange">
</el-slider> </el-slider>
</div> </div>
<div class="style-item"> <div class="style-item">
<span class="style-label">字体:</span> <span class="style-label">字体:</span>
<el-select v-model="textStyle.font" placeholder="选择字体" @change="handleFontChange"> <el-select v-model="textStyle.font" placeholder="选择字体" @change="handleFontChange">
<el-option v-for="(font, index) in Object.keys(TEXT_PATTERNS)" :key="index" :label="font" <el-option v-for="(font, index) in Object.keys(TEXT_PATTERNS)" :key="index" :label="font" :value="font"
:value="font" :style="{ fontFamily: font }"> :style="{ fontFamily: font }">
{{ font }} {{ font }}
</el-option> </el-option>
</el-select> </el-select>
...@@ -170,30 +173,25 @@ ...@@ -170,30 +173,25 @@
<span class="style-label">对齐:</span> <span class="style-label">对齐:</span>
<div class="text-style-buttons"> <div class="text-style-buttons">
<el-button-group style="width: 100%"> <el-button-group style="width: 100%">
<el-button style="min-width: 20%; max-width: 20%" <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.align === 'left' ? 'primary' : ''"
:type="textStyle.align === 'left' ? 'primary' : ''"
@click="textStyle.align = 'left'; updateTextStyle()" title="左对齐"> @click="textStyle.align = 'left'; updateTextStyle()" title="左对齐">
<i class="el-icon-s-fold"></i> <i class="el-icon-s-fold"></i>
</el-button> </el-button>
<el-button style="min-width: 20%; max-width: 20%" <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.align === 'center' ? 'primary' : ''"
:type="textStyle.align === 'center' ? 'primary' : ''"
@click="textStyle.align = 'center'; updateTextStyle()" title="居中对齐"> @click="textStyle.align = 'center'; updateTextStyle()" title="居中对齐">
<i class="el-icon-menu"></i> <i class="el-icon-menu"></i>
</el-button> </el-button>
<el-button style="min-width: 20%; max-width: 20%" <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.align === 'right' ? 'primary' : ''"
:type="textStyle.align === 'right' ? 'primary' : ''"
@click="textStyle.align = 'right'; updateTextStyle()" title="右对齐"> @click="textStyle.align = 'right'; updateTextStyle()" title="右对齐">
<i class="el-icon-s-unfold"></i> <i class="el-icon-s-unfold"></i>
</el-button> </el-button>
<!-- 粗体按钮 --> <!-- 粗体按钮 -->
<el-button style="min-width: 20%; max-width: 20%" <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.bold ? 'primary' : ''"
:type="textStyle.bold ? 'primary' : ''"
@click="textStyle.bold = !textStyle.bold; updateTextStyle()" title="粗体"> @click="textStyle.bold = !textStyle.bold; updateTextStyle()" title="粗体">
<span style="font-weight: bold">B</span> <span style="font-weight: bold">B</span>
</el-button> </el-button>
<!-- 斜体按钮 --> <!-- 斜体按钮 -->
<el-button style="min-width: 20%; max-width: 20%" <el-button style="min-width: 20%; max-width: 20%" :type="textStyle.italic ? 'primary' : ''"
:type="textStyle.italic ? 'primary' : ''"
@click="textStyle.italic = !textStyle.italic; updateTextStyle()" title="斜体"> @click="textStyle.italic = !textStyle.italic; updateTextStyle()" title="斜体">
<span style="font-style: italic">I</span> <span style="font-style: italic">I</span>
</el-button> </el-button>
...@@ -344,7 +342,7 @@ export default { ...@@ -344,7 +342,7 @@ export default {
LineStylePanel, LineStylePanel,
YsgcIndex YsgcIndex
}, },
data() { data () {
return { return {
// 布局模式:vertical 上下结构;horizontal 左右结构 // 布局模式:vertical 上下结构;horizontal 左右结构
layoutMode: 'vertical', layoutMode: 'vertical',
...@@ -700,10 +698,13 @@ export default { ...@@ -700,10 +698,13 @@ export default {
_lastBottomScrollLeft: 0, // 记录底部滚动条水平位置 _lastBottomScrollLeft: 0, // 记录底部滚动条水平位置
_lastBottomScrollTop: 0, // 记录底部滚动条垂直位置 _lastBottomScrollTop: 0, // 记录底部滚动条垂直位置
thumbReady: false, thumbReady: false,
showThumbDialog: false, // 缩略图大图弹窗可见性
// 是否允许在未指定项目/无接口数据时加载示例数据
shouldLoadDemo: false,
}; };
}, },
computed: { computed: {
routeId() { routeId () {
try { try {
const route = this.$route || {}; const route = this.$route || {};
const params = route.params || {}; const params = route.params || {};
...@@ -714,7 +715,7 @@ export default { ...@@ -714,7 +715,7 @@ export default {
} }
} }
}, },
mounted() { mounted () {
// 初始化时强制设置为初始状态 // 初始化时强制设置为初始状态
this.resetToInitialState(); this.resetToInitialState();
...@@ -727,15 +728,15 @@ export default { ...@@ -727,15 +728,15 @@ export default {
// 关闭强力滚动条监控,避免影响全局布局 // 关闭强力滚动条监控,避免影响全局布局
// this.startAggressiveScrollbarMonitor(); // this.startAggressiveScrollbarMonitor();
this.$nextTick(() => { this.$nextTick(async () => {
['thumb-test-container', 'thumb-chart-container', 'super-visible-thumb'].forEach(id => { ['thumb-test-container', 'thumb-chart-container', 'super-visible-thumb'].forEach(id => {
const el = document.getElementById(id); const el = document.getElementById(id);
if (el) try { el.remove(); } catch (e) { } if (el) try { el.remove(); } catch (e) { }
}); });
if (this.$refs.thumbContainer && this.$refs.thumbContainer.parentNode !== document.body) { // 保持缩略图容器在组件内部,避免在DOM树中难以定位
document.body.appendChild(this.$refs.thumbContainer); // 初始化场景时不自动加载演示数据,等待接口结果决定
} this.shouldLoadDemo = false;
this.createScene(this.$refs.plot); this.createScene(this.$refs.plot, { autoloadDemo: false });
// 等DOM稳定后再渲染缩略图组件 // 等DOM稳定后再渲染缩略图组件
setTimeout(() => { setTimeout(() => {
this.thumbReady = true; this.thumbReady = true;
...@@ -746,6 +747,24 @@ export default { ...@@ -746,6 +747,24 @@ export default {
}, 200); }, 200);
}, 100); }, 100);
// 已改为内嵌 YsgcIndex 缩略图,不再走旧的 ECharts 缩略图初始化 // 已改为内嵌 YsgcIndex 缩略图,不再走旧的 ECharts 缩略图初始化
// 自动拉取接口数据并加载第一组上/下部 SEGY(jbsegy -> 顶部,xbsegy -> 底部)
try {
await this.loadThumbData();
if (Array.isArray(this.segyList) && this.segyList.length > 0) {
await this.loadCurrentSegy();
} else {
// 无接口数据:若没有路由id,允许加载演示数据;若有id但无数据,保持空白
const hasId = !!this.routeId;
if (!hasId) {
this.shouldLoadDemo = false;
try { await this.handleFileSelect(this.plots); } catch (e) { }
} else {
this.clearCurrentPlots();
this.$message.info('该项目无可用SEGY数据');
}
}
} catch (e) { /* ignore */ }
}); });
if (this.$refs.plot) { if (this.$refs.plot) {
...@@ -755,26 +774,8 @@ export default { ...@@ -755,26 +774,8 @@ export default {
// 添加键盘事件监听 // 添加键盘事件监听
} }
}, },
mounted() { // 删除重复的 mounted,避免生命周期被覆盖
// 将缩略图容器移动到body,确保fixed基于视口 beforeDestroy () {
if (this.$refs.thumbContainer && this.$refs.thumbContainer.parentNode !== document.body) {
document.body.appendChild(this.$refs.thumbContainer);
}
this.createScene(this.$refs.plot);
// 等DOM稳定后再渲染缩略图组件
setTimeout(() => {
this.thumbReady = true;
// 再兜底:确保右上角出现内容,并直接绘制缩略图
setTimeout(() => {
this.ensureThumbRendered();
}, 200);
}, 100);
console.log('测试函数已添加:');
console.log('- window.testOuterScrollbarSync() - 测试外层滚动条同步');
console.log('- window.testInternalScrollbarHidden() - 测试内部滚动条隐藏');
},
beforeDestroy() {
// 移除右键菜单事件监听 // 移除右键菜单事件监听
if (this.$refs.plot) { if (this.$refs.plot) {
this.$refs.plot.removeEventListener('contextmenu', this.showContextMenu); this.$refs.plot.removeEventListener('contextmenu', this.showContextMenu);
...@@ -786,7 +787,7 @@ export default { ...@@ -786,7 +787,7 @@ export default {
window.removeEventListener('resize', this.updateBaseCanvasSize); window.removeEventListener('resize', this.updateBaseCanvasSize);
}, },
methods: { methods: {
ensureThumbRendered() { ensureThumbRendered () {
try { try {
const holder = this.$refs.thumbHolder; const holder = this.$refs.thumbHolder;
if (!holder) return; if (!holder) return;
...@@ -805,7 +806,7 @@ export default { ...@@ -805,7 +806,7 @@ export default {
} }
} catch (e) { /* ignore */ } } catch (e) { /* ignore */ }
}, },
drawThumbDirect() { drawThumbDirect () {
try { try {
const holder = this.$refs.thumbHolder; const holder = this.$refs.thumbHolder;
if (!holder) return; if (!holder) return;
...@@ -829,26 +830,53 @@ export default { ...@@ -829,26 +830,53 @@ export default {
animation: false animation: false
}; };
chart.setOption(option, true); chart.setOption(option, true);
// 绑定双击事件:双击某条线,加载对应的上下SEGY(新/旧)
try {
// 系列下标说明:
// buildThumbOption 会在最前面插入边框(line) => 索引0
// 如果存在井点,会有一个散点系列 => 可能是索引1
// 之后按顺序依次是每一条线。我们需要把 seriesIndex 映射到 segyList 的下标
const hasPoints = Array.isArray(this.thumbPoints) && this.thumbPoints.length > 0;
const lineSeriesBaseIndex = 1 + (hasPoints ? 1 : 0); // 边框1 + 可选散点1
chart.off('dblclick');
chart.on('dblclick', (params) => {
if (params && params.seriesType === 'line') {
const seriesIndex = params.seriesIndex;
const lineIdx = seriesIndex - lineSeriesBaseIndex;
if (lineIdx >= 0 && Array.isArray(this.segyList) && lineIdx < this.segyList.length) {
const seg = this.segyList[lineIdx];
this.currentSegyIndex = lineIdx;
if (seg) {
// 加载该线对应的新/旧SEGY:jbsegy -> 顶部,xbsegy -> 底部
this.loadDualSegyFiles(seg.jbsegy, seg.xbsegy, seg.jbsegyName, seg.xbsegyName);
this.$message.success(`已加载第${lineIdx + 1}条线的数据`);
}
}
}
});
} catch (e) { /* ignore binding errors */ }
} catch (e) { /* ignore */ } } catch (e) { /* ignore */ }
}, },
// 顶部操作:切换布局与上一/下一道(占位) // 顶部操作:切换布局与上一/下一道(占位)
setVerticalLayout() { setVerticalLayout () {
this.layoutMode = 'vertical'; this.layoutMode = 'vertical';
this.showDualChart(); this.showDualChart();
this.$nextTick(() => this.resizeAfterLayout()); this.$nextTick(() => this.resizeAfterLayout());
}, },
// 已移除全局浮动缩略图容器,缩略图仅在本页右上角显示 // 已移除全局浮动缩略图容器,缩略图仅在本页右上角显示
setHorizontalLayout() { setHorizontalLayout () {
this.layoutMode = 'horizontal'; this.layoutMode = 'horizontal';
this.showDualChart(); this.showDualChart();
this.$nextTick(() => this.resizeAfterLayout()); this.$nextTick(() => this.resizeAfterLayout());
}, },
resizeAfterLayout() { resizeAfterLayout () {
try { this.updateBaseCanvasSize(); } catch (e) { } try { this.updateBaseCanvasSize(); } catch (e) { }
try { this._seismicWidget && this._seismicWidget.invalidate(); } catch (e) { } try { this._seismicWidget && this._seismicWidget.invalidate(); } catch (e) { }
try { this._seismicWidgetBottom && this._seismicWidgetBottom.invalidate(); } catch (e) { } try { this._seismicWidgetBottom && this._seismicWidgetBottom.invalidate(); } catch (e) { }
}, },
async handlePrevTrace() { async handlePrevTrace () {
console.log('[index2] 上一道 clicked'); console.log('[index2] 上一道 clicked');
if (!Array.isArray(this.segyList) || this.segyList.length === 0) { if (!Array.isArray(this.segyList) || this.segyList.length === 0) {
console.log('[index2] segyList 为空,尝试重新加载'); console.log('[index2] segyList 为空,尝试重新加载');
...@@ -868,7 +896,7 @@ export default { ...@@ -868,7 +896,7 @@ export default {
// 加载当前segy文件 // 加载当前segy文件
this.loadCurrentSegy(); this.loadCurrentSegy();
}, },
async handleNextTrace() { async handleNextTrace () {
console.log('[index2] 下一道 clicked'); console.log('[index2] 下一道 clicked');
if (!Array.isArray(this.segyList) || this.segyList.length === 0) { if (!Array.isArray(this.segyList) || this.segyList.length === 0) {
console.log('[index2] segyList 为空,尝试重新加载'); console.log('[index2] segyList 为空,尝试重新加载');
...@@ -889,7 +917,7 @@ export default { ...@@ -889,7 +917,7 @@ export default {
this.loadCurrentSegy(); this.loadCurrentSegy();
}, },
// 加载当前segy文件 // 加载当前segy文件
async loadCurrentSegy() { async loadCurrentSegy () {
if (this.segyList.length === 0) { if (this.segyList.length === 0) {
console.log('[index2] 没有segy数据可加载'); console.log('[index2] 没有segy数据可加载');
return; return;
...@@ -914,7 +942,7 @@ export default { ...@@ -914,7 +942,7 @@ export default {
} }
}, },
// 清空当前图表 // 清空当前图表
clearCurrentPlots() { clearCurrentPlots () {
console.log('[index2] 清空当前图表'); console.log('[index2] 清空当前图表');
try { try {
// 清空主图表 // 清空主图表
...@@ -933,7 +961,7 @@ export default { ...@@ -933,7 +961,7 @@ export default {
} }
}, },
// 加载segy文件的具体实现 // 加载segy文件的具体实现
async loadSegyFile(segyPath) { async loadSegyFile (segyPath) {
console.log('[index2] 开始加载segy文件:', segyPath); console.log('[index2] 开始加载segy文件:', segyPath);
try { try {
...@@ -956,7 +984,7 @@ export default { ...@@ -956,7 +984,7 @@ export default {
} }
}, },
// 同时加载上下两个segy(jbsegy到顶部,xbsegy到底部) // 同时加载上下两个segy(jbsegy到顶部,xbsegy到底部)
async loadDualSegyFiles(jbPath, xbPath, jbName, xbName) { async loadDualSegyFiles (jbPath, xbPath, jbName, xbName) {
// 兜底:若无路径,则给出提示 // 兜底:若无路径,则给出提示
if (!jbPath && !xbPath) { if (!jbPath && !xbPath) {
this.$message.warning('无可加载的SEGY文件'); this.$message.warning('无可加载的SEGY文件');
...@@ -970,7 +998,7 @@ export default { ...@@ -970,7 +998,7 @@ export default {
this.clearCurrentPlots(); this.clearCurrentPlots();
// 确保两个画布已初始化 // 确保两个画布已初始化
if (this.$refs.plot) this.createScene(this.$refs.plot); if (this.$refs.plot) this.createScene(this.$refs.plot, { autoloadDemo: false });
if (this.$refs.plot2) this.initSecondWidget(this.$refs.plot2); if (this.$refs.plot2) this.initSecondWidget(this.$refs.plot2);
// 顺序加载,分别统计成功与失败 // 顺序加载,分别统计成功与失败
...@@ -1003,7 +1031,7 @@ export default { ...@@ -1003,7 +1031,7 @@ export default {
} }
}, },
// 将指定segy加载到顶部/底部widget // 将指定segy加载到顶部/底部widget
async loadSegyIntoWidget(position, segyPath, displayName) { async loadSegyIntoWidget (position, segyPath, displayName) {
// 构造可访问的完整URL // 构造可访问的完整URL
const url = this.buildSegyURL(segyPath); const url = this.buildSegyURL(segyPath);
...@@ -1069,7 +1097,7 @@ export default { ...@@ -1069,7 +1097,7 @@ export default {
} }
}, },
// 根据后端网关构造SEGY访问URL // 根据后端网关构造SEGY访问URL
buildSegyURL(path) { buildSegyURL (path) {
if (!path) return ''; if (!path) return '';
// 如果已经是完整URL,直接返回 // 如果已经是完整URL,直接返回
if (/^https?:\/\//i.test(path)) return path; if (/^https?:\/\//i.test(path)) return path;
...@@ -1083,7 +1111,7 @@ export default { ...@@ -1083,7 +1111,7 @@ export default {
return `${base}${p}`; return `${base}${p}`;
}, },
// 拉取SEGY二进制 // 拉取SEGY二进制
async fetchSegyBlob(url) { async fetchSegyBlob (url) {
if (!url) throw new Error('无效的SEGY地址'); if (!url) throw new Error('无效的SEGY地址');
const res = await fetch(url, { headers: { Authorization: 'Bearer ' + getToken() } }); const res = await fetch(url, { headers: { Authorization: 'Bearer ' + getToken() } });
if (!res.ok) throw new Error(`网络请求失败: ${res.status} ${res.statusText}`); if (!res.ok) throw new Error(`网络请求失败: ${res.status} ${res.statusText}`);
...@@ -1092,7 +1120,7 @@ export default { ...@@ -1092,7 +1120,7 @@ export default {
return blob; return blob;
}, },
// 显示单个图表(隐藏底部图表) // 显示单个图表(隐藏底部图表)
showSingleChart() { showSingleChart () {
console.log('[index2] 切换到单图表显示模式'); console.log('[index2] 切换到单图表显示模式');
// 隐藏底部图表容器 // 隐藏底部图表容器
...@@ -1112,7 +1140,7 @@ export default { ...@@ -1112,7 +1140,7 @@ export default {
this.layoutMode = 'single'; this.layoutMode = 'single';
}, },
// 显示双图表(恢复上下或左右布局) // 显示双图表(恢复上下或左右布局)
showDualChart() { showDualChart () {
console.log('[index2] 切换到双图表显示模式'); console.log('[index2] 切换到双图表显示模式');
// 显示底部图表容器 // 显示底部图表容器
...@@ -1134,7 +1162,7 @@ export default { ...@@ -1134,7 +1162,7 @@ export default {
} }
}, },
// 清空场景 // 清空场景
clearScene(container) { clearScene (container) {
if (!container) return; if (!container) return;
try { try {
...@@ -1150,161 +1178,37 @@ export default { ...@@ -1150,161 +1178,37 @@ export default {
console.warn('[index2] 清空场景时出错:', e); console.warn('[index2] 清空场景时出错:', e);
} }
}, },
handleThumbClick() { handleThumbClick () {
const id = this.routeId; this.showThumbDialog = true;
this.$router.push({ name: 'YsgcIndex', query: id ? { id } : {} }); },
// 处理缩略图(绿色线)点击/双击事件
onThumbLinePick (payload) {
try {
if (!payload || typeof payload.index !== 'number') return;
const lineIdx = payload.index;
if (!Array.isArray(this.segyList) || lineIdx < 0 || lineIdx >= this.segyList.length) return;
const seg = this.segyList[lineIdx];
this.currentSegyIndex = lineIdx;
if (seg) {
this.loadDualSegyFiles(seg.jbsegy, seg.xbsegy, seg.jbsegyName, seg.xbsegyName);
this.$message.success(`已加载第${lineIdx + 1}条线的数据`);
}
} catch (e) { /* ignore */ }
}, },
// 确保缩略图渲染 // 确保缩略图渲染
ensureThumbRendered() { ensureThumbRendered () {
if (!this.thumbReady) { if (!this.thumbReady) {
this.thumbReady = true; this.thumbReady = true;
} }
}, },
// ====== 缩略图(ECharts) ====== // ====== 缩略图(ECharts) ======
async initThumb() { async initThumb () {
// 已弃用:现在缩略图直接嵌入 YsgcIndex // 已弃用:现在缩略图直接嵌入 YsgcIndex
return; return;
console.log('[index2] ===== initThumb START =====');
console.log('[index2] initThumb called by button click');
try {
// 重试机制:如果ref没找到,等待一段时间再试
let holder = this.$refs.thumbHolder;
console.log('[index2] thumbHolder ref:', holder);
console.log('[index2] thumbHolder element:', holder ? holder.outerHTML : 'null');
// 不再查找全局固定容器,仅使用本页右上角容器
if (!holder) {
console.warn('[index2] thumbHolder ref not found, retrying...');
await new Promise(resolve => setTimeout(resolve, 500));
holder = this.$refs.thumbHolder;
console.log('[index2] thumbHolder ref after retry:', holder);
}
// 最终兜底:如果依然找不到,则直接返回
if (!holder) {
console.warn('[index2] thumbHolder still not found in this page');
return;
}
if (this.thumbChart) {
try { this.thumbChart.dispose(); } catch (e) { }
this.thumbChart = null;
}
// 强制设置尺寸并直接初始化(使用 !important 提升优先级)
holder.style.setProperty('width', '260px', 'important');
holder.style.setProperty('height', '160px', 'important');
holder.style.setProperty('display', 'block', 'important');
holder.style.setProperty('visibility', 'visible', 'important');
holder.style.setProperty('min-width', '260px', 'important');
holder.style.setProperty('min-height', '160px', 'important');
holder.style.setProperty('max-width', '260px', 'important');
holder.style.setProperty('max-height', '160px', 'important');
holder.style.setProperty('flex', 'none', 'important'); // 防止flex布局影响
holder.style.setProperty('position', 'relative', 'important'); // 确保定位正确
holder.style.setProperty('overflow', 'hidden', 'important'); // 防止内容溢出
// 强制设置父容器尺寸
const parent = holder.parentElement;
if (parent) {
// 强制父容器为固定定位且可见,避免0尺寸(使用 !important)
parent.style.setProperty('position', 'fixed', 'important');
parent.style.setProperty('top', '16px', 'important');
parent.style.setProperty('right', '16px', 'important');
parent.style.setProperty('z-index', '2147483647', 'important');
parent.style.setProperty('display', 'block', 'important');
parent.style.setProperty('visibility', 'visible', 'important');
parent.style.setProperty('width', '260px', 'important');
parent.style.setProperty('height', '200px', 'important');
parent.style.setProperty('min-height', '200px', 'important');
// 再次读取尺寸
console.log('[index2] parent container size set:', parent.clientWidth, 'x', parent.clientHeight);
}
console.log('[index2] thumb holder size after force set:', holder.clientWidth, 'x', holder.clientHeight);
console.log('[index2] thumb holder offsetWidth:', holder.offsetWidth, 'x', holder.offsetHeight);
console.log('[index2] thumb holder getBoundingClientRect:', holder.getBoundingClientRect());
// 等待一帧确保样式生效
await new Promise(resolve => requestAnimationFrame(resolve));
console.log('[index2] thumb holder size after animation frame:', holder.clientWidth, 'x', holder.clientHeight);
// 等待更长时间确保DOM完全渲染
await new Promise(resolve => setTimeout(resolve, 1000));
// 再次检查尺寸
console.log('[index2] thumb holder size after 1s delay:', holder.clientWidth, 'x', holder.clientHeight);
// 强制设置容器尺寸
holder.style.width = '260px';
holder.style.height = '160px';
holder.style.minWidth = '260px';
holder.style.minHeight = '160px';
holder.style.maxWidth = '260px';
holder.style.maxHeight = '160px';
// 如果容器尺寸仍然为0,使用独立容器
if (holder.clientWidth === 0 || holder.clientHeight === 0) {
console.log('[index2] Container size is 0, force setting fixed size and continue');
holder.style.width = '260px';
holder.style.height = '160px';
}
// 初始化ECharts
this.thumbChart = echarts.init(holder, null, {
width: 260,
height: 160,
renderer: 'canvas' // 强制使用canvas渲染器
});
console.log('[index2] thumb chart init directly');
console.log('[index2] thumb chart instance:', this.thumbChart);
// 先显示一个占位图,确保容器可见
try {
this.thumbChart.setOption({
grid: { top: 10, left: 10, right: 10, bottom: 10 },
xAxis: { type: 'value', min: 0, max: 100, show: false },
yAxis: { type: 'value', min: 0, max: 100, show: false },
series: [{ type: 'line', data: [[0, 0], [100, 100]], showSymbol: false, lineStyle: { color: '#d3d3d3' } }],
animation: false
}, true);
} catch (e) { console.warn('[index2] placeholder option failed', e); }
await this.loadThumbData();
this.renderThumb();
// 立即强制渲染
this.thumbChart.resize();
console.log('[index2] thumb chart immediate resize');
// 强制重新渲染
setTimeout(() => {
if (this.thumbChart) {
this.thumbChart.resize();
console.log('[index2] thumb chart resize called');
// 强制重新设置选项,确保图表显示
this.thumbChart.setOption(this.buildThumbOption(), true);
console.log('[index2] thumb chart option reset');
}
}, 100);
// 监听尺寸变化
if (!this.thumbResizeObserver) {
this.thumbResizeObserver = new ResizeObserver(() => {
try { this.thumbChart && this.thumbChart.resize(); } catch (e) { }
});
this.thumbResizeObserver.observe(holder);
}
} catch (e) {
console.warn('[index2] initThumb failed:', e);
// 不再调用备用方法,避免产生左下角黄色框
return;
}
console.log('[index2] ===== initThumb END =====');
}, },
// 测试缩略图方法 // 测试缩略图方法
testThumb() { testThumb () {
console.log('[index2] ===== testThumb START ====='); console.log('[index2] ===== testThumb START =====');
// 创建完全独立的测试容器 // 创建完全独立的测试容器
...@@ -1339,7 +1243,7 @@ export default { ...@@ -1339,7 +1243,7 @@ export default {
console.log('[index2] ===== testThumb END ====='); console.log('[index2] ===== testThumb END =====');
}, },
// 测试ECharts方法 // 测试ECharts方法
testECharts() { testECharts () {
console.log('[index2] ===== testECharts START ====='); console.log('[index2] ===== testECharts START =====');
// 清理现有容器 // 清理现有容器
...@@ -1422,14 +1326,14 @@ export default { ...@@ -1422,14 +1326,14 @@ export default {
console.log('[index2] ===== testECharts END ====='); console.log('[index2] ===== testECharts END =====');
}, },
// 测试按钮点击 // 测试按钮点击
testButtonClick() { testButtonClick () {
console.log('[index2] ===== testButtonClick START ====='); console.log('[index2] ===== testButtonClick START =====');
alert('按钮点击测试成功!'); alert('按钮点击测试成功!');
console.log('[index2] ===== testButtonClick END ====='); console.log('[index2] ===== testButtonClick END =====');
}, },
// 创建超级明显的缩略图测试 // 创建超级明显的缩略图测试
createSuperVisibleThumb() { createSuperVisibleThumb () {
console.log('[index2] ===== createSuperVisibleThumb START ====='); console.log('[index2] ===== createSuperVisibleThumb START =====');
// 清理现有容器 // 清理现有容器
...@@ -1576,7 +1480,7 @@ export default { ...@@ -1576,7 +1480,7 @@ export default {
console.log('[index2] ===== createSuperVisibleThumb END ====='); console.log('[index2] ===== createSuperVisibleThumb END =====');
}, },
// 重置缩略图方法 // 重置缩略图方法
resetThumb() { resetThumb () {
console.log('[index2] ===== resetThumb START ====='); console.log('[index2] ===== resetThumb START =====');
// 清理独立容器 // 清理独立容器
...@@ -1621,7 +1525,7 @@ export default { ...@@ -1621,7 +1525,7 @@ export default {
console.log('[index2] ===== resetThumb END ====='); console.log('[index2] ===== resetThumb END =====');
}, },
// 备用缩略图初始化方法 // 备用缩略图初始化方法
async initThumbFallback() { async initThumbFallback () {
console.log('[index2] ===== initThumbFallback START ====='); console.log('[index2] ===== initThumbFallback START =====');
try { try {
// 创建完全独立的ECharts容器 // 创建完全独立的ECharts容器
...@@ -1735,7 +1639,7 @@ export default { ...@@ -1735,7 +1639,7 @@ export default {
} }
console.log('[index2] ===== initThumbFallback END ====='); console.log('[index2] ===== initThumbFallback END =====');
}, },
async loadThumbData() { async loadThumbData () {
try { try {
// 与 index.vue 相同的取数方式:优先从路由取 id // 与 index.vue 相同的取数方式:优先从路由取 id
const route = this.$route || {}; const route = this.$route || {};
...@@ -1833,7 +1737,7 @@ export default { ...@@ -1833,7 +1737,7 @@ export default {
console.warn('[index2] loadThumbData failed:', e); console.warn('[index2] loadThumbData failed:', e);
} }
}, },
buildThumbOption() { buildThumbOption () {
const series = []; const series = [];
if (this.thumbPoints && this.thumbPoints.length) { if (this.thumbPoints && this.thumbPoints.length) {
series.push({ series.push({
...@@ -1936,7 +1840,7 @@ export default { ...@@ -1936,7 +1840,7 @@ export default {
}] }]
}; };
}, },
renderThumb() { renderThumb () {
if (!this.thumbChart) { if (!this.thumbChart) {
console.warn('[index2] renderThumb: no chart instance'); console.warn('[index2] renderThumb: no chart instance');
return; return;
...@@ -1960,7 +1864,7 @@ export default { ...@@ -1960,7 +1864,7 @@ export default {
} }
}, },
// 更新基准宽高,基于外层容器实际尺寸 // 更新基准宽高,基于外层容器实际尺寸
updateBaseCanvasSize() { updateBaseCanvasSize () {
try { try {
const topEl = this.$refs.topScroll; const topEl = this.$refs.topScroll;
if (topEl) { if (topEl) {
...@@ -1980,7 +1884,7 @@ export default { ...@@ -1980,7 +1884,7 @@ export default {
}, },
// 根据 GeoToolkit 模型范围动态计算滚动区域尺寸 // 根据 GeoToolkit 模型范围动态计算滚动区域尺寸
updateScrollAreaSize() { updateScrollAreaSize () {
try { try {
if (!this._seismicWidget) return; if (!this._seismicWidget) return;
...@@ -2054,7 +1958,7 @@ export default { ...@@ -2054,7 +1958,7 @@ export default {
}, },
// 彻底禁用滚动条工具 // 彻底禁用滚动条工具
disableScrollbarTools() { disableScrollbarTools () {
try { try {
// 等待widget创建完成后再禁用 // 等待widget创建完成后再禁用
setTimeout(() => { setTimeout(() => {
...@@ -2071,7 +1975,7 @@ export default { ...@@ -2071,7 +1975,7 @@ export default {
}, },
// 禁用单个widget的滚动条 // 禁用单个widget的滚动条
disableWidgetScrollbar(widget) { disableWidgetScrollbar (widget) {
try { try {
if (!widget) return; if (!widget) return;
...@@ -2154,7 +2058,7 @@ export default { ...@@ -2154,7 +2058,7 @@ export default {
}, },
// 强制隐藏滚动条DOM元素 // 强制隐藏滚动条DOM元素
forceHideScrollbarDOM(widget) { forceHideScrollbarDOM (widget) {
try { try {
if (!widget || !widget.getCanvas) return; if (!widget || !widget.getCanvas) return;
...@@ -2225,7 +2129,7 @@ export default { ...@@ -2225,7 +2129,7 @@ export default {
}, },
// 强制重置到初始状态,不显示滚动条 // 强制重置到初始状态,不显示滚动条
resetToInitialState() { resetToInitialState () {
try { try {
const topEl = this.$refs.topScroll; const topEl = this.$refs.topScroll;
if (topEl) { if (topEl) {
...@@ -2245,7 +2149,7 @@ export default { ...@@ -2245,7 +2149,7 @@ export default {
}, },
// 创建下半屏镜像视图 // 创建下半屏镜像视图
initSecondWidget(canvas) { initSecondWidget (canvas) {
try { try {
this.plotsBottom = new Plot({ this.plotsBottom = new Plot({
'canvasElement': canvas, 'canvasElement': canvas,
...@@ -2319,7 +2223,7 @@ export default { ...@@ -2319,7 +2223,7 @@ export default {
}, },
// 同步滚动条(左右与上下)- 防死循环版本 // 同步滚动条(左右与上下)- 防死循环版本
onScroll(origin) { onScroll (origin) {
// 多重防护:防止死循环 // 多重防护:防止死循环
if (this._isSyncingScroll || this._scrollSyncTimeout) return; if (this._isSyncingScroll || this._scrollSyncTimeout) return;
...@@ -2359,7 +2263,7 @@ export default { ...@@ -2359,7 +2263,7 @@ export default {
}, },
// 让顶部/底部视图缩放同步 // 让顶部/底部视图缩放同步
ensureZoomSyncHook() { ensureZoomSyncHook () {
if (this._zoomHooked) return; if (this._zoomHooked) return;
const top = this._seismicWidget; const top = this._seismicWidget;
const bottom = this._seismicWidgetBottom; const bottom = this._seismicWidgetBottom;
...@@ -2419,7 +2323,7 @@ export default { ...@@ -2419,7 +2323,7 @@ export default {
}, },
// 更新内部滚动条工具 // 更新内部滚动条工具
updateWidgetScrollbar(widget) { updateWidgetScrollbar (widget) {
try { try {
const toolManager = widget && widget.getTool && widget.getTool(); const toolManager = widget && widget.getTool && widget.getTool();
if (!toolManager || !toolManager.getScrollbarTool) return; if (!toolManager || !toolManager.getScrollbarTool) return;
...@@ -2431,7 +2335,7 @@ export default { ...@@ -2431,7 +2335,7 @@ export default {
}, },
// 强制禁用内部滚动条 // 强制禁用内部滚动条
forceDisableInternalScrollbars(widget) { forceDisableInternalScrollbars (widget) {
if (!widget) return; if (!widget) return;
try { try {
...@@ -2504,7 +2408,7 @@ export default { ...@@ -2504,7 +2408,7 @@ export default {
}, },
// 定期检查并禁用内部滚动条 // 定期检查并禁用内部滚动条
startScrollbarMonitor() { startScrollbarMonitor () {
if (this._scrollbarMonitorInterval) { if (this._scrollbarMonitorInterval) {
clearInterval(this._scrollbarMonitorInterval); clearInterval(this._scrollbarMonitorInterval);
} }
...@@ -2547,7 +2451,7 @@ export default { ...@@ -2547,7 +2451,7 @@ export default {
}, },
// 停止滚动条监控 // 停止滚动条监控
stopScrollbarMonitor() { stopScrollbarMonitor () {
if (this._scrollbarMonitorInterval) { if (this._scrollbarMonitorInterval) {
clearInterval(this._scrollbarMonitorInterval); clearInterval(this._scrollbarMonitorInterval);
this._scrollbarMonitorInterval = null; this._scrollbarMonitorInterval = null;
...@@ -2555,7 +2459,7 @@ export default { ...@@ -2555,7 +2459,7 @@ export default {
}, },
// 使用CSS方法彻底禁用内部滚动条 // 使用CSS方法彻底禁用内部滚动条
setScrollbarCSS(widget) { setScrollbarCSS (widget) {
if (!widget || !widget.setCss) return; if (!widget || !widget.setCss) return;
try { try {
...@@ -2665,7 +2569,7 @@ export default { ...@@ -2665,7 +2569,7 @@ export default {
}, },
// 强制同步内部滚动条(如果必须保留内部滚动条) // 强制同步内部滚动条(如果必须保留内部滚动条)
enableInternalScrollbarSync() { enableInternalScrollbarSync () {
if (!this._seismicWidget || !this._seismicWidgetBottom) return; if (!this._seismicWidget || !this._seismicWidgetBottom) return;
try { try {
...@@ -2684,7 +2588,7 @@ export default { ...@@ -2684,7 +2588,7 @@ export default {
}, },
// 设置外层滚动条同步(GeoToolkit 3.2.80兼容模式) // 设置外层滚动条同步(GeoToolkit 3.2.80兼容模式)
setupOuterScrollbarSync() { setupOuterScrollbarSync () {
if (!this._seismicWidget || !this._seismicWidgetBottom) return; if (!this._seismicWidget || !this._seismicWidgetBottom) return;
try { try {
// 清除之前的监听器 // 清除之前的监听器
...@@ -2756,7 +2660,7 @@ export default { ...@@ -2756,7 +2660,7 @@ export default {
}, },
// 清除外层滚动条监听器 // 清除外层滚动条监听器
clearOuterScrollbarListeners() { clearOuterScrollbarListeners () {
try { try {
if (this._outerScrollListeners) { if (this._outerScrollListeners) {
this._outerScrollListeners.forEach(({ element, event, handler }) => { this._outerScrollListeners.forEach(({ element, event, handler }) => {
...@@ -2772,9 +2676,9 @@ export default { ...@@ -2772,9 +2676,9 @@ export default {
}, },
// 防抖函数 // 防抖函数
debounce(func, wait) { debounce (func, wait) {
let timeout; let timeout;
return function executedFunction(...args) { return function executedFunction (...args) {
const later = () => { const later = () => {
clearTimeout(timeout); clearTimeout(timeout);
func(...args); func(...args);
...@@ -2785,7 +2689,7 @@ export default { ...@@ -2785,7 +2689,7 @@ export default {
}, },
// 设置DOM级别的滚动条同步 // 设置DOM级别的滚动条同步
setupDOMScrollbarSync() { setupDOMScrollbarSync () {
try { try {
// 清除之前的DOM监听器 // 清除之前的DOM监听器
this.clearDOMScrollbarListeners(); this.clearDOMScrollbarListeners();
...@@ -2856,7 +2760,7 @@ export default { ...@@ -2856,7 +2760,7 @@ export default {
}, },
// 获取外层滚动容器(GeoToolkit 3.2.80兼容) // 获取外层滚动容器(GeoToolkit 3.2.80兼容)
getOuterScrollContainer(widget) { getOuterScrollContainer (widget) {
try { try {
if (!widget || !widget.getCanvas) return null; if (!widget || !widget.getCanvas) return null;
...@@ -2892,7 +2796,7 @@ export default { ...@@ -2892,7 +2796,7 @@ export default {
}, },
// 同步GeoToolkit内部视图(GeoToolkit 3.2.80兼容) // 同步GeoToolkit内部视图(GeoToolkit 3.2.80兼容)
syncGeoToolkitView(widget, scrollLeft, scrollTop) { syncGeoToolkitView (widget, scrollLeft, scrollTop) {
try { try {
if (!widget) return; if (!widget) return;
...@@ -2952,7 +2856,7 @@ export default { ...@@ -2952,7 +2856,7 @@ export default {
}, },
// 启动外层滚动条同步监控(GeoToolkit 3.2.80兼容) // 启动外层滚动条同步监控(GeoToolkit 3.2.80兼容)
startOuterScrollbarSyncMonitor() { startOuterScrollbarSyncMonitor () {
if (this._outerScrollbarSyncInterval) { if (this._outerScrollbarSyncInterval) {
clearInterval(this._outerScrollbarSyncInterval); clearInterval(this._outerScrollbarSyncInterval);
} }
...@@ -2967,7 +2871,7 @@ export default { ...@@ -2967,7 +2871,7 @@ export default {
}, },
// 强制外层滚动条同步(GeoToolkit 3.2.80兼容) // 强制外层滚动条同步(GeoToolkit 3.2.80兼容)
forceOuterScrollbarSync() { forceOuterScrollbarSync () {
try { try {
if (!this._seismicWidget || !this._seismicWidgetBottom) return; if (!this._seismicWidget || !this._seismicWidgetBottom) return;
...@@ -3011,7 +2915,7 @@ export default { ...@@ -3011,7 +2915,7 @@ export default {
}, },
// 停止外层滚动条同步监控 // 停止外层滚动条同步监控
stopOuterScrollbarSyncMonitor() { stopOuterScrollbarSyncMonitor () {
if (this._outerScrollbarSyncInterval) { if (this._outerScrollbarSyncInterval) {
clearInterval(this._outerScrollbarSyncInterval); clearInterval(this._outerScrollbarSyncInterval);
this._outerScrollbarSyncInterval = null; this._outerScrollbarSyncInterval = null;
...@@ -3019,7 +2923,7 @@ export default { ...@@ -3019,7 +2923,7 @@ export default {
}, },
// 强制隐藏所有内部滚动条 // 强制隐藏所有内部滚动条
forceHideAllInternalScrollbars() { forceHideAllInternalScrollbars () {
try { try {
// 方法1: 禁用widget滚动条 // 方法1: 禁用widget滚动条
if (this._seismicWidget) { if (this._seismicWidget) {
...@@ -3045,7 +2949,7 @@ export default { ...@@ -3045,7 +2949,7 @@ export default {
}, },
// 启动强力滚动条隐藏监控 // 启动强力滚动条隐藏监控
startAggressiveScrollbarHideMonitor() { startAggressiveScrollbarHideMonitor () {
if (this._scrollbarHideInterval) { if (this._scrollbarHideInterval) {
clearInterval(this._scrollbarHideInterval); clearInterval(this._scrollbarHideInterval);
} }
...@@ -3066,7 +2970,7 @@ export default { ...@@ -3066,7 +2970,7 @@ export default {
}, },
// 禁用滚动条交互 // 禁用滚动条交互
disableScrollbarInteractions() { disableScrollbarInteractions () {
try { try {
const rootEl = this.$el || document; const rootEl = this.$el || document;
const scrollbarElements = rootEl.querySelectorAll ? rootEl.querySelectorAll('.sync-section [class*="scrollbar"], .sync-section [class*="Scrollbar"], .sync-section [class*="scroll"], .sync-section [class*="Scroll"], .sync-section [class*="geotoolkit.controls.tools.scroll"]') : []; const scrollbarElements = rootEl.querySelectorAll ? rootEl.querySelectorAll('.sync-section [class*="scrollbar"], .sync-section [class*="Scrollbar"], .sync-section [class*="scroll"], .sync-section [class*="Scroll"], .sync-section [class*="geotoolkit.controls.tools.scroll"]') : [];
...@@ -3106,7 +3010,7 @@ export default { ...@@ -3106,7 +3010,7 @@ export default {
}, },
// 停止滚动条隐藏监控 // 停止滚动条隐藏监控
stopScrollbarHideMonitor() { stopScrollbarHideMonitor () {
if (this._scrollbarHideInterval) { if (this._scrollbarHideInterval) {
clearInterval(this._scrollbarHideInterval); clearInterval(this._scrollbarHideInterval);
this._scrollbarHideInterval = null; this._scrollbarHideInterval = null;
...@@ -3114,7 +3018,7 @@ export default { ...@@ -3114,7 +3018,7 @@ export default {
}, },
// 测试外层滚动条同步(GeoToolkit 3.2.80兼容) // 测试外层滚动条同步(GeoToolkit 3.2.80兼容)
testOuterScrollbarSync() { testOuterScrollbarSync () {
try { try {
console.log('=== 测试外层滚动条同步 ==='); console.log('=== 测试外层滚动条同步 ===');
...@@ -3160,7 +3064,7 @@ export default { ...@@ -3160,7 +3064,7 @@ export default {
}, },
// 测试内部滚动条是否被隐藏 // 测试内部滚动条是否被隐藏
testInternalScrollbarHidden() { testInternalScrollbarHidden () {
try { try {
console.log('=== 测试内部滚动条是否被隐藏 ==='); console.log('=== 测试内部滚动条是否被隐藏 ===');
...@@ -3214,7 +3118,7 @@ export default { ...@@ -3214,7 +3118,7 @@ export default {
}, },
// 强制禁用内部滚动条(GeoToolkit 3.2.80兼容) // 强制禁用内部滚动条(GeoToolkit 3.2.80兼容)
forceDisableInternalScrollbars() { forceDisableInternalScrollbars () {
try { try {
if (!this._seismicWidget || !this._seismicWidgetBottom) return; if (!this._seismicWidget || !this._seismicWidgetBottom) return;
...@@ -3268,18 +3172,18 @@ export default { ...@@ -3268,18 +3172,18 @@ export default {
}, },
// 启动滚动条同步状态监控 // 启动滚动条同步状态监控
startScrollbarSyncStatusMonitor() { startScrollbarSyncStatusMonitor () {
// 已禁用内部滚动条同步,直接返回 // 已禁用内部滚动条同步,直接返回
return; return;
}, },
// 确保滚动条同步(已禁用内部同步,直接返回) // 确保滚动条同步(已禁用内部同步,直接返回)
ensureScrollbarSync() { ensureScrollbarSync () {
return; return;
}, },
// 停止滚动条同步状态监控 // 停止滚动条同步状态监控
stopScrollbarSyncStatusMonitor() { stopScrollbarSyncStatusMonitor () {
if (this._scrollbarSyncStatusInterval) { if (this._scrollbarSyncStatusInterval) {
clearInterval(this._scrollbarSyncStatusInterval); clearInterval(this._scrollbarSyncStatusInterval);
this._scrollbarSyncStatusInterval = null; this._scrollbarSyncStatusInterval = null;
...@@ -3287,14 +3191,14 @@ export default { ...@@ -3287,14 +3191,14 @@ export default {
}, },
// 添加强制隐藏滚动条的CSS(GeoToolkit 3.2.80兼容) // 添加强制隐藏滚动条的CSS(GeoToolkit 3.2.80兼容)
addForceHideScrollbarCSS() { addForceHideScrollbarCSS () {
// 为避免影响全局左侧菜单,这里不再注入全局隐藏滚动条的样式。 // 为避免影响全局左侧菜单,这里不再注入全局隐藏滚动条的样式。
// 内部滚动条隐藏交由 .sync-section 作用域 CSS 与 DOM 级隐藏来完成。 // 内部滚动条隐藏交由 .sync-section 作用域 CSS 与 DOM 级隐藏来完成。
return; return;
}, },
// 启动强力滚动条监控 // 启动强力滚动条监控
startAggressiveScrollbarMonitor() { startAggressiveScrollbarMonitor () {
// 仅监控本页面容器,避免影响全局(菜单/标题) // 仅监控本页面容器,避免影响全局(菜单/标题)
if (this._scrollbarObserver) { if (this._scrollbarObserver) {
this._scrollbarObserver.disconnect(); this._scrollbarObserver.disconnect();
...@@ -3332,7 +3236,7 @@ export default { ...@@ -3332,7 +3236,7 @@ export default {
}, },
// 隐藏单个滚动条元素 // 隐藏单个滚动条元素
hideScrollbarElement(element) { hideScrollbarElement (element) {
if (!element || !element.classList) return; if (!element || !element.classList) return;
const classList = Array.from(element.classList); const classList = Array.from(element.classList);
...@@ -3356,7 +3260,7 @@ export default { ...@@ -3356,7 +3260,7 @@ export default {
}, },
// 强制隐藏所有滚动条(仅作用于给定根节点,默认当前组件内) // 强制隐藏所有滚动条(仅作用于给定根节点,默认当前组件内)
forceHideAllScrollbars(root) { forceHideAllScrollbars (root) {
const rootEl = root || this.$el || document; const rootEl = root || this.$el || document;
const query = rootEl.querySelectorAll ? rootEl.querySelectorAll.bind(rootEl) : document.querySelectorAll.bind(document); const query = rootEl.querySelectorAll ? rootEl.querySelectorAll.bind(rootEl) : document.querySelectorAll.bind(document);
const selectors = [ const selectors = [
...@@ -3379,7 +3283,7 @@ export default { ...@@ -3379,7 +3283,7 @@ export default {
}, },
// 停止强力滚动条监控 // 停止强力滚动条监控
stopAggressiveScrollbarMonitor() { stopAggressiveScrollbarMonitor () {
if (this._scrollbarObserver) { if (this._scrollbarObserver) {
this._scrollbarObserver.disconnect(); this._scrollbarObserver.disconnect();
this._scrollbarObserver = null; this._scrollbarObserver = null;
...@@ -3391,7 +3295,7 @@ export default { ...@@ -3391,7 +3295,7 @@ export default {
}, },
// 强制禁用所有滚动条 // 强制禁用所有滚动条
forceDisableAllScrollbars() { forceDisableAllScrollbars () {
try { try {
// 禁用widget滚动条 // 禁用widget滚动条
if (this._seismicWidget) { if (this._seismicWidget) {
...@@ -3414,7 +3318,7 @@ export default { ...@@ -3414,7 +3318,7 @@ export default {
}, },
// 添加全局滚动条隐藏CSS // 添加全局滚动条隐藏CSS
addGlobalScrollbarHideCSS() { addGlobalScrollbarHideCSS () {
try { try {
// 检查是否已经添加过样式 // 检查是否已经添加过样式
if (document.getElementById('geotoolkit-scrollbar-hide')) { if (document.getElementById('geotoolkit-scrollbar-hide')) {
...@@ -3455,7 +3359,7 @@ export default { ...@@ -3455,7 +3359,7 @@ export default {
} }
}, },
createScene(canvas) { createScene (canvas, options) {
try { try {
const autoFormat = new AutoNumberFormat(4); const autoFormat = new AutoNumberFormat(4);
// 创建 Plot 实例,同时创建 SeismicWidget // 创建 Plot 实例,同时创建 SeismicWidget
...@@ -3579,9 +3483,10 @@ export default { ...@@ -3579,9 +3483,10 @@ export default {
// 初始化默认的颜色映射,使用256色以获得更平滑的渐变 // 初始化默认的颜色映射,使用256色以获得更平滑的渐变
this._colorMap = this.colorProvider.createNamedColorMap('WhiteBlack', 256); this._colorMap = this.colorProvider.createNamedColorMap('WhiteBlack', 256);
// 加载数据 // 根据需要加载默认演示数据
this.$nextTick(() => { this.$nextTick(() => {
this.handleFileSelect(this.plots).then(() => { const autoload = options && options.autoloadDemo === false ? false : this.shouldLoadDemo;
const doAfterLoad = () => {
// 数据加载完成后更新轴标题 // 数据加载完成后更新轴标题
if (this.pipeline && this._seismicWidget) { if (this.pipeline && this._seismicWidget) {
this._seismicWidget.setOptions({ this._seismicWidget.setOptions({
...@@ -3625,7 +3530,14 @@ export default { ...@@ -3625,7 +3530,14 @@ export default {
// 启用内部滚动条同步 // 启用内部滚动条同步
this.enableInternalScrollbarSync(); this.enableInternalScrollbarSync();
}); });
}); };
if (autoload) {
this.handleFileSelect(this.plots).then(doAfterLoad);
} else {
// 不加载演示数据,直接走后续初始化(保持空画布)
doAfterLoad();
}
}); });
} catch (error) { } catch (error) {
this.loadingError = `创建场景失败: ${error.message}`; this.loadingError = `创建场景失败: ${error.message}`;
...@@ -3633,7 +3545,7 @@ export default { ...@@ -3633,7 +3545,7 @@ export default {
} }
}, },
handleFileSelect(plot) { handleFileSelect (plot) {
let url = process.env.VUE_APP_BASE_API + "/ndy/dz/getSegyDataFile?fileName=density.segy"; let url = process.env.VUE_APP_BASE_API + "/ndy/dz/getSegyDataFile?fileName=density.segy";
let fileName = 'density.segy'; let fileName = 'density.segy';
...@@ -3798,20 +3710,20 @@ export default { ...@@ -3798,20 +3710,20 @@ export default {
}); });
}, },
handleMouseMove(event) { handleMouseMove (event) {
if (!this._seismicWidget || !this.isHovering) return; if (!this._seismicWidget || !this.isHovering) return;
// 使用内置状态栏,不需要额外的处理逻辑 // 使用内置状态栏,不需要额外的处理逻辑
}, },
onFileOpen(evt, plot, fileInfo) { onFileOpen (evt, plot, fileInfo) {
evt.stopPropagation(); evt.stopPropagation();
evt.preventDefault(); evt.preventDefault();
const files = evt.target.files; const files = evt.target.files;
return this.handleFileSelect(this.plots); return this.handleFileSelect(this.plots);
}, },
initAnnotationTools(widget) { initAnnotationTools (widget) {
if (!this.checkWidgetStatus()) { if (!this.checkWidgetStatus()) {
console.error('Widget status check failed'); console.error('Widget status check failed');
return; return;
...@@ -3950,7 +3862,7 @@ export default { ...@@ -3950,7 +3862,7 @@ export default {
} }
}, },
toggleDrawText() { toggleDrawText () {
if (!this.checkWidgetStatus() || !this.isWidgetReady) { if (!this.checkWidgetStatus() || !this.isWidgetReady) {
console.warn('Widget or annotation tools not ready'); console.warn('Widget or annotation tools not ready');
return; return;
...@@ -4114,7 +4026,7 @@ export default { ...@@ -4114,7 +4026,7 @@ export default {
} }
}, },
removeAnnotation() { removeAnnotation () {
if (this.annotationTool && this.annotationTool.isEnabled() && if (this.annotationTool && this.annotationTool.isEnabled() &&
this.annotationTool.getMode() === PaintMode.Edit && this.annotationTool.getMode() === PaintMode.Edit &&
this.annotationTool.getShape()) { this.annotationTool.getShape()) {
...@@ -4127,7 +4039,7 @@ export default { ...@@ -4127,7 +4039,7 @@ export default {
} }
}, },
updateAllStyles() { updateAllStyles () {
if (this.annotationTool && this.annotationTool.getShape()) { if (this.annotationTool && this.annotationTool.getShape()) {
const shape = this.annotationTool.getShape(); const shape = this.annotationTool.getShape();
...@@ -4210,7 +4122,7 @@ export default { ...@@ -4210,7 +4122,7 @@ export default {
}, },
// 修改字体大小变化处理方法 // 修改字体大小变化处理方法
handleFontSizeChange(value) { handleFontSizeChange (value) {
this.textStyle.size = value; this.textStyle.size = value;
this.updateAllStyles(); this.updateAllStyles();
...@@ -4250,7 +4162,7 @@ export default { ...@@ -4250,7 +4162,7 @@ export default {
}, },
// 修改字体变化处理方法 // 修改字体变化处理方法
handleFontChange(value) { handleFontChange (value) {
this.textStyle.font = value; this.textStyle.font = value;
this.updateAllStyles(); this.updateAllStyles();
...@@ -4289,15 +4201,15 @@ export default { ...@@ -4289,15 +4201,15 @@ export default {
}, },
// 修改字体样式处理方法 // 修改字体样式处理方法
handleFontStyleChange() { handleFontStyleChange () {
this.updateAllStyles(); this.updateAllStyles();
}, },
updateTextStyle() { updateTextStyle () {
this.updateAllStyles(); this.updateAllStyles();
}, },
updateLineStyle() { updateLineStyle () {
// 创建新的线条样式 // 创建新的线条样式
const lineStyle = new LineStyle({ const lineStyle = new LineStyle({
color: this.lineStyle.color, color: this.lineStyle.color,
...@@ -4361,11 +4273,11 @@ export default { ...@@ -4361,11 +4273,11 @@ export default {
} }
}, },
updateFillStyle() { updateFillStyle () {
this.updateAllStyles(); this.updateAllStyles();
}, },
getFillPatternStyle(key) { getFillPatternStyle (key) {
// 基本样式对象 // 基本样式对象
const baseStyle = { const baseStyle = {
height: '24px', height: '24px',
...@@ -4406,7 +4318,7 @@ export default { ...@@ -4406,7 +4318,7 @@ export default {
return baseStyle; return baseStyle;
}, },
getLinePatternStyle(key) { getLinePatternStyle (key) {
let dashStyle = ''; let dashStyle = '';
// 使用处理后的线条模式 // 使用处理后的线条模式
...@@ -4427,7 +4339,7 @@ export default { ...@@ -4427,7 +4339,7 @@ export default {
}; };
}, },
getProcessedLinePattern(pattern) { getProcessedLinePattern (pattern) {
// 如果pattern是数组,直接返回 // 如果pattern是数组,直接返回
if (Array.isArray(pattern)) { if (Array.isArray(pattern)) {
return pattern; return pattern;
...@@ -4467,7 +4379,7 @@ export default { ...@@ -4467,7 +4379,7 @@ export default {
return []; return [];
}, },
debounce(fn, delay = 300) { debounce (fn, delay = 300) {
let timer = null; let timer = null;
return (...args) => { return (...args) => {
if (timer) clearTimeout(timer); if (timer) clearTimeout(timer);
...@@ -4477,7 +4389,7 @@ export default { ...@@ -4477,7 +4389,7 @@ export default {
}; };
}, },
checkWidgetStatus() { checkWidgetStatus () {
if (!this._seismicWidget) { if (!this._seismicWidget) {
console.warn('Widget未初始化'); console.warn('Widget未初始化');
this.loadingError = 'Widget未初始化'; this.loadingError = 'Widget未初始化';
...@@ -4507,7 +4419,7 @@ export default { ...@@ -4507,7 +4419,7 @@ export default {
}, },
// 修改边框圆角更新方法 // 修改边框圆角更新方法
handleBorderRadiusChange(value) { handleBorderRadiusChange (value) {
// 确保值为数字 // 确保值为数字
const radius = parseInt(value) || 0; const radius = parseInt(value) || 0;
this.textStyle.borderRadius = radius; this.textStyle.borderRadius = radius;
...@@ -4515,13 +4427,13 @@ export default { ...@@ -4515,13 +4427,13 @@ export default {
}, },
// 修改固定字体更新方法 // 修改固定字体更新方法
handleFixedFontChange(value) { handleFixedFontChange (value) {
this.textStyle.fixedFont = value; this.textStyle.fixedFont = value;
this.updateAllStyles(); this.updateAllStyles();
}, },
// 添加清除所有工具状态的方法 // 添加清除所有工具状态的方法
clearAllTools() { clearAllTools () {
this.showTextStylePanel = false; this.showTextStylePanel = false;
this.showLineStylePanel = false; this.showLineStylePanel = false;
this.isDrawingText = false; this.isDrawingText = false;
...@@ -4543,7 +4455,7 @@ export default { ...@@ -4543,7 +4455,7 @@ export default {
}, },
// 修改请求重绘的方法 // 修改请求重绘的方法
requestRepaint() { requestRepaint () {
// 只调用有invalidate方法的对象 // 只调用有invalidate方法的对象
if (this._seismicWidget) { if (this._seismicWidget) {
this._seismicWidget.invalidate(); this._seismicWidget.invalidate();
...@@ -4557,7 +4469,7 @@ export default { ...@@ -4557,7 +4469,7 @@ export default {
}, },
// 添加更新选择视觉反馈的方法 // 添加更新选择视觉反馈的方法
updateSelectionVisualFeedback() { updateSelectionVisualFeedback () {
// 更新所有形状的选中状态 // 更新所有形状的选中状态
if (this.annotationLayer) { if (this.annotationLayer) {
const children = this.annotationLayer.getChildren(); const children = this.annotationLayer.getChildren();
...@@ -4574,7 +4486,7 @@ export default { ...@@ -4574,7 +4486,7 @@ export default {
}, },
// 添加切换颜色映射的方法 // 添加切换颜色映射的方法
switchColorMap(colorMapName) { switchColorMap (colorMapName) {
if (!this.pipeline || !this.colorProvider) { if (!this.pipeline || !this.colorProvider) {
console.error('Pipeline or colorProvider not initialized'); console.error('Pipeline or colorProvider not initialized');
return; return;
...@@ -4625,7 +4537,7 @@ export default { ...@@ -4625,7 +4537,7 @@ export default {
}, },
// 添加注册颜色映射的方法 // 添加注册颜色映射的方法
registerColorMaps(colorProvider) { registerColorMaps (colorProvider) {
if (!colorProvider) { if (!colorProvider) {
console.error('colorProvider为空,无法注册颜色映射'); console.error('colorProvider为空,无法注册颜色映射');
return; return;
...@@ -4898,7 +4810,7 @@ export default { ...@@ -4898,7 +4810,7 @@ export default {
} }
}, },
toggleLineStylePanel() { toggleLineStylePanel () {
// 如果工具已经激活,则停用 // 如果工具已经激活,则停用
if (this.showLineStylePanel) { if (this.showLineStylePanel) {
this.deactivatePencilTool(); this.deactivatePencilTool();
...@@ -4998,7 +4910,7 @@ export default { ...@@ -4998,7 +4910,7 @@ export default {
this.pencilTool.setEnabled(true); this.pencilTool.setEnabled(true);
}, },
deactivatePencilTool() { deactivatePencilTool () {
this.showLineStylePanel = false; this.showLineStylePanel = false;
if (this.pencilTool) { if (this.pencilTool) {
this.pencilTool.setEnabled(false); this.pencilTool.setEnabled(false);
...@@ -5016,15 +4928,15 @@ export default { ...@@ -5016,15 +4928,15 @@ export default {
} }
}, },
zoomIn() { zoomIn () {
this.zoomScale = Math.min(this.zoomScale * 1.2, 6); this.zoomScale = Math.min(this.zoomScale * 1.2, 6);
}, },
zoomOut() { zoomOut () {
this.zoomScale = Math.max(this.zoomScale / 1.2, 0.2); this.zoomScale = Math.max(this.zoomScale / 1.2, 0.2);
}, },
async exportToPDF(data) { async exportToPDF (data) {
if (!this.plots || !this.isWidgetReady) { if (!this.plots || !this.isWidgetReady) {
this.$message.warning('请等待数据加载完成'); this.$message.warning('请等待数据加载完成');
return; return;
...@@ -5045,7 +4957,7 @@ export default { ...@@ -5045,7 +4957,7 @@ export default {
/** /**
* 显示右键菜单 * 显示右键菜单
*/ */
showContextMenu(event) { showContextMenu (event) {
event.preventDefault(); event.preventDefault();
// 获取当前活动的工具 // 获取当前活动的工具
...@@ -5089,7 +5001,7 @@ export default { ...@@ -5089,7 +5001,7 @@ export default {
/** /**
* 隐藏右键菜单 * 隐藏右键菜单
*/ */
hideContextMenu() { hideContextMenu () {
if (this.contextMenu.visible) { if (this.contextMenu.visible) {
this.contextMenu.visible = false; this.contextMenu.visible = false;
this._contextMenuTool = null; this._contextMenuTool = null;
...@@ -5100,7 +5012,7 @@ export default { ...@@ -5100,7 +5012,7 @@ export default {
/** /**
* 检查菜单项是否可用 * 检查菜单项是否可用
*/ */
isMenuItemEnabled(action) { isMenuItemEnabled (action) {
// 获取当前活动的工具 // 获取当前活动的工具
const tool = this._contextMenuTool; const tool = this._contextMenuTool;
...@@ -5126,7 +5038,7 @@ export default { ...@@ -5126,7 +5038,7 @@ export default {
/** /**
* 处理菜单动作 * 处理菜单动作
*/ */
handleMenuAction(action) { handleMenuAction (action) {
if (!this.isMenuItemEnabled(action)) return; if (!this.isMenuItemEnabled(action)) return;
const tool = this._contextMenuTool; const tool = this._contextMenuTool;
...@@ -5168,7 +5080,7 @@ export default { ...@@ -5168,7 +5080,7 @@ export default {
this.requestRepaint(); this.requestRepaint();
}, },
copyShape(tool) { copyShape (tool) {
const shape = tool.getShape(); const shape = tool.getShape();
if (!shape) return; if (!shape) return;
...@@ -5178,7 +5090,7 @@ export default { ...@@ -5178,7 +5090,7 @@ export default {
[shape.clone()]; [shape.clone()];
}, },
pasteShape() { pasteShape () {
if (!this.clipboard || this.clipboard.length === 0) return; if (!this.clipboard || this.clipboard.length === 0) return;
// 创建偏移量,以便粘贴的形状不会完全覆盖原始形状 // 创建偏移量,以便粘贴的形状不会完全覆盖原始形状
...@@ -5200,7 +5112,7 @@ export default { ...@@ -5200,7 +5112,7 @@ export default {
this.requestRepaint(); this.requestRepaint();
}, },
deleteShape(tool) { deleteShape (tool) {
const shape = tool.getShape(); const shape = tool.getShape();
if (!shape) return; if (!shape) return;
...@@ -5226,7 +5138,7 @@ export default { ...@@ -5226,7 +5138,7 @@ export default {
this.requestRepaint(); this.requestRepaint();
}, },
handleKeyDown(event) { handleKeyDown (event) {
// 检查是否有活动的工具 // 检查是否有活动的工具
const activeTool = this.pencilTool && this.pencilTool.isEnabled() ? this.pencilTool : const activeTool = this.pencilTool && this.pencilTool.isEnabled() ? this.pencilTool :
(this.annotationTool && this.annotationTool.isEnabled() ? this.annotationTool : null); (this.annotationTool && this.annotationTool.isEnabled() ? this.annotationTool : null);
...@@ -5272,7 +5184,7 @@ export default { ...@@ -5272,7 +5184,7 @@ export default {
}, },
// 添加一个新方法,用于切换形状的编辑状态 // 添加一个新方法,用于切换形状的编辑状态
toggleShapeEditMode(shape) { toggleShapeEditMode (shape) {
if (!shape) return; if (!shape) return;
// 获取活动工具 // 获取活动工具
...@@ -5296,7 +5208,7 @@ export default { ...@@ -5296,7 +5208,7 @@ export default {
this.requestRepaint(); this.requestRepaint();
}, },
getElementIcon(mdiIcon) { getElementIcon (mdiIcon) {
// 将Vuetify的mdi图标转换为Element UI图标 // 将Vuetify的mdi图标转换为Element UI图标
const iconMap = { const iconMap = {
'mdi-undo': 'el-icon-refresh-left', 'mdi-undo': 'el-icon-refresh-left',
...@@ -5310,19 +5222,19 @@ export default { ...@@ -5310,19 +5222,19 @@ export default {
}, },
// 添加鼠标悬停相关事件 // 添加鼠标悬停相关事件
initCursorTools() { initCursorTools () {
// 实现鼠标悬停相关事件的初始化逻辑 // 实现鼠标悬停相关事件的初始化逻辑
}, },
// 添加鼠标移动处理方法 // 添加鼠标移动处理方法
handleMouseMove(event) { handleMouseMove (event) {
if (!this._seismicWidget || !this.isHovering) return; if (!this._seismicWidget || !this.isHovering) return;
// 使用内置状态栏,不需要额外的处理逻辑 // 使用内置状态栏,不需要额外的处理逻辑
}, },
// 添加保存标注数据的方法 // 添加保存标注数据的方法
saveAnnotation(node) { saveAnnotation (node) {
if (!node) { if (!node) {
console.warn('无法保存标注:节点为空'); console.warn('无法保存标注:节点为空');
return; return;
...@@ -5406,7 +5318,7 @@ export default { ...@@ -5406,7 +5318,7 @@ export default {
}, },
// 添加恢复标注数据的方法 // 添加恢复标注数据的方法
restoreAnnotations() { restoreAnnotations () {
// 先恢复文本标注 // 先恢复文本标注
if (!this.annotations || !this._seismicWidget || !this.savedAnnotations) { if (!this.annotations || !this._seismicWidget || !this.savedAnnotations) {
console.warn('无法恢复标注:缺少必要组件', { console.warn('无法恢复标注:缺少必要组件', {
...@@ -5488,7 +5400,7 @@ export default { ...@@ -5488,7 +5400,7 @@ export default {
}, },
// 添加恢复线条标注的方法 // 添加恢复线条标注的方法
restoreLineAnnotations() { restoreLineAnnotations () {
if (!this.annotations || !this._seismicWidget || !this.savedLineAnnotations) { if (!this.annotations || !this._seismicWidget || !this.savedLineAnnotations) {
console.warn('无法恢复线条标注:缺少必要组件'); console.warn('无法恢复线条标注:缺少必要组件');
return; return;
...@@ -5561,7 +5473,7 @@ export default { ...@@ -5561,7 +5473,7 @@ export default {
}, },
// 添加在指定位置创建文本的方法 // 添加在指定位置创建文本的方法
createTextAtPosition() { createTextAtPosition () {
if (!this._seismicWidget || !this.annotations) { if (!this._seismicWidget || !this.annotations) {
console.warn('Widget or annotations layer not ready'); console.warn('Widget or annotations layer not ready');
return; return;
...@@ -5611,7 +5523,7 @@ export default { ...@@ -5611,7 +5523,7 @@ export default {
}, },
// 添加新的辅助方法 // 添加新的辅助方法
detectChanges(previousState, currentNode) { detectChanges (previousState, currentNode) {
if (!previousState || !currentNode) return {}; if (!previousState || !currentNode) return {};
const changes = {}; const changes = {};
...@@ -5668,7 +5580,7 @@ export default { ...@@ -5668,7 +5580,7 @@ export default {
}, },
// 切换内部滚动条同步 // 切换内部滚动条同步
toggleInternalScrollbarSync() { toggleInternalScrollbarSync () {
this.internalScrollbarSyncEnabled = !this.internalScrollbarSyncEnabled; this.internalScrollbarSyncEnabled = !this.internalScrollbarSyncEnabled;
if (this.internalScrollbarSyncEnabled) { if (this.internalScrollbarSyncEnabled) {
...@@ -5686,7 +5598,7 @@ export default { ...@@ -5686,7 +5598,7 @@ export default {
} }
}, },
beforeDestroy() { beforeDestroy () {
// 如果缩略图容器被移动到body,销毁前移回组件内,避免遗留 // 如果缩略图容器被移动到body,销毁前移回组件内,避免遗留
try { try {
if (this.$refs && this.$refs.thumbContainer && this.$refs.thumbContainer.parentNode === document.body) { if (this.$refs && this.$refs.thumbContainer && this.$refs.thumbContainer.parentNode === document.body) {
...@@ -5791,7 +5703,7 @@ export default { ...@@ -5791,7 +5703,7 @@ export default {
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
gap: 12px; gap: 12px;
margin-bottom: 220px; margin-bottom: 110px;
/* 顶部操作与地震图拉开距离 */ /* 顶部操作与地震图拉开距离 */
min-width: 100%; min-width: 100%;
/* 确保有足够宽度 */ /* 确保有足够宽度 */
...@@ -5799,6 +5711,7 @@ export default { ...@@ -5799,6 +5711,7 @@ export default {
/* 允许内容溢出显示 */ /* 允许内容溢出显示 */
position: relative; position: relative;
z-index: 20; z-index: 20;
/* border: 1px solid blue; */
/* 确保不被地震图覆盖 */ /* 确保不被地震图覆盖 */
} }
...@@ -5811,24 +5724,17 @@ export default { ...@@ -5811,24 +5724,17 @@ export default {
} }
.right-thumb { .right-thumb {
display: flex;
flex-direction: column;
width: 260px;
height: 200px;
/* 固定高度,确保有足够空间 */
min-height: 200px;
background: #ffffff;
cursor: pointer;
position: fixed; position: fixed;
top: 16px; /* 固定在视口右上角 */
right: 16px; top: 50px;
right: 40px;
width: 280px;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
z-index: 9999; z-index: 9999;
flex-shrink: 0; /* 确保在画布之上 */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
border-radius: 4px; border-radius: 4px;
border: 1px solid #dcdfe6;
visibility: visible !important;
opacity: 1 !important;
} }
.thumb-title { .thumb-title {
...@@ -6013,7 +5919,7 @@ export default { ...@@ -6013,7 +5919,7 @@ export default {
.toolbar .el-button.active { .toolbar .el-button.active {
background-color: #e6e6e6; background-color: #e6e6e6;
border-color: #adadad; border-color: #adadad;
color: #409EFF; color: #409eff;
} }
/* 鼠标悬停信息面板样式 */ /* 鼠标悬停信息面板样式 */
...@@ -6279,27 +6185,48 @@ export default { ...@@ -6279,27 +6185,48 @@ export default {
} }
.CustomRedScale { .CustomRedScale {
background: linear-gradient(to right, #F62814, #DD8B66, #D7C692, #FBFAFF, #6E6E8A, #323136); background: linear-gradient(to right,
#f62814,
#dd8b66,
#d7c692,
#fbfaff,
#6e6e8a,
#323136);
} }
.BlueWhiteRed { .BlueWhiteRed {
background: linear-gradient(to right, #0000FF, #FFFFFF, #FF0000); background: linear-gradient(to right, #0000ff, #ffffff, #ff0000);
} }
.Rainbow { .Rainbow {
background: linear-gradient(to right, #FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000); background: linear-gradient(to right,
#ff0000,
#ffff00,
#00ff00,
#00ffff,
#0000ff,
#ff00ff,
#ff0000);
} }
.Jet { .Jet {
background: linear-gradient(to right, #00008F, #0000FF, #00FFFF, #00FF00, #FFFF00, #FF7F00, #FF0000, #7F0000); background: linear-gradient(to right,
#00008f,
#0000ff,
#00ffff,
#00ff00,
#ffff00,
#ff7f00,
#ff0000,
#7f0000);
} }
.Hot { .Hot {
background: linear-gradient(to right, #000000, #FF0000, #FFFF00, #FFFFFF); background: linear-gradient(to right, #000000, #ff0000, #ffff00, #ffffff);
} }
.Cool { .Cool {
background: linear-gradient(to right, #00FFFF, #FF00FF); background: linear-gradient(to right, #00ffff, #ff00ff);
} }
/* 在style标签中添加 */ /* 在style标签中添加 */
...@@ -6406,8 +6333,9 @@ export default { ...@@ -6406,8 +6333,9 @@ export default {
.scrollbar-track, .scrollbar-track,
.gt-scrollbar-thumb, .gt-scrollbar-thumb,
.gt-scrollbar-track, .gt-scrollbar-track,
[class*="thumb"], /* 仅在地震图可滚动区域内隐藏内部滚动条相关“thumb/track”,避免误伤缩略图 */
[class*="track"] { .sync-section [class*="thumb"]:not(.thumb-holder):not(.thumb-title):not(.right-thumb),
.sync-section [class*="track"] {
display: none !important; display: none !important;
visibility: hidden !important; visibility: hidden !important;
opacity: 0 !important; opacity: 0 !important;
...@@ -6482,27 +6410,6 @@ export default { ...@@ -6482,27 +6410,6 @@ export default {
</style> </style>
<style> <style>
/* 让被移动到 body 下的缩略图容器也能生效(非 scoped 全局样式) */
.right-thumb {
display: flex;
flex-direction: column;
width: 260px;
height: 200px;
min-height: 200px;
background: #ffffff;
cursor: pointer;
position: fixed;
top: 16px;
right: 16px;
z-index: 9999;
flex-shrink: 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
border-radius: 4px;
border: 1px solid #dcdfe6;
visibility: visible !important;
opacity: 1 !important;
}
.thumb-holder { .thumb-holder {
flex: none; flex: none;
width: 260px; width: 260px;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<template>
<template>
<div class="ysgc-container"
:class="{ compact }">
<!-- <el-form :inline="true" size="small" class="toolbar" label-width="80px">
<el-form-item label="项目名称">
<el-input v-model="filters.projectName" placeholder="请输入" class="input" />
</el-form-item>
<el-form-item label="区块">
<el-input v-model="filters.block" placeholder="请输入" class="input" />
</el-form-item>
</el-form> -->
<div ref="chartRef"
class="chart"
:style="compact ? { width: (width || 260) + 'px', height: (height || 160) + 'px' } : {}"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { toDht } from '@/api/ysqqXmxx/ysqqXmxx'
export default {
name: 'YsgcIndex',
props: {
compact: { type: Boolean, default: false },
width: { type: Number, default: 0 },
height: { type: Number, default: 0 },
idOverride: { type: [String, Number], default: null }
},
data () {
return {
chart: null,
resizeObserver: null,
loadingDht: false,
dhtResult: null,
segyLines: [],
filters: {
projectName: '',
block: ''
},
// 示例数据,后续可由接口/路由参数加载
xMin: null,
xMax: null,
yMin: null,
yMax: null,
verticalLineX: null,
points: []
}
},
mounted () {
// 仅使用延迟初始化,确保容器有尺寸后再 init
this.deferInit()
window.addEventListener('resize', this.resizeChart)
// 若路由中带有 id,则尝试调用接口
this.loadDht()
// 兜底:在下一帧强制渲染一次(compact 时保证首屏显示)
this.$nextTick(() => setTimeout(() => {
if (this.chart) {
this.renderChart()
this.chart.resize()
}
}, 50))
// 对于缩略图模式,确保即使在隐藏状态下也能渲染
if (this.compact) {
// 强制初始化并渲染
this.$nextTick(() => {
this.initChart()
this.renderChart()
})
}
},
created () {
// 尽早触发接口调用,进入页面即发起请求
this.loadDht()
},
activated () {
// 当页面被 keep-alive 缓存后再次进入时,确保尺寸和图表刷新
this.deferInit()
this.resizeChart()
},
beforeDestroy () {
window.removeEventListener('resize', this.resizeChart)
if (this.chart) {
this.chart.dispose()
this.chart = null
}
if (this.resizeObserver) {
try { this.resizeObserver.disconnect() } catch (e) { }
this.resizeObserver = null
}
},
methods: {
// 等待容器有有效尺寸再初始化,避免 echarts 容器宽高为 0 报错
deferInit () {
const tryInit = () => {
const el = this.$refs.chartRef
if (!el) return
// 缩略图模式:尺寸已知,直接初始化
if (this.compact) {
this.initChart()
return
}
let w = el.clientWidth
let h = el.clientHeight
console.log('[ysgc] before size', w, h)
if (w === 0) {
el.style.width = '800px'
w = el.clientWidth
}
if (h === 0) {
// 若元素当前不可见(display: none)或父容器高度为 0,clientHeight 依然为 0
// 使用 ResizeObserver 监听直到有高度后再初始化
if (!this.resizeObserver) {
this.resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const cr = entry.contentRect
if (cr.height > 0 && cr.width > 0) {
console.log('[ysgc] ResizeObserver visible', cr.width, cr.height)
if (this.resizeObserver) {
try { this.resizeObserver.disconnect() } catch (e) { }
this.resizeObserver = null
}
this.initChart()
}
}
})
this.resizeObserver.observe(el)
}
}
console.log('[ysgc] after size', w, h)
// 即使高度为 0,也先用回退尺寸初始化,待可见后再 resize
this.initChart()
// 兜底:稍后再尝试一次 resize
setTimeout(() => this.resizeChart(), 150)
}
this.$nextTick(tryInit)
},
resizeChart () {
if (this.chart) this.chart.resize()
},
initChart () {
const el = this.$refs.chartRef
if (!el) return
if (this.chart) {
this.chart.dispose()
this.chart = null
}
// 当容器高度为 0 时,先用显式宽高初始化,等可见后再 resize
const initWidth = this.compact ? (this.width || 260) : (el.clientWidth || 800)
const initHeight = this.compact ? (this.height || 160) : (el.clientHeight || 600)
this.chart = echarts.init(el, null, { width: initWidth, height: initHeight })
// 初始渲染
this.renderChart()
this.resizeChart()
// 对于缩略图模式,确保渲染成功
if (this.compact) {
console.log('[ysgc] 缩略图初始化完成', initWidth, initHeight)
}
},
// 数据变化后自动刷新(确保缩略图及时绘制)
_requestRender () {
if (!this.chart) return
this.$nextTick(() => {
this.renderChart()
this.chart.resize()
// 确保缩略图正确显示
if (this.compact) {
console.log('[ysgc] 缩略图渲染完成')
}
})
},
// 调用地层/断层图接口(示例),优先从路由参数获取 id
loadDht () {
if (this.loadingDht || this.dhtResult) return
try {
const route = this.$route || {}
const params = route.params || {}
const query = route.query || {}
const id = this.idOverride != null ? this.idOverride : (params.zbid || query.zbid || params.id || query.id)
if (!id) return
this.loadingDht = true
toDht(id)
.then(res => {
// 根据后端返回结构做适配:优先取 data 字段
this.dhtResult = (res && (res.data !== undefined ? res.data : res)) || null
this.applyDhtResult()
if (this.chart) this._requestRender()
})
.catch(err => {
// 保留错误日志,避免打断现有流程
console.error('[ysgc] toDht error:', err)
})
.finally(() => {
this.loadingDht = false
})
} catch (e) {
console.error('[ysgc] loadDht failed:', e)
}
},
// 将接口返回的数据应用到图表状态
applyDhtResult () {
const data = this.dhtResult || {}
// 边界
this.xMin = data.xmin != null ? Number(data.xmin) : this.xMin
this.xMax = data.xmax != null ? Number(data.xmax) : this.xMax
this.yMin = data.ymin != null ? Number(data.ymin) : this.yMin
this.yMax = data.ymax != null ? Number(data.ymax) : this.yMax
// 井点
const list = Array.isArray(data.ysqqXmxxJxxList) ? data.ysqqXmxxJxxList : []
if (list.length) {
this.points = list
.filter(it => it && it.x != null && it.y != null)
.map(it => ({ name: String(it.jh || ''), x: Number(it.x), y: Number(it.y) }))
}
// 线(SEGY)
const segys = Array.isArray(data.ysqqXmxxSegy) ? data.ysqqXmxxSegy : []
console.log(segys, 'segys');
const lines = segys.map((seg, idx) => {
try {
const arr = typeof seg.x === 'string' ? JSON.parse(seg.x) : (Array.isArray(seg.x) ? seg.x : [])
// 若存在有效的 sxh,则按 sxh 升序连线;否则按原始顺序
const enriched = arr
.filter(p => p && p.x != null && p.y != null)
.map(p => ({ sxh: Number(p.sxh), x: Number(p.x), y: Number(p.y) }))
.filter(p => Number.isFinite(p.x) && Number.isFinite(p.y))
const hasSxh = enriched.every(p => Number.isFinite(p.sxh))
const ordered = hasSxh ? enriched.sort((a, b) => a.sxh - b.sxh) : enriched
const pairs = ordered.map(p => [p.x, p.y])
try {
const cloneForLog = pairs.map(it => [it[0], it[1]])
console.log('[ysgc] segy parsed', { index: idx, id: seg && seg.id, points: cloneForLog.length, sample: cloneForLog.slice(0, 5) })
console.log('[ysgc] segy full points', { index: idx, id: seg && seg.id, pointsArray: cloneForLog })
} catch (e) { }
return pairs
} catch (e) {
console.error('[ysgc] segy parse error', { index: idx, id: seg && seg.id, err: e })
return []
}
}).filter(line => line.length > 0)
this.segyLines = lines
try {
console.log('[ysgc] segyLines summary', { lines: this.segyLines.length, lengths: this.segyLines.map(l => l.length) })
} catch (e) { }
},
// 生成图表配置
buildOption () {
// 若未提供边界,则根据数据自动估算
const allXs = []
const allYs = []
for (const p of this.points) { allXs.push(p.x); allYs.push(p.y) }
for (const line of this.segyLines) {
for (const [lx, ly] of line) { allXs.push(lx); allYs.push(ly) }
}
if (allXs.length && (this.xMin == null || this.xMax == null)) {
const padX = Math.max(1, Math.round((Math.max(...allXs) - Math.min(...allXs)) * 0.02))
this.xMin = this.xMin != null ? this.xMin : Math.min(...allXs) - padX
this.xMax = this.xMax != null ? this.xMax : Math.max(...allXs) + padX
}
if (allYs.length && (this.yMin == null || this.yMax == null)) {
const padY = Math.max(1, Math.round((Math.max(...allYs) - Math.min(...allYs)) * 0.02))
this.yMin = this.yMin != null ? this.yMin : Math.min(...allYs) - padY
this.yMax = this.yMax != null ? this.yMax : Math.max(...allYs) + padY
}
const series = []
// 井点散点图
if (this.points && this.points.length) {
series.push({
type: 'scatter',
symbolSize: this.compact ? 8 : 12,
data: this.points.map(p => [p.x, p.y, p.name]),
itemStyle: { color: '#2d72ff', borderColor: '#2d72ff' },
label: this.compact ? { show: false } : { show: true, position: 'top', color: '#333', formatter: params => params.data[2] }
})
}
// 叠加 SEGY 线
for (const line of this.segyLines) {
series.push({
type: 'line',
coordinateSystem: 'cartesian2d',
data: line,
showSymbol: false,
connectNulls: true,
smooth: false,
emphasis: { scale: false },
encode: { x: 0, y: 1 },
lineStyle: { color: '#00aa66', width: 2 },
tooltip: { show: false }
})
// 调试:在每条线之上叠加小点,便于核对路径
series.push({
type: 'scatter',
data: line,
symbolSize: 3,
itemStyle: { color: '#888' },
tooltip: { show: false }
})
}
// 垂直参考线(可选)
if (this.verticalLineX != null && this.yMin != null && this.yMax != null) {
series.push({
type: 'line',
data: [[this.verticalLineX, this.yMin], [this.verticalLineX, this.yMax]],
showSymbol: false,
lineStyle: { color: '#222', width: 2 },
tooltip: { show: false }
})
}
return {
backgroundColor: this.compact ? '#f2f2f2' : '#ffffff',
grid: this.compact ? { top: 6, left: 6, right: 6, bottom: 6, containLabel: false } : { top: 40, left: 50, right: 40, bottom: 50, containLabel: true },
xAxis: this.compact ? { type: 'value', min: this.xMin, max: this.xMax, scale: true, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false }, splitLine: { show: false } } : { type: 'value', min: this.xMin, max: this.xMax, scale: false, axisLine: { show: true }, axisTick: { show: true }, axisLabel: { color: '#666' }, splitLine: { show: true, lineStyle: { color: '#9bb3e7', opacity: 0.6 } } },
yAxis: this.compact ? { type: 'value', min: this.yMin, max: this.yMax, scale: true, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false }, splitLine: { show: false } } : { type: 'value', min: this.yMin, max: this.yMax, scale: false, axisLine: { show: true }, axisTick: { show: true }, axisLabel: { color: '#666' }, splitLine: { show: true, lineStyle: { color: '#9bb3e7', opacity: 0.6 } } },
series,
tooltip: { trigger: 'item' }
}
},
// 渲染或更新图表
renderChart () {
if (!this.chart) return
const option = this.buildOption()
this.chart.setOption(option, true)
}
}
}
</script>
<style lang="scss" scoped>
.ysgc-container {
display: flex;
flex-direction: column;
height: 88vh;
overflow: hidden;
/* 避免出现滚动条 */
}
.toolbar {
display: flex;
align-items: center;
gap: 80px;
padding: 10px 0 8px 10px;
}
.field {
display: flex;
align-items: center;
}
.label {
font-size: 20px;
font-weight: 600;
margin-right: 16px;
}
.input {
width: 180px;
}
.chart {
flex: 1;
min-height: 0;
/* 让 flex 子项在容器内收缩,避免溢出 */
width: 100%;
margin: 0;
/* 取消外边距,防止产生滚动条 */
background: #fff;
border: 1px solid #e0e0e0;
}
</style>
\ No newline at end of file
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