Commit 66a45d27 by zhaopanyu

zpy

parent ec54ff1b
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
"url": "https://gitee.com/y_project/RuoYi-Vue.git" "url": "https://gitee.com/y_project/RuoYi-Vue.git"
}, },
"dependencies": { "dependencies": {
"@jsonforms/core": "^3.6.0",
"@jsonforms/vue": "^3.6.0",
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "0.28.1", "axios": "0.28.1",
"clipboard": "2.0.8", "clipboard": "2.0.8",
...@@ -48,6 +50,9 @@ ...@@ -48,6 +50,9 @@
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"jsonforms-core": "^1.0.11",
"jsonforms-vue": "^1.1.4",
"jsonforms-vue-material": "^1.1.17",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "2.0.2", "quill": "2.0.2",
"screenfull": "5.0.2", "screenfull": "5.0.2",
......
import request from "@/utils/request";
// 简单去重:相同 id 的详情请求在同一时刻仅发起一次
const inFlightDetailMap = new Map();
// 查询会议信息列表
export function listHyjyxx(query) {
return request({
url: "/hyjyxx/hyjyxx/list",
method: "get",
params: query,
});
}
// 查询会议信息详细
export function getHyjyxx(id) {
const key = String(id);
if (inFlightDetailMap.has(key)) {
return inFlightDetailMap.get(key);
}
const p = request({
url: "/hyjyxx/hyjyxx/" + id,
method: "get",
}).finally(() => {
// 请求结束后清理,允许后续新的刷新
inFlightDetailMap.delete(key);
});
inFlightDetailMap.set(key, p);
return p;
}
// 新增会议信息
export function addHyjyxx(data) {
return request({
url: "/hyjyxx/hyjyxx",
method: "post",
data: data,
});
}
// 修改会议信息
export function updateHyjyxx(data) {
return request({
url: "/hyjyxx/hyjyxx",
method: "put",
data: data,
});
}
// 删除会议信息
export function delHyjyxx(id) {
return request({
url: "/hyjyxx/hyjyxx/" + id,
method: "delete",
});
}
//下拉框
export function getHyjyxxAll() {
return request({
url: "/hyjyxxMb/hymb/selectHybm",
method: "get",
});
}
// 开始转录
export function startConvert(id) {
return request({
url: `/hyjyxx/hyjyxx/hyzl/${id}`,
method: "post",
});
}
import request from '@/utils/request'
// 查询会议模板列表
export function listHymb(query) {
return request({
url: '/hyjyxxMb/hymb/list',
method: 'get',
params: query
})
}
// 查询会议模板详细
export function getHymb(id) {
return request({
url: '/hyjyxxMb/hymb/' + id,
method: 'get'
})
}
// 新增会议模板
export function addHymb(data) {
return request({
url: '/hyjyxxMb/hymb',
method: 'post',
data: data
})
}
// 修改会议模板
export function updateHymb(data) {
return request({
url: '/hyjyxxMb/hymb',
method: 'put',
data: data
})
}
// 删除会议模板
export function delHymb(id) {
return request({
url: '/hyjyxxMb/hymb/' + id,
method: 'delete'
})
}
import request from '@/utils/request'
// 查询成果管理列表
export function listWjscqk(query) {
return request({
url: '/yscgWjscqk/wjscqk/list',
method: 'get',
params: query
})
}
// 查询成果管理详细
export function getWjscqk(id) {
return request({
url: '/yscgWjscqk/wjscqk/' + id,
method: 'get'
})
}
// 新增成果管理
export function addWjscqk(data) {
return request({
url: '/yscgWjscqk/wjscqk',
method: 'post',
data: data
})
}
// 修改成果管理
export function updateWjscqk(data) {
return request({
url: '/yscgWjscqk/wjscqk',
method: 'put',
data: data
})
}
// 删除成果管理
export function delWjscqk(id) {
return request({
url: '/yscgWjscqk/wjscqk/' + id,
method: 'delete'
})
}
import request from '@/utils/request'
// 查询资料类型列表
export function listZllx(query) {
return request({
url: '/yscgZllx/zllx/list',
method: 'get',
params: query
})
}
// 查询资料类型详细
export function getZllx(id) {
return request({
url: '/yscgZllx/zllx/' + id,
method: 'get'
})
}
// 新增资料类型
export function addZllx(data) {
return request({
url: '/yscgZllx/zllx',
method: 'post',
data: data
})
}
// 修改资料类型
export function updateZllx(data) {
return request({
url: '/yscgZllx/zllx',
method: 'put',
data: data
})
}
// 删除资料类型
export function delZllx(id) {
return request({
url: '/yscgZllx/zllx/' + id,
method: 'delete'
})
}
import request from "@/utils/request";
// 查询验收前期-项目信息列表
export function listYsqqXmxx(query) {
return request({
url: "/ysqqXmxx/ysqqXmxx/list",
method: "get",
params: query,
});
}
// 查询验收前期-项目信息详细
export function getYsqqXmxx(id) {
return request({
url: "/ysqqXmxx/ysqqXmxx/" + id,
method: "get",
});
}
// 新增验收前期-项目信息
export function addYsqqXmxx(data) {
return request({
url: "/ysqqXmxx/ysqqXmxx",
method: "post",
data: data,
});
}
// 修改验收前期-项目信息
export function updateYsqqXmxx(data) {
return request({
url: "/ysqqXmxx/ysqqXmxx",
method: "put",
data: data,
});
}
// 删除验收前期-项目信息
export function delYsqqXmxx(id) {
return request({
url: "/ysqqXmxx/ysqqXmxx/" + id,
method: "delete",
});
}
//提交按钮
export function startConvert(id) {
return request({
url: "/ysqqXmxx/ysqqXmxx/toDys/" + id,
method: "post",
});
}
//撤回按钮
export function withdraw(id) {
return request({
url: "/ysqqXmxx/ysqqXmxx/toWtj/" + id,
method: "post",
});
}
export function toDht(id) {
return request({
url: "/ysqqXmxx/ysqqXmxx/dht/" + id,
method: "get",
});
}
import request from "@/utils/request";
// 查询验收前期-项目信息-井信息列表
export function listJxx(query) {
return request({
url: "/ysqqXmxxJxx/jxx/list",
method: "get",
params: query,
});
}
// 查询验收前期-项目信息-井信息详细
export function getJxx(id) {
return request({
url: "/ysqqXmxxJxx/jxx/" + id,
method: "get",
});
}
// 新增验收前期-项目信息-井信息
export function addJxx(data) {
return request({
url: "/ysqqXmxxJxx/jxx",
method: "post",
data: data,
});
}
// 修改验收前期-项目信息-井信息
export function updateJxx(data) {
return request({
url: "/ysqqXmxxJxx/jxx",
method: "put",
data: data,
});
}
// 删除验收前期-项目信息-井信息
export function delJxx(id) {
return request({
url: "/ysqqXmxxJxx/jxx/" + id,
method: "delete",
});
}
import request from '@/utils/request'
// 查询segy信息列表
export function listSegy(query) {
return request({
url: '/ysqqXmxxSegy/segy/list',
method: 'get',
params: query
})
}
// 查询segy信息详细
export function getSegy(id) {
return request({
url: '/ysqqXmxxSegy/segy/' + id,
method: 'get'
})
}
// 新增segy信息
export function addSegy(data) {
return request({
url: '/ysqqXmxxSegy/segy',
method: 'post',
data: data
})
}
// 修改segy信息
export function updateSegy(data) {
return request({
url: '/ysqqXmxxSegy/segy',
method: 'put',
data: data
})
}
// 删除segy信息
export function delSegy(id) {
return request({
url: '/ysqqXmxxSegy/segy/' + id,
method: 'delete'
})
}
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#d81e06" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#d81e06" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#d81e06" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#d81e06" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#f4ea2a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#f4ea2a" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#f4ea2a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#f4ea2a" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#afcd50" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#afcd50" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#afcd50" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#afcd50" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#e0620d" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#e0620d" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#e0620d" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#e0620d" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#1afa29" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#1afa29" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#1afa29" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#1afa29" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#1296db" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#1296db" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#1296db" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#1296db" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#13227a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#13227a" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#13227a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#13227a" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#d4237a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#d4237a" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#d4237a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#d4237a" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#f3ca7e" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#f3ca7e" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#f3ca7e" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#f3ca7e" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#e8989a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#e8989a" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#e8989a" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#e8989a" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#112079" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#112079" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#112079" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#112079" p-id="4656"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#88147f" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#88147f" p-id="4656"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758098836708" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4654" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M640.766712 362.494964c0-71.386864-58.078767-129.464607-129.464607-129.464607-71.386864 0-129.464607 58.077743-129.464607 129.464607s58.077743 129.464607 129.464607 129.464607C582.687946 491.959571 640.766712 433.881828 640.766712 362.494964z" fill="#88147f" p-id="4655"></path><path d="M829.65164 195.676611C744.998635 111.023606 632.445186 64.402799 512.727571 64.402799c-119.718639 0-232.272088 46.62183-316.925093 131.274836C111.148449 280.33064 64.527642 392.884089 64.527642 512.602727c0 119.717615 46.62183 232.272088 131.274836 316.925093 84.654029 84.655052 197.207477 131.275859 316.925093 131.275859 119.717615 0 232.272088-46.620807 316.925093-131.275859 84.655052-84.653005 131.275859-197.207477 131.275859-316.925093C960.927499 392.884089 914.306692 280.33064 829.65164 195.676611zM732.97581 764.003478c-11.04966 0-20.008706-8.959046-20.008706-20.008706 0-111.199615-90.466408-201.666022-201.664999-201.666022S309.637106 632.795157 309.637106 743.994772c0 11.04966-8.958022 20.008706-20.008706 20.008706-11.050684 0-20.008706-8.959046-20.008706-20.008706 0-107.011222 69.916373-197.986213 166.462243-229.684146-55.807027-27.76332-94.262874-85.36932-94.262874-151.816684 0-93.452415 76.029604-169.483042 169.483042-169.483042 93.452415 0 169.483042 76.029604 169.483042 169.483042 0 66.446341-38.455847 124.052341-94.262874 151.816684 96.54587 31.697933 166.462243 122.6719 166.462243 229.684146C752.984516 755.044432 744.025471 764.003478 732.97581 764.003478z" fill="#88147f" p-id="4656"></path></svg>
\ No newline at end of file
<template> <template>
<div class="upload-file"> <div class="upload-file">
<el-upload <el-upload multiple :action="uploadFileUrl" :before-upload="handleBeforeUpload" :file-list="fileList" :data="data"
multiple :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed" :on-success="handleUploadSuccess"
:action="uploadFileUrl" :show-file-list="false" :headers="headers" class="upload-file-uploader" ref="fileUpload" v-if="!disabled">
:before-upload="handleBeforeUpload"
:file-list="fileList"
:data="data"
:limit="limit"
:on-error="handleUploadError"
:on-exceed="handleExceed"
:on-success="handleUploadSuccess"
:show-file-list="false"
:headers="headers"
class="upload-file-uploader"
ref="fileUpload"
v-if="!disabled"
>
<!-- 上传按钮 --> <!-- 上传按钮 -->
<el-button size="mini" type="primary">选取文件</el-button> <el-button size="mini" type="primary">选取文件</el-button>
<!-- 上传提示 --> <!-- 上传提示 -->
...@@ -28,7 +15,8 @@ ...@@ -28,7 +15,8 @@
</el-upload> </el-upload>
<!-- 文件列表 --> <!-- 文件列表 -->
<transition-group ref="uploadFileList" class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> <transition-group ref="uploadFileList" class="upload-file-list el-upload-list el-upload-list--text"
name="el-fade-in-linear" tag="ul">
<li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"> <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank"> <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span> <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
...@@ -67,7 +55,7 @@ export default { ...@@ -67,7 +55,7 @@ export default {
// 大小限制(MB) // 大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
default: 5 default: 100
}, },
// 文件类型, 例如['png', 'jpg', 'jpeg'] // 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: { fileType: {
...@@ -241,21 +229,25 @@ export default { ...@@ -241,21 +229,25 @@ export default {
opacity: 0.5; opacity: 0.5;
background: #c8ebfb; background: #c8ebfb;
} }
.upload-file-uploader { .upload-file-uploader {
margin-bottom: 5px; margin-bottom: 5px;
} }
.upload-file-list .el-upload-list__item { .upload-file-list .el-upload-list__item {
border: 1px solid #e4e7ed; border: 1px solid #e4e7ed;
line-height: 2; line-height: 2;
margin-bottom: 10px; margin-bottom: 10px;
position: relative; position: relative;
} }
.upload-file-list .ele-upload-list__item-content { .upload-file-list .ele-upload-list__item-content {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: inherit; color: inherit;
} }
.ele-upload-list__item-content-action .el-link { .ele-upload-list__item-content-action .el-link {
margin-right: 10px; margin-right: 10px;
} }
......
...@@ -82,6 +82,9 @@ DictData.install(); ...@@ -82,6 +82,9 @@ DictData.install();
* Currently MockJs will be used in the production environment, * Currently MockJs will be used in the production environment,
* please remove it before going online! ! ! * please remove it before going online! ! !
*/ */
// 修改elementUI默认样式-- 关于对话框中,当点击对话框外部区域或者键入【esc】是退出对话框的问题
Element.Dialog.props.closeOnClickModal = false;
Element.Dialog.props.closeOnPressEscape = false;
Vue.use(Element, { Vue.use(Element, {
size: Cookies.get("size") || "medium", // set element-ui default size size: Cookies.get("size") || "medium", // set element-ui default size
......
import Vue from 'vue' import Vue from "vue";
import Router from 'vue-router' import Router from "vue-router";
Vue.use(Router) Vue.use(Router);
/* Layout */ /* Layout */
import Layout from '@/layout' import Layout from "@/layout";
/** /**
* Note: 路由配置项 * Note: 路由配置项
...@@ -31,153 +31,216 @@ import Layout from '@/layout' ...@@ -31,153 +31,216 @@ import Layout from '@/layout'
// 公共路由 // 公共路由
export const constantRoutes = [ export const constantRoutes = [
{ {
path: '/redirect', path: "/redirect",
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: '/redirect/:path(.*)', path: "/redirect/:path(.*)",
component: () => import('@/views/redirect') component: () => import("@/views/redirect"),
} },
] ],
}, },
{ {
path: '/login', path: "/login",
component: () => import('@/views/login'), component: () => import("@/views/login"),
hidden: true hidden: true,
}, },
{ {
path: '/register', path: "/register",
component: () => import('@/views/register'), component: () => import("@/views/register"),
hidden: true hidden: true,
}, },
{ {
path: '/404', path: "/404",
component: () => import('@/views/error/404'), component: () => import("@/views/error/404"),
hidden: true hidden: true,
}, },
{ {
path: '/401', path: "/401",
component: () => import('@/views/error/401'), component: () => import("@/views/error/401"),
hidden: true hidden: true,
}, },
{ {
path: '', path: "",
component: Layout, component: Layout,
redirect: 'index', redirect: "index",
children: [ children: [
{ {
path: 'index', path: "index",
component: () => import('@/views/index'), component: () => import("@/views/index"),
name: 'Index', name: "Index",
meta: { title: '首页', icon: 'dashboard', affix: true } meta: { title: "首页", icon: "dashboard", affix: true },
} },
] ],
}, },
{ {
path: '/user', path: "/user",
component: Layout, component: Layout,
hidden: true, hidden: true,
redirect: 'noredirect', redirect: "noredirect",
children: [ children: [
{ {
path: 'profile', path: "profile",
component: () => import('@/views/system/user/profile/index'), component: () => import("@/views/system/user/profile/index"),
name: 'Profile', name: "Profile",
meta: { title: '个人中心', icon: 'user' } meta: { title: "个人中心", icon: "user" },
} },
] ],
} },
] {
path: "/hyjyxx/hyjyxx",
component: Layout,
hidden: true,
children: [
{
path: "detail/:id(\\d+)",
component: () => import("@/views/hyjyxx/hyjyxx/detail"),
name: "HyjyxxDetail",
meta: { title: "会议详情", activeMenu: "/hyjyxx/hyjyxx" },
},
],
},
{
path: "/ysqqXmxxJxx/jxx",
component: Layout,
hidden: true,
children: [
{
path: "index",
component: () => import("@/views/ysqqXmxxJxx/jxx/index"),
name: "JxxIndex",
meta: { title: "井信息管理", activeMenu: "/ysqqXmxx/ysqqXmxx" },
},
],
},
{
path: "/ysqqXmxxSegy/segy",
component: Layout,
hidden: true,
children: [
{
path: "index",
component: () => import("@/views/ysqqXmxxSegy/segy/index"),
name: "SegyIndex",
meta: { title: "segy信息管理", activeMenu: "/ysqqXmxx/ysqqXmxx" },
},
],
},
{
path: "/ysqqXmxx/ysgc",
component: Layout,
hidden: true,
children: [
{
path: "index",
component: () => import("@/views/ysqqXmxx/ysgc/index"),
name: "YsgcIndex",
meta: { title: "导航图", activeMenu: "/ysqqXmxx/ysqqXmxx" },
},
{
path: "index2",
component: () => import("@/views/ysqqXmxx/ysgc/index2"),
name: "YsgcIndex2",
hidden: false,
meta: {
title: "导航图2",
breadcrumb: true,
activeMenu: "/ysqqXmxx/ysqqXmxx",
},
},
],
},
];
// 动态路由,基于用户权限动态去加载 // 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [ export const dynamicRoutes = [
{ {
path: '/system/user-auth', path: "/system/user-auth",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['system:user:edit'], permissions: ["system:user:edit"],
children: [ children: [
{ {
path: 'role/:userId(\\d+)', path: "role/:userId(\\d+)",
component: () => import('@/views/system/user/authRole'), component: () => import("@/views/system/user/authRole"),
name: 'AuthRole', name: "AuthRole",
meta: { title: '分配角色', activeMenu: '/system/user' } meta: { title: "分配角色", activeMenu: "/system/user" },
} },
] ],
}, },
{ {
path: '/system/role-auth', path: "/system/role-auth",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['system:role:edit'], permissions: ["system:role:edit"],
children: [ children: [
{ {
path: 'user/:roleId(\\d+)', path: "user/:roleId(\\d+)",
component: () => import('@/views/system/role/authUser'), component: () => import("@/views/system/role/authUser"),
name: 'AuthUser', name: "AuthUser",
meta: { title: '分配用户', activeMenu: '/system/role' } meta: { title: "分配用户", activeMenu: "/system/role" },
} },
] ],
}, },
{ {
path: '/system/dict-data', path: "/system/dict-data",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['system:dict:list'], permissions: ["system:dict:list"],
children: [ children: [
{ {
path: 'index/:dictId(\\d+)', path: "index/:dictId(\\d+)",
component: () => import('@/views/system/dict/data'), component: () => import("@/views/system/dict/data"),
name: 'Data', name: "Data",
meta: { title: '字典数据', activeMenu: '/system/dict' } meta: { title: "字典数据", activeMenu: "/system/dict" },
} },
] ],
}, },
{ {
path: '/monitor/job-log', path: "/monitor/job-log",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['monitor:job:list'], permissions: ["monitor:job:list"],
children: [ children: [
{ {
path: 'index/:jobId(\\d+)', path: "index/:jobId(\\d+)",
component: () => import('@/views/monitor/job/log'), component: () => import("@/views/monitor/job/log"),
name: 'JobLog', name: "JobLog",
meta: { title: '调度日志', activeMenu: '/monitor/job' } meta: { title: "调度日志", activeMenu: "/monitor/job" },
} },
] ],
}, },
{ {
path: '/tool/gen-edit', path: "/tool/gen-edit",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['tool:gen:edit'], permissions: ["tool:gen:edit"],
children: [ children: [
{ {
path: 'index/:tableId(\\d+)', path: "index/:tableId(\\d+)",
component: () => import('@/views/tool/gen/editTable'), component: () => import("@/views/tool/gen/editTable"),
name: 'GenEdit', name: "GenEdit",
meta: { title: '修改生成配置', activeMenu: '/tool/gen' } meta: { title: "修改生成配置", activeMenu: "/tool/gen" },
} },
] ],
} },
] ];
// 防止连续点击多次路由报错 // 防止连续点击多次路由报错
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);
} };
export default new Router({ export default new Router({
mode: 'history', // 去掉url中的# mode: "history", // 去掉url中的#
scrollBehavior: () => ({ y: 0 }), scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes routes: constantRoutes,
}) });
import axios from 'axios' import axios from "axios";
import { Notification, MessageBox, Message, Loading } from 'element-ui' import { Notification, MessageBox, Message, Loading } from "element-ui";
import store from '@/store' import store from "@/store";
import { getToken } from '@/utils/auth' import { getToken } from "@/utils/auth";
import errorCode from '@/utils/errorCode' import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi" import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from '@/plugins/cache' import cache from "@/plugins/cache";
import { saveAs } from 'file-saver' import { saveAs } from "file-saver";
let downloadLoadingInstance let downloadLoadingInstance;
// 是否显示重新登录 // 是否显示重新登录
export let isRelogin = { show: false } export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例 // 创建axios实例
const service = axios.create({ const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分 // axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API, baseURL: process.env.VUE_APP_BASE_API,
// 超时 // 超时
timeout: 10000 timeout: 300000,
}) });
// request拦截器 // request拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(
// 是否需要设置 token (config) => {
const isToken = (config.headers || {}).isToken === false // 是否需要设置 token
// 是否需要防止数据重复提交 const isToken = (config.headers || {}).isToken === false;
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false // 是否需要防止数据重复提交
if (getToken() && !isToken) { const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 if (getToken() && !isToken) {
} config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params)
url = url.slice(0, -1)
config.params = {}
config.url = url
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
} }
const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小 // get请求映射params参数
const limitSize = 5 * 1024 * 1024 // 限制存放数据5M if (config.method === "get" && config.params) {
if (requestSize >= limitSize) { let url = config.url + "?" + tansParams(config.params);
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。') url = url.slice(0, -1);
return config config.params = {};
config.url = url;
} }
const sessionObj = cache.session.getJSON('sessionObj') if (
if (sessionObj === undefined || sessionObj === null || sessionObj === '') { !isRepeatSubmit &&
cache.session.setJSON('sessionObj', requestObj) (config.method === "post" || config.method === "put")
} else { ) {
const s_url = sessionObj.url // 请求地址 const requestObj = {
const s_data = sessionObj.data // 请求数据 url: config.url,
const s_time = sessionObj.time // 请求时间 data:
const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交 typeof config.data === "object"
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { ? JSON.stringify(config.data)
const message = '数据正在处理,请勿重复提交' : config.data,
console.warn(`[${s_url}]: ` + message) time: new Date().getTime(),
return Promise.reject(new Error(message)) };
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
if (requestSize >= limitSize) {
console.warn(
`[${config.url}]: ` +
"请求数据大小超出允许的5M限制,无法进行防重复提交验证。"
);
return config;
}
const sessionObj = cache.session.getJSON("sessionObj");
if (
sessionObj === undefined ||
sessionObj === null ||
sessionObj === ""
) {
cache.session.setJSON("sessionObj", requestObj);
} else { } else {
cache.session.setJSON('sessionObj', requestObj) const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (
s_data === requestObj.data &&
requestObj.time - s_time < interval &&
s_url === requestObj.url
) {
const message = "数据正在处理,请勿重复提交";
console.warn(`[${s_url}]: ` + message);
return Promise.reject(new Error(message));
} else {
cache.session.setJSON("sessionObj", requestObj);
}
} }
} }
return config;
},
(error) => {
console.log(error);
Promise.reject(error);
} }
return config );
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器 // 响应拦截器
service.interceptors.response.use(res => { service.interceptors.response.use(
(res) => {
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200 const code = res.data.code || 200;
// 获取错误信息 // 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default'] const msg = errorCode[code] || res.data.msg || errorCode["default"];
// 二进制数据则直接返回 // 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { if (
return res.data res.request.responseType === "blob" ||
res.request.responseType === "arraybuffer"
) {
return res.data;
} }
if (code === 401) { if (code === 401) {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { MessageBox.confirm(
isRelogin.show = false "登录状态已过期,您可以继续留在该页面,或者重新登录",
store.dispatch('LogOut').then(() => { "系统提示",
location.href = '/index' {
confirmButtonText: "重新登录",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
isRelogin.show = false;
store.dispatch("LogOut").then(() => {
location.href = "/index";
});
}) })
}).catch(() => { .catch(() => {
isRelogin.show = false isRelogin.show = false;
}) });
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
} else if (code === 500) { } else if (code === 500) {
Message({ message: msg, type: 'error' }) Message({ message: msg, type: "error" });
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg));
} else if (code === 601) { } else if (code === 601) {
Message({ message: msg, type: 'warning' }) Message({ message: msg, type: "warning" });
return Promise.reject('error') return Promise.reject("error");
} else if (code !== 200) { } else if (code !== 200) {
Notification.error({ title: msg }) Notification.error({ title: msg });
return Promise.reject('error') return Promise.reject("error");
} else { } else {
return res.data return res.data;
} }
}, },
error => { (error) => {
console.log('err' + error) console.log("err" + error);
let { message } = error let { message } = error;
if (message == "Network Error") { if (message == "Network Error") {
message = "后端接口连接异常" message = "后端接口连接异常";
} else if (message.includes("timeout")) { } else if (message.includes("timeout")) {
message = "系统接口请求超时" message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常" message = "系统接口" + message.substr(message.length - 3) + "异常";
} }
Message({ message: message, type: 'error', duration: 5 * 1000 }) Message({ message: message, type: "error", duration: 5 * 1000 });
return Promise.reject(error) return Promise.reject(error);
} }
) );
// 通用下载方法 // 通用下载方法
export function download(url, params, filename, config) { export function download(url, params, filename, config) {
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) downloadLoadingInstance = Loading.service({
return service.post(url, params, { text: "正在下载数据,请稍候",
transformRequest: [(params) => { return tansParams(params) }], spinner: "el-icon-loading",
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, background: "rgba(0, 0, 0, 0.7)",
responseType: 'blob', });
...config return service
}).then(async (data) => { .post(url, params, {
const isBlob = blobValidate(data) transformRequest: [
if (isBlob) { (params) => {
const blob = new Blob([data]) return tansParams(params);
saveAs(blob, filename) },
} else { ],
const resText = await data.text() headers: { "Content-Type": "application/x-www-form-urlencoded" },
const rspObj = JSON.parse(resText) responseType: "blob",
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] ...config,
Message.error(errMsg) })
} .then(async (data) => {
downloadLoadingInstance.close() const isBlob = blobValidate(data);
}).catch((r) => { if (isBlob) {
console.error(r) const blob = new Blob([data]);
Message.error('下载文件出现错误,请联系管理员!') saveAs(blob, filename);
downloadLoadingInstance.close() } else {
}) const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg =
errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
Message.error(errMsg);
}
downloadLoadingInstance.close();
})
.catch((r) => {
console.error(r);
Message.error("下载文件出现错误,请联系管理员!");
downloadLoadingInstance.close();
});
} }
export default service export default service;
<template>
<div class="app-container">
<el-card shadow="never" v-loading="loading">
<div slot="header" class="clearfix">
<span>{{ detail.ypwjName || '会议详情' }}</span>
<el-button style="float: right; padding: 3px 0" type="text" @click="$router.back()">返回</el-button>
</div>
<el-row :gutter="20">
<el-col :span="12">
<el-card shadow="never"
body-style="padding: 12px; height: calc(100vh - 220px); overflow: hidden; display: flex; flex-direction: column;background-color:#f6f8fa ">
<div style="font-weight: 600; margin-bottom: 8px;">转录文本</div>
<div class="transcript-area flex-scroll" style="margin-left: 10px;">
<div style="padding-bottom: 10px;">
<div v-for="(segment, index) in transcriptList" :key="index" placement="top">
<div class="seg-header">
<span style="color: #000000; margin-right: 6px;">{{ segment.speaker }}</span>
<span style="color: #C0C4CC;">{{ segment.timestamp || segment.time }}</span>
</div>
<div class="seg-body">
<el-avatar :class="getAvatarClass(getSpeakerIndex(segment.speaker))">
<img :src="getSpeakerIcon(getSpeakerIndex(segment.speaker))"
class="avatar-img" alt="avatar" />
</el-avatar>
<div :class="['seg-bubble', { 'is-active': activeIndex === index }]">
<div :class="['seg-content', { 'is-active': activeIndex === index }]"
style="border-color: #ffffff;" @click="onSegmentClick(index, segment)"
title="点击跳转到该时间播放">{{
segment.content
|| segment.text }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="audio-footer">
<audio ref="audio" :src="getAudioUrl(detail.ypwj)" controls />
</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never" body-style="padding: 12px; height: calc(100vh - 220px); overflow: auto;">
<div
style="display:flex; align-items:center; justify-content: space-between; margin-bottom: 12px;">
<div style="font-weight: 600;">纪要</div>
</div>
<div class="summary" v-html="detail.hyjy"></div>
</el-card>
</el-col>
</el-row>
</el-card>
</div>
</template>
<script>
import { getHyjyxx } from '@/api/hyjyxx/hyjyxx'
import icon1 from '@/assets/images/个人1.svg'
import icon2 from '@/assets/images/个人2.svg'
import icon3 from '@/assets/images/个人3.svg'
import icon4 from '@/assets/images/个人4.svg'
import icon5 from '@/assets/images/个人5.svg'
import icon6 from '@/assets/images/个人6.svg'
import icon7 from '@/assets/images/个人7.svg'
import icon8 from '@/assets/images/个人8.svg'
import icon9 from '@/assets/images/个人9.svg'
import icon10 from '@/assets/images/个人10.svg'
import icon11 from '@/assets/images/个人11.svg'
export default {
name: 'HyjyxxDetail',
data() {
return {
id: null,
detail: {},
transcriptList: [],
activeIndex: null,
_loadedId: null,
_inFlightId: null,
_loadTimer: null,
loading: false,
speakerIcons: [icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, icon9, icon10, icon11]
}
},
created() {
// 不在 created/activated/watch 里多点触发,统一由路由钩子调用
},
activated() {
// 组件从 keep-alive 恢复时,若路由参数变化,需刷新
const newId = this.$route && this.$route.params && this.$route.params.id
if (newId && newId !== this.id) {
this.id = newId
this.load()
}
},
watch: {
'$route.params.id'(val) {
if (val && val !== this.id) {
this.id = val
this.load()
}
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
vm.id = to.params.id
vm.load()
})
},
beforeRouteUpdate(to, from, next) {
this.id = to.params.id
this.load()
next()
},
methods: {
// 去掉去抖函数,改为仅从路由钩子触发,天然 1 次/次导航
onSegmentClick(index, segment) {
this.activeIndex = index
const t = segment && (segment.timestamp || segment.time)
this.seekTo(t)
},
getSpeakerIndex(speaker) {
// 解析“发言人X”中的数字X;若未解析到则使用哈希映射到1-11
const m = String(speaker || '').match(/(\d{1,2})/)
if (m) {
const idx = parseInt(m[1], 10)
if (idx >= 1 && idx <= 11) return idx
}
// 简单哈希到 1..11
const s = String(speaker || '')
let hash = 0
for (let i = 0; i < s.length; i++) hash = (hash * 31 + s.charCodeAt(i)) >>> 0
return (hash % 11) + 1
},
getAvatarClass(idx) {
return `avatar-color-${idx}`
},
getSpeakerIcon(idx) {
const n = Number(idx)
if (!n || n < 1) return this.speakerIcons[0]
if (n > 11) return this.speakerIcons[10]
return this.speakerIcons[n - 1]
},
getAvatarText(speaker) {
// 头像内显示发言人序号或首字
const m = String(speaker || '').match(/(\d{1,2})/)
if (m) return m[1]
const s = String(speaker || '').trim()
return s ? s[0] : '发'
},
normalizeText(str) {
if (str == null) return ''
return String(str)
.replace(/\r/g, '')
.replace(/\s+/g, ' ')
.trim()
},
getAudioUrl(path) {
if (!path) return ''
// 绝对地址直接返回,相对地址补全网关前缀
if (/^https?:\/\//i.test(path)) return path
const base = process.env.VUE_APP_BASE_API || ''
return `${base}${path}`
},
load() {
if (!this.id) return
if (this._loadedId === this.id) {
// 避免重复加载导致的展示重复
return
}
// 先清空旧数据,避免短时显示上一条内容
this.detail = {}
this.transcriptList = []
this.activeIndex = null
const currentId = this.id
if (this._inFlightId === currentId) {
// 已有同一个ID的请求在进行,直接跳过
return
}
// 标记进行中的请求,后到的旧响应将被忽略
this._inFlightId = currentId
this.loading = true
getHyjyxx(currentId).then(res => {
if (this._inFlightId !== currentId) return
this.detail = res.data || {}
// 优先使用后端标准字段 detail.ywBzh(数组:{ speaker, timestamp, content })
let bzh = this.detail.ywBzh
console.log('ywBzh (raw):', bzh)
// 兼容后端把数组以字符串返回的情况
if (typeof bzh === 'string') {
try {
const parsed = JSON.parse(bzh)
if (Array.isArray(parsed)) bzh = parsed
} catch (e) {
console.warn('Failed to parse ywBzh string:', e)
}
}
if (Array.isArray(bzh)) {
// 不做去重与规范化,按后端返回原样展示
this.transcriptList = bzh
this._loadedId = currentId
} else {
// 不再使用 detail.yw 的回退解析,避免展示超出接口返回的内容
this.transcriptList = []
this._loadedId = currentId
}
}).finally(() => {
if (this._inFlightId === currentId) {
this.loading = false
this._inFlightId = null
}
})
},
parseTranscript(raw) {
if (!raw) return []
// 简单解析:支持形如 “发言人A 00:00:25:内容...” 的行
const lines = String(raw).split(/\n+/)
return lines.filter(Boolean).map(line => {
const m = line.match(/^(.*?)(\d{2}:\d{2}:\d{2})[::]\s*(.*)$/)
if (m) {
return { speaker: m[1].trim() || '发言人', time: m[2], text: m[3] }
}
return { speaker: '发言', time: '', text: line }
})
},
/**
* 将时间表达(如 "01:02:03"、"12:34"、"90")解析为秒
*/
parseTimeToSeconds(timeLike) {
if (timeLike == null || timeLike === '') return null
const s = String(timeLike).trim()
// 纯数字视为秒
if (/^\d+(?:\.\d+)?$/.test(s)) return parseFloat(s)
// 支持 HH:MM:SS 或 MM:SS
const parts = s.split(':').map(n => parseFloat(n))
if (parts.some(isNaN)) return null
let seconds = 0
if (parts.length === 3) {
seconds = parts[0] * 3600 + parts[1] * 60 + parts[2]
} else if (parts.length === 2) {
seconds = parts[0] * 60 + parts[1]
} else if (parts.length === 1) {
seconds = parts[0]
} else {
return null
}
return seconds
},
/**
* 跳转到指定时间并播放
*/
seekTo(timeLike) {
const audio = this.$refs.audio
if (!audio) return
const seconds = this.parseTimeToSeconds(timeLike)
if (seconds == null || !isFinite(seconds)) return
try {
// 边界保护
const target = Math.max(0, seconds)
audio.currentTime = target
audio.play && audio.play()
} catch (e) {
// 忽略设置失败
}
},
playAudio() {
const el = this.$refs.audio
if (el) el.play()
},
reload() {
this.load()
}
}
}
</script>
<style scoped>
/* 全局字体(该组件内) */
.app-container {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC",
"Source Han Sans SC", sans-serif;
}
::v-deep .el-timeline-item {
padding-bottom: 10px !important;
}
.summary {
white-space: pre-wrap;
line-height: 1.8;
}
/* 头部(发言人 + 时间)同一行展示 */
.seg-header {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: nowrap;
white-space: nowrap;
margin-bottom: 8px;
}
/* 下方头像 + 内容布局 */
.seg-body {
display: flex;
align-items: flex-start;
}
.seg-content {
margin-left: 10px;
cursor: pointer;
}
.seg-content.is-active {
color: #409EFF;
/* Element 主色 */
}
.avatar-text {
font-size: 12px;
}
/* 替换为SVG图标时,确保图标适配头像大小 */
.seg-body .el-avatar {
display: inline-flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: transparent;
width: 35px;
height: 35px;
min-width: 35px;
min-height: 35px;
}
.avatar-img {
width: 35px;
height: 35px;
object-fit: contain;
display: block;
}
/* 文本气泡容器:与头像分离的一块背景 */
.seg-bubble {
background-color: #ffffff;
border: 1px solid #ebeef5;
border-radius: 8px;
padding: 8px 10px;
margin-left: 10px;
flex: 1 1 auto;
}
.seg-bubble.is-active {
border-color: #409EFF;
background-color: #f0f8ff;
}
/* 11种可区分的颜色,按发言人编号映射 */
.avatar-color-1 {
color: #14a1ff;
}
.avatar-color-2 {
color: #52c41a;
}
.avatar-color-3 {
color: #fa8c16;
}
.avatar-color-4 {
color: #ff4d4f;
}
.avatar-color-5 {
color: #909399;
}
.avatar-color-6 {
color: #00B8A9;
}
.avatar-color-7 {
color: #8E54E9;
}
.avatar-color-8 {
color: #2D9CDB;
}
.avatar-color-9 {
color: #27AE60;
}
.avatar-color-10 {
color: #EB5757;
}
.avatar-color-11 {
color: #F2994A;
}
/* 左侧:上方可滚动,下方固定播放器 */
.flex-scroll {
flex: 1 1 auto;
overflow: auto;
}
.audio-footer {
flex: 0 0 auto;
padding-top: 12px;
border-top: 1px solid #ebeef5;
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.04);
}
.audio-footer audio {
width: 100%;
}
</style>
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="96px">
<!-- <el-form-item label="主键" prop="id">
<el-input
v-model="queryParams.id"
placeholder="请输入主键"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<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="hymc">
<el-input v-model="queryParams.hymc" placeholder="请输入会议名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="解析状态" prop="jxzt">
<el-input v-model="queryParams.jxzt" placeholder="请输入解析状态" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="解析完成时间" prop="jxwcsj">
<el-date-picker clearable v-model="queryParams.jxwcsj" type="datetime" format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择解析完成时间">
</el-date-picker>
</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 label="备用3" prop="ext3">
<el-input v-model="queryParams.ext3" placeholder="请输入备用3" 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-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['hyjyxx:hyjyxx:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['hyjyxx:hyjyxx:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['hyjyxx:hyjyxx:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['hyjyxx:hyjyxx:export']">导出</el-button>
</el-form-item>
</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="hyjyxxList" @selection-change="handleSelectionChange">
<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="hymc" min-width="130" show-overflow-tooltip>
<template slot-scope="scope">
<el-link type="primary" @click="goDetail(scope.row)">{{ scope.row.hymc }}</el-link>
</template>
</el-table-column>
<el-table-column label="音频文件名称" align="center" prop="ypwjName" min-width="140" show-overflow-tooltip />
<el-table-column label="会议模版名称" align="center" prop="mbmc" min-width="140" show-overflow-tooltip />
<el-table-column label="会议开始时间" align="center" prop="jxwcsj" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.jxwcsj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="解析状态" align="center" prop="jxzt" min-width="90" show-overflow-tooltip />
<!-- <el-table-column label="原文" align="center" prop="yw" min-width="140" show-overflow-tooltip />
<el-table-column label="会议纪要" align="center" prop="hyjy" min-width="140" show-overflow-tooltip />
<el-table-column label="解析完成时间" align="center" prop="jxwcsj" min-width="100" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ parseTime(scope.row.jxwcsj, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column> -->
<!-- <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="120" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['hyjyxx:hyjyxx:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['hyjyxx:hyjyxx:remove']">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-bottom-right" @click="handleKszr(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" />
<!-- 添加或修改会议信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="98px">
<!-- <el-form-item label="项目id" prop="xmid">
<el-input v-model="form.xmid" placeholder="请输入项目id" />
</el-form-item> -->
<el-form-item label="会议名称" prop="hymc">
<el-input v-model="form.hymc" placeholder="请输入内容" />
</el-form-item>
<!-- <el-form-item label="解析状态" prop="jxzt">
<el-input v-model="form.jxzt" placeholder="请输入解析状态" />
</el-form-item> -->
<el-form-item label="会议音频上传" prop="ypwj">
<el-upload drag :headers="upload.headers" :action="upload.url" :limit="1" :auto-upload="true"
accept=".mp3,.wav,.wma,.aac,.3gp,.m4a" :on-success="handleAudioSuccess" :on-error="handleAudioError"
:file-list="audioFileList">
<i class="el-icon-upload"></i>
<div class="el-upload__text">点击或拖动到此区域</div>
<div class="el-upload__tip" slot="tip">格式支持: mp3,wav,wma,aac,3gp,m4a</div>
</el-upload>
<!-- <el-input v-if="form.ypwj" v-model="form.ypwj" placeholder="文件上传后返回的路径" readonly style="margin-top: 8px;" /> -->
</el-form-item>
<el-form-item label="会议模版" prop="mbmc">
<el-select v-model="form.mbmc" placeholder="请选择会议模版" filterable style="width: 100%"
@change="handleHymbChange">
<el-option v-for="item in hymbOptions" :key="item.id || item.value || item.mbmc"
:label="item.mbmc || item.label" :value="item.id || item.value" />
</el-select>
</el-form-item>
<!-- <el-form-item label="会议纪要" prop="hyjy">
<el-input v-model="form.hyjy" type="textarea" placeholder="请输入内容" />
</el-form-item> -->
<el-form-item label="会议开始时间" prop="jxwcsj">
<el-date-picker clearable v-model="form.jxwcsj" type="datetime" format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择会议开始时间" style="width: 100%;">
</el-date-picker>
</el-form-item>
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listHyjyxx, getHyjyxx, delHyjyxx, addHyjyxx, updateHyjyxx, getHyjyxxAll, startConvert } from "@/api/hyjyxx/hyjyxx"
import { getToken } from "@/utils/auth"
export default {
name: "Hyjyxx",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 会议信息表格数据
hyjyxxList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 模版下拉选项
hymbOptions: [],
// 音频上传配置
upload: {
headers: { Authorization: "Bearer " + getToken() },
url: process.env.VUE_APP_BASE_API + "/common/upload"
},
// el-upload 文件列表(用于编辑时回显)
audioFileList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
id: null,
xmid: null,
hymc: null,
jxzt: null,
ypwj: null,
yw: null,
hyjy: null,
jxwcsj: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null
},
// 表单参数
form: {},
// 表单校验
rules: {
}
}
},
created() {
this.getList()
// 获取会议模版下拉
getHyjyxxAll().then(res => {
// 兼容不同返回结构,优先 data
this.hymbOptions = res.data || res.rows || []
})
},
methods: {
/** 查询会议信息列表 */
getList() {
this.loading = true
const qp = { ...this.queryParams }
// 转换为字符串再请求,避免后端无法解析 Date
if (qp.jxwcsj instanceof Date) {
qp.jxwcsj = this.parseTime(qp.jxwcsj, '{y}-{m}-{d} {h}:{i}:{s}')
}
listHyjyxx(qp).then(response => {
this.hyjyxxList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
xmid: null,
hymc: null,
jxzt: null,
ypwj: null,
ypwjName: null,
yw: null,
hyjy: null,
jxwcsj: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
mbid: null,
mbmc: null,
ext1: null,
ext2: null,
ext3: null
}
this.resetForm("form")
this.audioFileList = []
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加会议信息"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getHyjyxx(id).then(response => {
this.form = response.data
// 兼容后端仅返回 mbid 的情况
if (this.form && this.form.mbid && !this.form.mbmc) {
const found = (this.hymbOptions || []).find(o => (o.id || o.value) === this.form.mbid)
this.form.mbmc = found ? (found.mbmc || found.label) : this.form.mbmc
}
// 回显已上传的音频文件
this.audioFileList = []
if (this.form && this.form.ypwj) {
this.audioFileList = [{
name: this.form.ypwjName || this.getFileName(this.form.ypwj),
url: this.getAudioUrl(this.form.ypwj)
}]
}
this.open = true
this.title = "修改会议信息"
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
const payload = { ...this.form }
if (payload.jxwcsj instanceof Date) {
payload.jxwcsj = this.parseTime(payload.jxwcsj, '{y}-{m}-{d} {h}:{i}:{s}')
}
if (this.form.id != null) {
updateHyjyxx(payload).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addHyjyxx(payload).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
handleHymbChange(value) {
const found = (this.hymbOptions || []).find(o => (o.id || o.value) === value)
this.form.mbmc = found ? (found.mbmc || found.label) : null
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除会议信息编号为"' + ids + '"的数据项?').then(function () {
return delHyjyxx(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
handleKszr(row) {
if (!row || !row.id) {
this.$modal.msgError("未找到ID,无法开始转录")
return
}
const id = row.id
this.$modal.confirm('确认对编号为"' + id + '"的数据开始转录?').then(() => {
return startConvert(id)
}).then(() => {
this.$modal.msgSuccess("已开始转录")
this.getList()
}).catch(() => { })
},
// 跳转到详情页
goDetail(row) {
if (!row || !row.id) return
this.$router.push({ path: `/hyjyxx/hyjyxx/detail/${row.id}` })
},
// 音频上传成功
handleAudioSuccess(response) {
if (response && response.code === 200) {
// 后端返回的文件名或url字段可能为 fileName/url
this.form.ypwj = response.fileName || response.url || ""
// 取文件名用于显示/保存到 ypwjName
this.form.ypwjName = response.originalFilename || ""
// 同步到文件列表用于回显
const displayName = this.form.ypwjName || this.getFileName(this.form.ypwj)
this.audioFileList = this.form.ypwj ? [{ name: displayName, url: this.getAudioUrl(this.form.ypwj) }] : []
this.$modal.msgSuccess("上传成功")
} else {
this.$modal.msgError((response && response.msg) || "上传失败")
}
},
// 音频上传失败
handleAudioError() {
this.$modal.msgError("上传失败,请重试")
},
// 获取音频绝对地址
getAudioUrl(path) {
if (!path) return ""
if (/^https?:\/\//i.test(path)) return path
const base = process.env.VUE_APP_BASE_API || ""
return `${base}${path}`
},
getFileName(fullPath) {
if (!fullPath) return ""
const idx = fullPath.lastIndexOf('/')
return idx >= 0 ? fullPath.slice(idx + 1) : fullPath
},
/** 导出按钮操作 */
handleExport() {
this.download('hyjyxx/hyjyxx/export', {
...this.queryParams
}, `hyjyxx_${new Date().getTime()}.xlsx`)
}
}
}
</script>
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="96px">
<!-- <el-form-item label="主键" prop="id">
<el-input
v-model="queryParams.id"
placeholder="请输入主键"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> -->
<el-form-item label="模版名称" prop="mbmc">
<el-input v-model="queryParams.mbmc" placeholder="请输入模版名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="排序" prop="px">
<el-input v-model="queryParams.px" placeholder="请输入排序" clearable @keyup.enter.native="handleQuery" />
</el-form-item> -->
<!-- <el-form-item label="解析完成时间" prop="jxwcsj">
<el-date-picker clearable v-model="queryParams.jxwcsj" type="date" value-format="yyyy-MM-dd"
placeholder="请选择解析完成时间">
</el-date-picker>
</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 label="备用3" prop="ext3">
<el-input
v-model="queryParams.ext3"
placeholder="请输入备用3"
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-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['hyjyxxMb:hymb:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['hyjyxxMb:hymb:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['hyjyxxMb:hymb:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['hyjyxxMb:hymb:export']">导出</el-button>
</el-form-item>
</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="hymbList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
<el-table-column label="模板名称" align="center" prop="mbmc" min-width="70" show-overflow-tooltip />
<el-table-column label="模板内容" align="center" prop="mbnr" min-width="500" show-overflow-tooltipmin-width="120"
show-overflow-tooltip />
<!-- <el-table-column label="是否默认" align="center" prop="sfmr" min-width="70" show-overflow-tooltip /> -->
<el-table-column label="排序" align="center" prop="px" min-width="50" show-overflow-tooltip />
<!-- <el-table-column label="解析完成时间" align="center" prop="jxwcsj" min-width="80" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ parseTime(scope.row.jxwcsj, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column> -->
<!-- <el-table-column label="创建人" align="center" prop="createdBy" /> -->
<el-table-column label="创建时间" align="center" prop="createdTime" width="150">
<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="120" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['hyjyxxMb:hymb:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['hyjyxxMb:hymb:remove']">删除</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" />
<!-- 添加或修改会议模板对话框 -->
<el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="98px">
<el-form-item label="模板名称" prop="mbmc">
<el-input v-model="form.mbmc" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="模板内容" prop="mbnr">
<el-input v-model="form.mbnr" type="textarea" :autosize="{ minRows: 20, maxRows: 30 }" :maxlength="4000"
show-word-limit placeholder="请输入内容" />
</el-form-item>
<!-- <el-form-item label="是否默认" prop="sfmr">
<el-input v-model="form.sfmr" placeholder="请输入是否默认" />
</el-form-item> -->
<el-form-item label="排序" prop="px">
<el-input v-model="form.px" placeholder="请输入排序" />
</el-form-item>
<!-- <el-form-item label="解析完成时间" prop="jxwcsj">
<el-date-picker clearable v-model="form.jxwcsj" type="date" value-format="yyyy-MM-dd" placeholder="请选择解析完成时间"
style="width: 100%;">
</el-date-picker>
</el-form-item> -->
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listHymb, getHymb, delHymb, addHymb, updateHymb } from "@/api/hyjyxxMb/hymb"
export default {
name: "Hymb",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 会议模板表格数据
hymbList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
id: null,
mbmc: null,
mbnr: null,
sfmr: null,
px: null,
jxwcsj: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null
},
// 表单参数
form: {},
// 表单校验
rules: {
mbmc: [
{ required: true, message: "名称不能为空", trigger: "blur" }
],
mbnr: [
{ required: true, message: "内容不能为空", trigger: "blur" }
],
px: [
{ required: true, message: "排序不能为空", trigger: "blur" }
]
}
}
},
created() {
this.getList()
},
methods: {
/** 查询会议模板列表 */
getList() {
this.loading = true
listHymb(this.queryParams).then(response => {
this.hymbList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
mbmc: null,
mbnr: null,
sfmr: null,
px: null,
jxwcsj: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
ext1: null,
ext2: null,
ext3: null
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加会议模板"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getHymb(id).then(response => {
this.form = response.data
this.open = true
this.title = "修改会议模板"
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateHymb(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addHymb(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除会议模板编号为"' + ids + '"的数据项?').then(function () {
return delHymb(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
/** 导出按钮操作 */
handleExport() {
this.download('hyjyxxMb/hymb/export', {
...this.queryParams
}, `hymb_${new Date().getTime()}.xlsx`)
}
}
}
</script>
<template>
<div class="app-containersy">
<!-- 搜索条件 -->
<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>
<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>
<!-- Tab页面 -->
<el-tabs v-model="activeTab" @tab-click="handleTabClick" style="margin-top: -10px;" class="tabClass">
<!-- 待验收Tab -->
<el-tab-pane label="待验收" name="pending">
<div class="card-container">
<el-row :gutter="16" v-loading="pendingLoading">
<el-col :span="6" v-for="item in pendingList" :key="item.id" class="card-item">
<el-card class="project-card" shadow="hover">
<div class="card-header">
<h3 class="project-title">{{ item.xmmc }}</h3>
<el-tag type="warning" size="small">待验收</el-tag>
</div>
<div class="card-content">
<div class="content-wrapper">
<div class="info-section">
<div class="info-item">
<span class="label">区块:</span>
<span class="value">{{ item.qk || '-' }}</span>
</div>
<div class="info-item">
<span class="label">甲方单位:</span>
<span class="value">{{ item.jfdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">结合单位:</span>
<span class="value">{{ item.jhdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">项目日期:</span>
<span class="value">{{ item.xmrq || '-' }}</span>
</div>
</div>
<div class="button-section">
<el-button type="primary" size="small"
@click="handleComplete(item)">完成</el-button>
</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 分页 -->
<div class="pagination-wrapper">
<pagination v-show="pendingTotal > 0" :total="pendingTotal"
:page.sync="pendingQueryParams.pageNum" :limit.sync="pendingQueryParams.pageSize"
@pagination="getPendingList" />
</div>
</div>
</el-tab-pane>
<!-- 已验收Tab -->
<el-tab-pane label="已验收" name="completed">
<div class="card-container">
<el-row :gutter="16" v-loading="completedLoading">
<el-col :span="6" v-for="item in completedList" :key="item.id" class="card-item">
<el-card class="project-card" shadow="hover">
<div class="card-header">
<h3 class="project-title">{{ item.xmmc }}</h3>
<el-tag type="success" size="small">已验收</el-tag>
</div>
<div class="card-content">
<div class="info-item">
<span class="label">区块:</span>
<span class="value">{{ item.qk || '-' }}</span>
</div>
<div class="info-item">
<span class="label">甲方单位:</span>
<span class="value">{{ item.jfdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">结合单位:</span>
<span class="value">{{ item.jhdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">项目日期:</span>
<span class="value">{{ item.xmrq || '-' }}</span>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 分页 -->
<div class="pagination-wrapper">
<pagination v-show="completedTotal > 0" :total="completedTotal"
:page.sync="completedQueryParams.pageNum" :limit.sync="completedQueryParams.pageSize"
@pagination="getCompletedList" />
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import { listYsqqXmxx, updateYsqqXmxx } from "@/api/ysqqXmxx/ysqqXmxx"
export default {
name: "Ysgc",
data() {
return {
// 当前激活的tab
activeTab: 'pending',
// 显示搜索条件
showSearch: true,
// 查询参数
queryParams: {
xmmc: null
},
// 待验收列表
pendingList: [],
pendingLoading: false,
pendingTotal: 0,
pendingQueryParams: {
pageNum: 1,
pageSize: 12,
xmzt: '待验收'
},
// 已验收列表
completedList: [],
completedLoading: false,
completedTotal: 0,
completedQueryParams: {
pageNum: 1,
pageSize: 12,
xmzt: '已验收'
}
}
},
created() {
this.getPendingList()
},
methods: {
/** 获取待验收列表 */
getPendingList() {
this.pendingLoading = true
const params = {
...this.pendingQueryParams,
...this.queryParams
}
listYsqqXmxx(params).then(response => {
this.pendingList = response.rows
this.pendingTotal = response.total
this.pendingLoading = false
}).catch(() => {
this.pendingLoading = false
})
},
/** 获取已验收列表 */
getCompletedList() {
this.completedLoading = true
const params = {
...this.completedQueryParams,
...this.queryParams
}
listYsqqXmxx(params).then(response => {
this.completedList = response.rows
this.completedTotal = response.total
this.completedLoading = false
}).catch(() => {
this.completedLoading = false
})
},
/** Tab切换 */
handleTabClick(tab) {
if (tab.name === 'pending') {
this.getPendingList()
} else if (tab.name === 'completed') {
this.getCompletedList()
}
},
/** 搜索按钮操作 */
handleQuery() {
if (this.activeTab === 'pending') {
this.pendingQueryParams.pageNum = 1
this.getPendingList()
} else if (this.activeTab === 'completed') {
this.completedQueryParams.pageNum = 1
this.getCompletedList()
}
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams.xmmc = null
this.handleQuery()
},
/** 完成按钮操作 */
handleComplete(row) {
this.$modal.confirm('是否确认完成项目"' + row.xmmc + '"的验收?').then(() => {
const updateData = {
...row,
xmzt: '已验收'
}
return updateYsqqXmxx(updateData)
}).then(() => {
this.$modal.msgSuccess("验收完成")
this.getPendingList()
// 如果当前在已验收tab,也刷新已验收列表
if (this.activeTab === 'completed') {
this.getCompletedList()
}
}).catch(() => { })
},
}
}
</script>
<style scoped>
.app-containersy {
margin: 10px 15px 10px 15px;
}
.card-container {
height: calc(100vh - 200px);
padding: 10px 0;
background: transparent;
border-radius: 8px;
margin: 0 -8px;
padding: 0px 8px;
position: relative;
}
.card-item {
margin-bottom: 10px;
transition: transform 0.2s ease;
}
.card-item:hover {
transform: scale(1.02);
}
.project-card {
height: 240px;
display: flex;
flex-direction: column;
border-radius: 12px;
border: 1px solid #cfd8e6;
background: #ffffff;
box-shadow: 0 10px 24px rgba(64, 158, 255, 0.10), 0 2px 6px rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.project-card:hover {
transform: translateY(-4px);
box-shadow: 0 14px 32px rgba(64, 158, 255, 0.18), 0 4px 10px rgba(0, 0, 0, 0.06);
border-color: #8cb7ff;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
padding: 12px 12px 8px 12px;
border-bottom: 1px solid #f0f2f5;
background: #f9fbff;
}
.project-title {
margin: 0;
font-size: 15px;
font-weight: 600;
color: #2c3e50;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 8px;
position: relative;
}
.card-content {
flex: 1;
padding: 12px;
}
.content-wrapper {
display: flex;
height: 100%;
gap: 12px;
}
.info-section {
flex: 1;
}
.info-item {
display: flex;
margin-bottom: 6px;
font-size: 13px;
padding: 3px 0;
border-radius: 4px;
transition: background-color 0.2s ease;
}
.info-item:hover {
background-color: #f8f9fa;
}
.label {
color: #6c757d;
min-width: 70px;
flex-shrink: 0;
font-weight: 500;
}
.value {
color: #495057;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 400;
}
.button-section {
display: flex;
align-items: center;
justify-content: center;
padding-top: 6px;
/* Ensure always visible, not hover-only */
opacity: 1 !important;
visibility: visible !important;
display: flex !important;
}
.button-section .el-button {
width: 70px;
height: 28px;
font-size: 12px;
font-weight: 500;
border-radius: 14px;
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
border: none;
box-shadow: 0 2px 4px rgba(40, 167, 69, 0.25);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
color: white;
position: relative;
overflow: hidden;
z-index: 1;
/* stay above any overlays */
}
.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.2), transparent);
transition: left 0.5s;
}
.button-section .el-button:hover {
background: linear-gradient(135deg, #20c997 0%, #28a745 100%);
box-shadow: 0 6px 12px rgba(40, 167, 69, 0.35);
transform: translateY(-2px);
}
.button-section .el-button:hover::before {
left: 100%;
}
.button-section .el-button:active {
transform: translateY(0);
box-shadow: 0 3px 6px rgba(40, 167, 69, 0.25);
}
/* Safety: if any global rule hid buttons inside cards on non-hover, override */
.project-card .button-section {
opacity: 1 !important;
visibility: visible !important;
display: flex !important;
}
/* Ensure button itself is not hidden by global rules */
.project-card .button-section .el-button {
opacity: 1 !important;
visibility: visible !important;
}
/* 分页固定在右下角 */
.pagination-wrapper {
position: fixed;
right: 20px;
bottom: 20px;
z-index: 1000;
}
/* 默认大屏下每行5列 */
.el-col {
width: 25% !important;
}
/* 响应式设计 */
@media (max-width: 1400px) {
.el-col {
width: 25% !important;
}
}
@media (max-width: 1200px) {
.el-col {
width: 33.333% !important;
}
}
@media (max-width: 768px) {
.el-col {
width: 50% !important;
}
}
@media (max-width: 480px) {
.el-col {
width: 100% !important;
}
}
</style>
<template> <template>
<div> <div class="app-containersy">
<!-- 搜索条件 -->
<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>
<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>
<!-- Tab页面 -->
<el-tabs v-model="activeTab" @tab-click="handleTabClick" style="margin-top: -10px;" class="tabClass">
<!-- 待验收Tab -->
<el-tab-pane label="待验收" name="pending">
<div class="card-container">
<el-row :gutter="16" v-loading="pendingLoading">
<el-col :span="6" v-for="item in pendingList" :key="item.id" class="card-item">
<el-card class="project-card" shadow="hover">
<div class="card-header" @click="goNav2(item)" style="cursor: pointer;">
<h3 class="project-title">{{ item.xmmc }}</h3>
<el-tag type="warning" size="small">待验收</el-tag>
</div>
<div class="card-content">
<div class="content-wrapper">
<div class="info-section">
<div class="info-item">
<span class="label">区块:</span>
<span class="value">{{ item.qk || '-' }}</span>
</div>
<div class="info-item">
<span class="label">甲方单位:</span>
<span class="value">{{ item.jfdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">结合单位:</span>
<span class="value">{{ item.jhdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">项目日期:</span>
<span class="value">{{ item.xmrq || '-' }}</span>
</div>
</div>
<div class="button-section">
<el-button size="small" @click="handleComplete(item)">完成</el-button>
</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 分页 -->
<div class="pagination-wrapper">
<pagination v-show="pendingTotal > 0" :total="pendingTotal"
:page.sync="pendingQueryParams.pageNum" :limit.sync="pendingQueryParams.pageSize"
@pagination="getPendingList" />
</div>
</div>
</el-tab-pane>
<!-- 已验收Tab -->
<el-tab-pane label="已验收" name="completed">
<div class="card-container">
<el-row :gutter="16" v-loading="completedLoading">
<el-col :span="6" v-for="item in completedList" :key="item.id" class="card-item">
<el-card class="project-card" shadow="hover">
<div class="card-header">
<h3 class="project-title">{{ item.xmmc }}</h3>
<el-tag type="success" size="small">已验收</el-tag>
</div>
<div class="card-content">
<div class="info-item">
<span class="label">区块:</span>
<span class="value">{{ item.qk || '-' }}</span>
</div>
<div class="info-item">
<span class="label">甲方单位:</span>
<span class="value">{{ item.jfdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">结合单位:</span>
<span class="value">{{ item.jhdw || '-' }}</span>
</div>
<div class="info-item">
<span class="label">项目日期:</span>
<span class="value">{{ item.xmrq || '-' }}</span>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 分页 -->
<div class="pagination-wrapper">
<pagination v-show="completedTotal > 0" :total="completedTotal"
:page.sync="completedQueryParams.pageNum" :limit.sync="completedQueryParams.pageSize"
@pagination="getCompletedList" />
</div>
</div>
</el-tab-pane>
</el-tabs>
</div> </div>
</template> </template>
<script> <script>
export default { import { listYsqqXmxx, updateYsqqXmxx } from "@/api/ysqqXmxx/ysqqXmxx"
export default {
name: "Ysgc",
data() {
return {
// 当前激活的tab
activeTab: 'pending',
// 显示搜索条件
showSearch: true,
// 查询参数
queryParams: {
xmmc: null
},
// 待验收列表
pendingList: [],
pendingLoading: false,
pendingTotal: 0,
pendingQueryParams: {
pageNum: 1,
pageSize: 10,
xmzt: '待验收'
},
// 已验收列表
completedList: [],
completedLoading: false,
completedTotal: 0,
completedQueryParams: {
pageNum: 1,
pageSize: 10,
xmzt: '已验收'
}
}
},
created() {
this.getPendingList()
},
methods: {
/** 获取待验收列表 */
getPendingList() {
this.pendingLoading = true
const params = {
...this.pendingQueryParams,
...this.queryParams
}
listYsqqXmxx(params).then(response => {
this.pendingList = response.rows
this.pendingTotal = response.total
this.pendingLoading = false
}).catch(() => {
this.pendingLoading = false
})
},
/** 获取已验收列表 */
getCompletedList() {
this.completedLoading = true
const params = {
...this.completedQueryParams,
...this.queryParams
}
listYsqqXmxx(params).then(response => {
this.completedList = response.rows
this.completedTotal = response.total
this.completedLoading = false
}).catch(() => {
this.completedLoading = false
})
},
/** Tab切换 */
handleTabClick(tab) {
if (tab.name === 'pending') {
this.getPendingList()
} else if (tab.name === 'completed') {
this.getCompletedList()
}
},
/** 搜索按钮操作 */
handleQuery() {
if (this.activeTab === 'pending') {
this.pendingQueryParams.pageNum = 1
this.getPendingList()
} else if (this.activeTab === 'completed') {
this.completedQueryParams.pageNum = 1
this.getCompletedList()
}
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams.xmmc = null
this.handleQuery()
},
/** 完成按钮操作 */
handleComplete(row) {
this.$modal.confirm('是否确认完成项目"' + row.xmmc + '"的验收?').then(() => {
const updateData = {
...row,
xmzt: '已验收'
}
return updateYsqqXmxx(updateData)
}).then(() => {
this.$modal.msgSuccess("验收完成")
this.getPendingList()
// 如果当前在已验收tab,也刷新已验收列表
if (this.activeTab === 'completed') {
this.getCompletedList()
}
}).catch(() => { })
},
/** 跳转到 导航图2 页面 */
goNav2(item) {
const id = item && (item.id || item.zbid)
this.$router.push({
name: 'YsgcIndex2',
query: id ? { id } : {}
})
},
}
} }
</script> </script>
<style lang="scss" scoped></style> <style scoped>
\ No newline at end of file .app-containersy {
margin: 10px 15px 10px 15px;
}
.card-container {
height: calc(100vh - 200px);
padding: 10px 0;
background: transparent;
border-radius: 8px;
margin: 0 -8px;
padding: 0px 8px;
position: relative;
}
.card-item {
margin-bottom: 10px;
transition: transform 0.2s ease;
}
.card-item:hover {
transform: none;
}
.project-card {
height: 220px;
display: flex;
flex-direction: column;
border-radius: 12px;
border: 1px solid #cfd8e6;
background: #ffffff;
box-shadow: 0 10px 24px rgba(64, 158, 255, 0.10), 0 2px 6px rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.project-card:hover {
transform: none;
box-shadow: 0 10px 24px rgba(64, 158, 255, 0.10), 0 2px 6px rgba(0, 0, 0, 0.04);
border-color: #cfd8e6;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
padding: 12px 12px 8px 12px;
border-bottom: 1px solid #f0f2f5;
background: #f9fbff;
}
.project-title {
margin: 0;
font-size: 15px;
font-weight: 600;
color: #2c3e50;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 8px;
position: relative;
}
.card-content {
flex: 1;
padding: 12px;
}
.content-wrapper {
display: flex;
height: 100%;
gap: 12px;
}
.info-section {
flex: 1;
}
.info-item {
display: flex;
margin-bottom: 6px;
font-size: 13px;
padding: 3px 0;
border-radius: 4px;
transition: background-color 0.2s ease;
}
.info-item:hover {
background-color: #f8f9fa;
}
.label {
color: #6c757d;
min-width: 70px;
flex-shrink: 0;
font-weight: 500;
}
.value {
color: #495057;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 400;
}
.button-section {
display: none;
align-items: center;
justify-content: center;
padding-top: 6px;
opacity: 0;
visibility: hidden;
}
.button-section .el-button {
width: 70px;
height: 28px;
font-size: 12px;
font-weight: 500;
border-radius: 14px;
}
/* Safety: if any global rule hid buttons inside cards on non-hover, override */
.project-card:hover .button-section {
display: flex;
opacity: 1;
visibility: visible;
}
/* Ensure button itself is not hidden by global rules */
/* 让按钮在显示时可见 */
.project-card:hover .button-section .el-button {
opacity: 1;
visibility: visible;
}
/* 分页固定在右下角 */
.pagination-wrapper {
position: fixed;
right: 20px;
bottom: 20px;
z-index: 1000;
}
/* 默认大屏下每行5列 */
.el-col {
width: 25% !important;
}
/* 响应式设计 */
@media (max-width: 1400px) {
.el-col {
width: 25% !important;
}
}
@media (max-width: 1200px) {
.el-col {
width: 33.333% !important;
}
}
@media (max-width: 768px) {
.el-col {
width: 50% !important;
}
}
@media (max-width: 480px) {
.el-col {
width: 100% !important;
}
}
</style>
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -36,18 +36,25 @@ ...@@ -36,18 +36,25 @@
<i class="el-icon-edit"></i> <i class="el-icon-edit"></i>
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<el-tooltip :content="internalScrollbarSyncEnabled ? '内部滚动条同步已启用' : '内部滚动条同步已禁用'" placement="bottom"
effect="light">
<el-button @click="toggleInternalScrollbarSync" :class="{ 'active': internalScrollbarSyncEnabled }">
<i class="el-icon-s-operation"></i>
</el-button>
</el-tooltip>
</div> </div>
</div> </div>
<div class="split-container"> <div class="split-container">
<div class="sync-section" ref="topScroll" @scroll="onScroll('top')"> <div class="sync-section" ref="topScroll" @scroll="onScroll('top')">
<div class="zoom-wrapper" ref="topWrapper" :style="{ height: (baseCanvasHeight * zoomScale) + 'px' }"> <div class="zoom-wrapper" ref="topWrapper"
<canvas ref="plot" id="canvasTop" class="plot-canvas" :style="{ transform: 'scale(' + zoomScale + ')' }" /> :style="{ width: baseCanvasWidth + 'px', height: baseCanvasHeight + 'px' }">
<canvas ref="plot" id="canvasTop" class="plot-canvas" />
</div> </div>
</div> </div>
<div class="sync-section" ref="bottomScroll" @scroll="onScroll('bottom')"> <div class="sync-section" ref="bottomScroll" @scroll="onScroll('bottom')">
<div class="zoom-wrapper" ref="bottomWrapper" :style="{ height: (baseCanvasHeight * zoomScale) + 'px' }"> <div class="zoom-wrapper" ref="bottomWrapper"
<canvas ref="plot2" id="canvasBottom" class="plot-canvas" :style="{ width: baseCanvasWidth + 'px', height: baseCanvasHeight + 'px' }">
:style="{ transform: 'scale(' + zoomScale + ')' }" /> <canvas ref="plot2" id="canvasBottom" class="plot-canvas" />
</div> </div>
</div> </div>
</div> </div>
...@@ -316,9 +323,11 @@ export default { ...@@ -316,9 +323,11 @@ export default {
// zoom & scroll sync // zoom & scroll sync
zoomScale: 1, zoomScale: 1,
baseCanvasHeight: 800, baseCanvasHeight: 800,
baseCanvasWidth: 1200,
_isSyncingScroll: false, _isSyncingScroll: false,
_zoomHooked: false, _zoomHooked: false,
_isSyncingZoom: false, _isSyncingZoom: false,
_isInitialLoad: true, // 添加初始加载标志
isHovering: false, isHovering: false,
cursorInfo: { cursorInfo: {
depth: null, depth: null,
...@@ -634,9 +643,32 @@ export default { ...@@ -634,9 +643,32 @@ export default {
clipboard: null, // 用于存储复制的路径 clipboard: null, // 用于存储复制的路径
undoStack: [], // 撤销栈 undoStack: [], // 撤销栈
redoStack: [], // 重做栈 redoStack: [], // 重做栈
internalScrollbarSyncEnabled: true, // 默认启用内部滚动条同步
_isSyncingInternalScroll: false, // 防止内部滚动条同步循环
_isSyncingOuterScroll: false, // 防止外层滚动条同步循环
_outerScrollListeners: [], // 外层滚动条监听器数组
_outerScrollbarSyncInterval: null, // 外层滚动条同步监控定时器
_isSyncingDOMScroll: false, // 防止DOM滚动条同步循环
_domScrollListeners: [], // DOM滚动条监听器列表
_lastTopScrollLeft: 0, // 记录顶部滚动条水平位置
_lastTopScrollTop: 0, // 记录顶部滚动条垂直位置
_lastBottomScrollLeft: 0, // 记录底部滚动条水平位置
_lastBottomScrollTop: 0, // 记录底部滚动条垂直位置
}; };
}, },
mounted() { mounted() {
// 初始化时强制设置为初始状态
this.resetToInitialState();
// 立即禁用滚动条工具
this.disableScrollbarTools();
// 添加强制隐藏滚动条的CSS
this.addForceHideScrollbarCSS();
// 启动强力滚动条监控
this.startAggressiveScrollbarMonitor();
this.$nextTick(() => { this.$nextTick(() => {
this.createScene(this.$refs.plot); this.createScene(this.$refs.plot);
}); });
...@@ -669,8 +701,315 @@ export default { ...@@ -669,8 +701,315 @@ export default {
this.$refs.plot2.addEventListener('contextmenu', this.showContextMenu); this.$refs.plot2.addEventListener('contextmenu', this.showContextMenu);
this.$refs.plot2.addEventListener('mousemove', this.handleMouseMove); this.$refs.plot2.addEventListener('mousemove', this.handleMouseMove);
} }
// 监听窗口变化,更新基准尺寸,确保横向溢出可产生外层滚动条
window.addEventListener('resize', this.updateBaseCanvasSize, { passive: true });
// 启动滚动条监控
this.startScrollbarMonitor();
// 添加全局测试函数(GeoToolkit 3.2.80兼容)
window.testOuterScrollbarSync = () => {
console.log('=== 通过全局函数测试外层滚动条同步 ===');
if (this.testOuterScrollbarSync) {
this.testOuterScrollbarSync();
} else {
console.log('测试方法未找到');
}
};
// 添加内部滚动条隐藏测试函数
window.testInternalScrollbarHidden = () => {
console.log('=== 通过全局函数测试内部滚动条隐藏 ===');
if (this.testInternalScrollbarHidden) {
this.testInternalScrollbarHidden();
} else {
console.log('测试方法未找到');
}
};
console.log('测试函数已添加:');
console.log('- window.testOuterScrollbarSync() - 测试外层滚动条同步');
console.log('- window.testInternalScrollbarHidden() - 测试内部滚动条隐藏');
}, },
methods: { methods: {
// 更新基准宽高,基于外层容器实际尺寸
updateBaseCanvasSize() {
try {
const topEl = this.$refs.topScroll;
if (topEl) {
const rect = topEl.getBoundingClientRect();
if (rect.width > 0) this.baseCanvasWidth = rect.width;
if (rect.height > 0) this.baseCanvasHeight = rect.height;
// 强制设置初始状态,确保不显示滚动条
if (this._isInitialLoad) {
console.log('强制设置初始尺寸,不显示滚动条:', {
width: this.baseCanvasWidth,
height: this.baseCanvasHeight
});
}
}
} catch (e) { /* ignore */ }
},
// 根据 GeoToolkit 模型范围动态计算滚动区域尺寸
updateScrollAreaSize() {
try {
if (!this._seismicWidget) return;
// 获取当前视图范围
const currentLimits = this._seismicWidget.getModelLimits();
if (!currentLimits) return;
// 获取容器实际尺寸作为基准
const topEl = this.$refs.topScroll;
if (topEl) {
const rect = topEl.getBoundingClientRect();
const containerWidth = rect.width;
const containerHeight = rect.height;
// 获取当前视图的宽度和高度
const viewWidth = currentLimits.getWidth();
const viewHeight = currentLimits.getHeight();
// 检查是否是初始状态(视图范围接近容器尺寸)
const isInitialState = Math.abs(viewWidth - containerWidth) < 200 &&
Math.abs(viewHeight - containerHeight) < 200;
// 如果是初始状态,保持原始尺寸,不显示滚动条
if (isInitialState || this._isInitialLoad) {
this.baseCanvasWidth = containerWidth;
this.baseCanvasHeight = containerHeight;
console.log('初始状态,保持容器尺寸:', {
containerSize: { width: containerWidth, height: containerHeight },
viewSize: { width: viewWidth, height: viewHeight },
isInitialLoad: this._isInitialLoad
});
return;
}
// 只有在用户主动缩放时才计算滚动区域
// 使用更保守的缩放因子
const minScale = 1.2; // 降低最小缩放比例
const maxScale = 5; // 降低最大缩放比例
// 基于视图范围计算缩放比例,但只在明显缩放时才应用
const scaleX = Math.min(maxScale, Math.max(minScale, containerWidth / viewWidth));
const scaleY = Math.min(maxScale, Math.max(minScale, containerHeight / viewHeight));
// 只有当缩放比例明显大于1时才更新滚动区域
if (scaleX > 1.1 || scaleY > 1.1) {
const scrollWidth = containerWidth * scaleX;
const scrollHeight = containerHeight * scaleY;
this.baseCanvasWidth = scrollWidth;
this.baseCanvasHeight = scrollHeight;
console.log('用户缩放后更新滚动区域尺寸:', {
containerSize: { width: containerWidth, height: containerHeight },
currentLimits: {
width: viewWidth,
height: viewHeight,
left: currentLimits.getLeft(),
right: currentLimits.getRight(),
top: currentLimits.getTop(),
bottom: currentLimits.getBottom()
},
scaleX, scaleY,
newScrollWidth: scrollWidth,
newScrollHeight: scrollHeight
});
}
}
} catch (e) {
console.warn('更新滚动区域尺寸失败:', e);
}
},
// 彻底禁用滚动条工具
disableScrollbarTools() {
try {
// 等待widget创建完成后再禁用
setTimeout(() => {
if (this._seismicWidget) {
this.disableWidgetScrollbar(this._seismicWidget);
}
if (this._seismicWidgetBottom) {
this.disableWidgetScrollbar(this._seismicWidgetBottom);
}
}, 100);
} catch (e) {
console.warn('禁用滚动条工具失败:', e);
}
},
// 禁用单个widget的滚动条
disableWidgetScrollbar(widget) {
try {
if (!widget) return;
// 方法1: 禁用滚动交互
if (widget.setScrollEnabled) {
widget.setScrollEnabled(false);
console.log('已禁用widget滚动交互');
}
// 方法2: 禁用所有鼠标交互
if (widget.setMouseInteractionsEnabled) {
widget.setMouseInteractionsEnabled(false);
console.log('已禁用widget鼠标交互');
}
// 尝试其他可能的交互禁用方法
if (widget.setInteractionsEnabled) {
widget.setInteractionsEnabled(false);
console.log('已禁用widget交互');
}
if (widget.setWheelEnabled) {
widget.setWheelEnabled(false);
console.log('已禁用widget滚轮交互');
}
if (widget.setPanEnabled) {
widget.setPanEnabled(false);
console.log('已禁用widget平移交互');
}
// 方法3: 通过setOptions禁用
widget.setOptions({
'tools': {
'scrollbar': {
'enabled': false,
'visible': false,
'active': false
}
}
});
// 方法4: 通过工具管理器移除滚动条工具
const toolManager = widget.getTool && widget.getTool();
if (toolManager) {
// 禁用现有的滚动条工具
if (toolManager.getScrollbarTool) {
const scrollbarTool = toolManager.getScrollbarTool();
if (scrollbarTool) {
try { scrollbarTool.setEnabled(false); } catch (e) { }
try { scrollbarTool.setVisible && scrollbarTool.setVisible(false); } catch (e) { }
try { scrollbarTool.setActive && scrollbarTool.setActive(false); } catch (e) { }
}
}
// 移除所有滚动条工具
try {
const tools = toolManager.getTools && toolManager.getTools();
if (tools) {
tools.forEach(tool => {
if (tool && tool.getType && tool.getType() === 'scrollbar') {
toolManager.remove(tool);
}
});
}
} catch (e) {
// ignore
}
}
// 方法5: 通过CSS隐藏滚动条
this.setScrollbarCSS(widget);
// 方法6: 直接操作DOM元素
this.forceHideScrollbarDOM(widget);
} catch (e) {
console.warn('禁用widget滚动条失败:', e);
}
},
// 强制隐藏滚动条DOM元素
forceHideScrollbarDOM(widget) {
try {
if (!widget || !widget.getCanvas) return;
const canvas = widget.getCanvas();
if (!canvas) return;
// 获取canvas的父容器
const container = canvas.parentElement;
if (!container) return;
// 递归查找并隐藏所有滚动条相关元素
const hideScrollbarElements = (element) => {
if (!element || !element.children) return;
Array.from(element.children).forEach(child => {
const classList = Array.from(child.classList || []);
const isScrollbar = classList.some(cls =>
cls.toLowerCase().includes('scrollbar') ||
cls.toLowerCase().includes('scroll') ||
cls.includes('geotoolkit.controls.tools.scroll')
);
if (isScrollbar) {
child.style.display = 'none';
child.style.visibility = 'hidden';
child.style.opacity = '0';
child.style.width = '0';
child.style.height = '0';
child.style.position = 'absolute';
child.style.left = '-9999px';
child.style.top = '-9999px';
child.style.pointerEvents = 'none';
}
// 递归处理子元素
hideScrollbarElements(child);
});
};
// 从容器开始查找
hideScrollbarElements(container);
// 也检查整个document
const allScrollbars = document.querySelectorAll('[class*="scrollbar"], [class*="Scrollbar"], [class*="scroll"], [class*="Scroll"], [class*="geotoolkit.controls.tools.scroll"]');
allScrollbars.forEach(sb => {
sb.style.display = 'none';
sb.style.visibility = 'hidden';
sb.style.opacity = '0';
sb.style.width = '0';
sb.style.height = '0';
sb.style.position = 'absolute';
sb.style.left = '-9999px';
sb.style.top = '-9999px';
sb.style.pointerEvents = 'none';
});
} catch (e) {
console.warn('强制隐藏滚动条DOM失败:', e);
}
},
// 强制重置到初始状态,不显示滚动条
resetToInitialState() {
try {
const topEl = this.$refs.topScroll;
if (topEl) {
const rect = topEl.getBoundingClientRect();
this.baseCanvasWidth = rect.width;
this.baseCanvasHeight = rect.height;
this._isInitialLoad = true;
console.log('强制重置到初始状态:', {
width: this.baseCanvasWidth,
height: this.baseCanvasHeight
});
}
} catch (e) {
console.warn('重置初始状态失败:', e);
}
},
// 创建下半屏镜像视图 // 创建下半屏镜像视图
initSecondWidget(canvas) { initSecondWidget(canvas) {
try { try {
...@@ -678,7 +1017,9 @@ export default { ...@@ -678,7 +1017,9 @@ export default {
'canvasElement': canvas, 'canvasElement': canvas,
'root': this._seismicWidgetBottom = new SeismicWidget(null, { 'root': this._seismicWidgetBottom = new SeismicWidget(null, {
'layouttype': 'inside', 'layouttype': 'inside',
'tools': { 'crosshair': { 'enabled': true } }, 'tools': {
'crosshair': { 'enabled': true }
},
'colorbar': { 'colorbar': {
'axis': { 'size': 20, 'autolabelrotation': true, 'tickgenerator': { 'edge': { 'tickvisible': false, 'labelvisible': false } } }, 'axis': { 'size': 20, 'autolabelrotation': true, 'tickgenerator': { 'edge': { 'tickvisible': false, 'labelvisible': false } } },
'title': { 'size': 0 }, 'title': { 'size': 0 },
...@@ -728,7 +1069,12 @@ export default { ...@@ -728,7 +1069,12 @@ export default {
this.pipelineBottom = pipelineBottom; this.pipelineBottom = pipelineBottom;
this._seismicWidgetBottom.setPipeline(pipelineBottom); this._seismicWidgetBottom.setPipeline(pipelineBottom);
this._seismicWidgetBottom.setOptions({ 'axes': { 'headers': { 'fields': this._headers }, 'samples': { 'title': { 'visible': true, 'text': pipelineBottom.getName() } } } }); this._seismicWidgetBottom.setOptions({ 'axes': { 'headers': { 'fields': this._headers }, 'samples': { 'title': { 'visible': true, 'text': pipelineBottom.getName() } } } });
this._seismicWidgetBottom.fitToBounds(); // 延迟调用fitToBounds,确保初始状态稳定
setTimeout(() => {
this._seismicWidgetBottom.fitToBounds();
}, 800);
// 使用CSS方法彻底禁用下半屏内部滚动条
this.setScrollbarCSS(this._seismicWidgetBottom);
} catch (e) { } catch (e) {
console.warn('初始化下半屏流水线失败:', e); console.warn('初始化下半屏流水线失败:', e);
} }
...@@ -776,6 +1122,12 @@ export default { ...@@ -776,6 +1122,12 @@ export default {
originalBottom(rect); originalBottom(rect);
if (bottom.invalidate) bottom.invalidate(); if (bottom.invalidate) bottom.invalidate();
if (self.updateWidgetScrollbar) self.updateWidgetScrollbar(bottom); if (self.updateWidgetScrollbar) self.updateWidgetScrollbar(bottom);
// 使用CSS方法彻底禁用内部滚动条
if (self.setScrollbarCSS) self.setScrollbarCSS(bottom);
// 更新外层滚动区域尺寸(只在非初始加载时)
if (self.updateScrollAreaSize && !self._isInitialLoad) {
self.updateScrollAreaSize();
}
} finally { } finally {
self._isSyncingZoom = false; self._isSyncingZoom = false;
} }
...@@ -791,6 +1143,12 @@ export default { ...@@ -791,6 +1143,12 @@ export default {
originalTop(rect); originalTop(rect);
if (top.invalidate) top.invalidate(); if (top.invalidate) top.invalidate();
if (self.updateWidgetScrollbar) self.updateWidgetScrollbar(top); if (self.updateWidgetScrollbar) self.updateWidgetScrollbar(top);
// 使用CSS方法彻底禁用内部滚动条
if (self.setScrollbarCSS) self.setScrollbarCSS(top);
// 更新外层滚动区域尺寸(只在非初始加载时)
if (self.updateScrollAreaSize && !self._isInitialLoad) {
self.updateScrollAreaSize();
}
} finally { } finally {
self._isSyncingZoom = false; self._isSyncingZoom = false;
} }
...@@ -816,6 +1174,1120 @@ export default { ...@@ -816,6 +1174,1120 @@ export default {
} }
}, },
// 强制禁用内部滚动条
forceDisableInternalScrollbars(widget) {
if (!widget) return;
try {
// 方法1: 通过工具管理器禁用
const toolManager = widget.getTool && widget.getTool();
if (toolManager) {
if (toolManager.getScrollbarTool) {
const scrollbarTool = toolManager.getScrollbarTool();
if (scrollbarTool) {
try { scrollbarTool.setEnabled(false); } catch (e) { }
try { scrollbarTool.setVisible && scrollbarTool.setVisible(false); } catch (e) { }
try { scrollbarTool.setActive && scrollbarTool.setActive(false); } catch (e) { }
}
}
// 尝试移除滚动条工具
if (toolManager.remove) {
try {
const tools = toolManager.getTools && toolManager.getTools();
if (tools) {
tools.forEach(tool => {
if (tool && tool.getType && tool.getType() === 'scrollbar') {
toolManager.remove(tool);
}
});
}
} catch (e) { }
}
}
// 方法2: 通过widget选项禁用
try {
widget.setOptions({
'tools': {
'scrollbar': {
'enabled': false,
'visible': false,
'active': false
}
}
});
} catch (e) { }
// 方法3: 通过DOM操作隐藏滚动条
setTimeout(() => {
try {
const canvas = widget.getCanvas && widget.getCanvas();
if (canvas) {
const container = canvas.parentElement;
if (container) {
// 隐藏所有可能的滚动条元素
const scrollbars = container.querySelectorAll('.gt-scrollbar, .scrollbar, [class*="scrollbar"]');
scrollbars.forEach(sb => {
sb.style.display = 'none';
sb.style.visibility = 'hidden';
sb.style.pointerEvents = 'none';
sb.style.opacity = '0';
sb.style.width = '0';
sb.style.height = '0';
});
}
}
} catch (e) { }
}, 100);
console.log('内部滚动条已强制禁用');
} catch (error) {
console.warn('禁用内部滚动条时出错:', error);
}
},
// 定期检查并禁用内部滚动条
startScrollbarMonitor() {
if (this._scrollbarMonitorInterval) {
clearInterval(this._scrollbarMonitorInterval);
}
// 只执行一次,不循环
try {
// 使用CSS方法彻底禁用顶部widget的滚动条
if (this._seismicWidget) {
this.setScrollbarCSS(this._seismicWidget);
this.disableWidgetScrollbar(this._seismicWidget);
}
// 使用CSS方法彻底禁用底部widget的滚动条
if (this._seismicWidgetBottom) {
this.setScrollbarCSS(this._seismicWidgetBottom);
this.disableWidgetScrollbar(this._seismicWidgetBottom);
}
// 通过DOM检查隐藏任何出现的滚动条
const allScrollbars = document.querySelectorAll('.gt-scrollbar, .scrollbar, [class*="scrollbar"], [class*="Scroll"], [class*="scroll"], [class*="geotoolkit.controls.tools.scroll"]');
allScrollbars.forEach(sb => {
if (sb.style.display !== 'none') {
sb.style.display = 'none';
sb.style.visibility = 'hidden';
sb.style.pointerEvents = 'none';
sb.style.opacity = '0';
sb.style.width = '0';
sb.style.height = '0';
sb.style.position = 'absolute';
sb.style.left = '-9999px';
sb.style.top = '-9999px';
}
});
console.log('滚动条监控已执行一次');
} catch (e) {
console.warn('滚动条监控失败:', e);
}
},
// 停止滚动条监控
stopScrollbarMonitor() {
if (this._scrollbarMonitorInterval) {
clearInterval(this._scrollbarMonitorInterval);
this._scrollbarMonitorInterval = null;
}
},
// 使用CSS方法彻底禁用内部滚动条
setScrollbarCSS(widget) {
if (!widget || !widget.setCss) return;
try {
const css = [
// 隐藏水平滚动条 - 使用GeoToolkit的实际类名
'*[class="geotoolkit.controls.tools.scroll.HorizontalScroll"] {',
' display: none !important;',
' visibility: hidden !important;',
' opacity: 0 !important;',
' width: 0 !important;',
' height: 0 !important;',
' pointer-events: none !important;',
' position: absolute !important;',
' left: -9999px !important;',
' top: -9999px !important;',
'}',
// 隐藏垂直滚动条 - 使用GeoToolkit的实际类名
'*[class="geotoolkit.controls.tools.scroll.VerticalScroll"] {',
' display: none !important;',
' visibility: hidden !important;',
' opacity: 0 !important;',
' width: 0 !important;',
' height: 0 !important;',
' pointer-events: none !important;',
' position: absolute !important;',
' left: -9999px !important;',
' top: -9999px !important;',
'}',
// 隐藏所有可能的滚动条相关元素
'.gt-scrollbar,',
'.gt-scrollbar-horizontal,',
'.gt-scrollbar-vertical,',
'[class*="scrollbar"],',
'[class*="Scrollbar"],',
'.scrollbar,',
'.scrollbar-horizontal,',
'.scrollbar-vertical,',
'[class*="Scroll"],',
'[class*="scroll"] {',
' display: none !important;',
' visibility: hidden !important;',
' opacity: 0 !important;',
' width: 0 !important;',
' height: 0 !important;',
' pointer-events: none !important;',
' position: absolute !important;',
' left: -9999px !important;',
' top: -9999px !important;',
'}',
// 隐藏滚动条滑块和轨道
'.scrollbar-thumb,',
'.scrollbar-track,',
'.gt-scrollbar-thumb,',
'.gt-scrollbar-track,',
'[class*="thumb"],',
'[class*="track"] {',
' display: none !important;',
' visibility: hidden !important;',
' opacity: 0 !important;',
' width: 0 !important;',
' height: 0 !important;',
' pointer-events: none !important;',
'}',
// 确保滚动条容器也被隐藏
'[class*="scroll-container"],',
'[class*="ScrollContainer"],',
'.scroll-container {',
' display: none !important;',
' visibility: hidden !important;',
' opacity: 0 !important;',
' width: 0 !important;',
' height: 0 !important;',
' pointer-events: none !important;',
'}',
// 新增:隐藏 GeoToolkit-js 2.0 特有的滚动条元素
'[class*="geotoolkit.controls.tools.scroll"],',
'[class*="ScrollTool"],',
'[class*="scroll-tool"],',
'[class*="ScrollBar"],',
'[class*="scroll-bar"],',
'[class*="ScrollbarTool"],',
'[class*="scrollbar-tool"] {',
' display: none !important;',
' visibility: hidden !important;',
' opacity: 0 !important;',
' width: 0 !important;',
' height: 0 !important;',
' position: absolute !important;',
' left: -9999px !important;',
' top: -9999px !important;',
' pointer-events: none !important;',
'}',
// 新增:隐藏可能的滚动条容器和包装器
'[class*="scroll-wrapper"],',
'[class*="ScrollWrapper"],',
'[class*="scroll-area"],',
'[class*="ScrollArea"] {',
' overflow: hidden !important;',
'}'
].join('\n');
widget.setCss(css);
console.log('已通过CSS方法彻底禁用内部滚动条');
} catch (error) {
console.warn('设置滚动条CSS失败:', error);
}
},
// 强制同步内部滚动条(如果必须保留内部滚动条)
enableInternalScrollbarSync() {
if (!this._seismicWidget || !this._seismicWidgetBottom) return;
try {
// 彻底禁用内部滚动条
this.forceDisableInternalScrollbars();
// 强制隐藏所有内部滚动条
this.forceHideAllInternalScrollbars();
// 设置外层滚动条同步
this.setupOuterScrollbarSync();
// 启动外层滚动条同步监控
this.startOuterScrollbarSyncMonitor();
console.log('已彻底禁用内部滚动条并启用外层滚动条同步')
} catch (error) {
console.warn('启用外层滚动条同步失败:', error);
}
},
// 设置外层滚动条同步(GeoToolkit 3.2.80兼容模式)
setupOuterScrollbarSync() {
if (!this._seismicWidget || !this._seismicWidgetBottom) return;
try {
// 清除之前的监听器
this.clearOuterScrollbarListeners();
// 获取外层滚动容器
const topContainer = this.getOuterScrollContainer(this._seismicWidget);
const bottomContainer = this.getOuterScrollContainer(this._seismicWidgetBottom);
if (!topContainer || !bottomContainer) {
console.warn('未找到外层滚动容器');
return;
}
// 创建防抖的同步函数
this._syncFromTopOuter = this.debounce((event) => {
try {
if (this._isSyncingOuterScroll) return;
this._isSyncingOuterScroll = true;
// 同步到底部容器
bottomContainer.scrollLeft = topContainer.scrollLeft;
bottomContainer.scrollTop = topContainer.scrollTop;
// 同步GeoToolkit内部视图
this.syncGeoToolkitView(this._seismicWidgetBottom, topContainer.scrollLeft, topContainer.scrollTop);
setTimeout(() => {
this._isSyncingOuterScroll = false;
}, 10);
} catch (e) {
console.warn('同步外层滚动位置失败:', e);
this._isSyncingOuterScroll = false;
}
}, 5);
this._syncFromBottomOuter = this.debounce((event) => {
try {
if (this._isSyncingOuterScroll) return;
this._isSyncingOuterScroll = true;
// 同步到顶部容器
topContainer.scrollLeft = bottomContainer.scrollLeft;
topContainer.scrollTop = bottomContainer.scrollTop;
// 同步GeoToolkit内部视图
this.syncGeoToolkitView(this._seismicWidget, bottomContainer.scrollLeft, bottomContainer.scrollTop);
setTimeout(() => {
this._isSyncingOuterScroll = false;
}, 10);
} catch (e) {
console.warn('同步外层滚动位置失败:', e);
this._isSyncingOuterScroll = false;
}
}, 5);
// 监听顶部容器的滚动事件
topContainer.addEventListener('scroll', this._syncFromTopOuter);
this._outerScrollListeners.push({ element: topContainer, event: 'scroll', handler: this._syncFromTopOuter });
// 监听底部容器的滚动事件
bottomContainer.addEventListener('scroll', this._syncFromBottomOuter);
this._outerScrollListeners.push({ element: bottomContainer, event: 'scroll', handler: this._syncFromBottomOuter });
console.log('外层滚动条同步已设置(GeoToolkit 3.2.80兼容模式)');
} catch (error) {
console.warn('设置外层滚动条同步失败:', error);
}
},
// 清除外层滚动条监听器
clearOuterScrollbarListeners() {
try {
if (this._outerScrollListeners) {
this._outerScrollListeners.forEach(({ element, event, handler }) => {
if (element && element.removeEventListener) {
element.removeEventListener(event, handler);
}
});
this._outerScrollListeners = [];
}
} catch (e) {
console.warn('清除外层滚动条监听器失败:', e);
}
},
// 防抖函数
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
},
// 设置DOM级别的滚动条同步
setupDOMScrollbarSync() {
try {
// 清除之前的DOM监听器
this.clearDOMScrollbarListeners();
// 获取滚动条DOM元素
const topScrollbars = this.findScrollbarElements(this._seismicWidget);
const bottomScrollbars = this.findScrollbarElements(this._seismicWidgetBottom);
if (topScrollbars.length === 0 || bottomScrollbars.length === 0) {
console.log('未找到滚动条DOM元素,跳过DOM同步');
return;
}
// 为顶部滚动条添加事件监听
topScrollbars.forEach(scrollbar => {
const onTopScroll = this.debounce((event) => {
if (this._isSyncingDOMScroll) return;
this._isSyncingDOMScroll = true;
// 同步到底部滚动条
bottomScrollbars.forEach(bottomScrollbar => {
if (bottomScrollbar.scrollLeft !== undefined) {
bottomScrollbar.scrollLeft = scrollbar.scrollLeft;
}
if (bottomScrollbar.scrollTop !== undefined) {
bottomScrollbar.scrollTop = scrollbar.scrollTop;
}
});
setTimeout(() => {
this._isSyncingDOMScroll = false;
}, 10);
}, 5);
scrollbar.addEventListener('scroll', onTopScroll);
this._domScrollListeners.push({ element: scrollbar, event: 'scroll', handler: onTopScroll });
});
// 为底部滚动条添加事件监听
bottomScrollbars.forEach(scrollbar => {
const onBottomScroll = this.debounce((event) => {
if (this._isSyncingDOMScroll) return;
this._isSyncingDOMScroll = true;
// 同步到顶部滚动条
topScrollbars.forEach(topScrollbar => {
if (topScrollbar.scrollLeft !== undefined) {
topScrollbar.scrollLeft = scrollbar.scrollLeft;
}
if (topScrollbar.scrollTop !== undefined) {
topScrollbar.scrollTop = scrollbar.scrollTop;
}
});
setTimeout(() => {
this._isSyncingDOMScroll = false;
}, 10);
}, 5);
scrollbar.addEventListener('scroll', onBottomScroll);
this._domScrollListeners.push({ element: scrollbar, event: 'scroll', handler: onBottomScroll });
});
console.log('DOM级别滚动条同步已设置');
} catch (e) {
console.warn('设置DOM滚动条同步失败:', e);
}
},
// 获取外层滚动容器(GeoToolkit 3.2.80兼容)
getOuterScrollContainer(widget) {
try {
if (!widget || !widget.getCanvas) return null;
const canvas = widget.getCanvas();
if (!canvas) return null;
// 查找包含widget的滚动容器
let container = canvas.parentElement;
while (container && container !== document.body) {
// 检查容器是否有滚动能力
if (container.scrollWidth > container.clientWidth ||
container.scrollHeight > container.clientHeight) {
return container;
}
// 检查容器是否有overflow: auto/scroll样式
const style = window.getComputedStyle(container);
if (style.overflow === 'auto' || style.overflow === 'scroll' ||
style.overflowX === 'auto' || style.overflowX === 'scroll' ||
style.overflowY === 'auto' || style.overflowY === 'scroll') {
return container;
}
container = container.parentElement;
}
// 如果没有找到滚动容器,返回canvas的直接父容器
return canvas.parentElement;
} catch (e) {
console.warn('获取外层滚动容器失败:', e);
return null;
}
},
// 同步GeoToolkit内部视图(GeoToolkit 3.2.80兼容)
syncGeoToolkitView(widget, scrollLeft, scrollTop) {
try {
if (!widget) return;
// 方法1: 通过setViewport同步
if (widget.setViewport) {
const viewport = widget.getViewport();
if (viewport) {
// 计算新的视图位置
const newViewport = {
x: scrollLeft || 0,
y: scrollTop || 0,
width: viewport.width || 800,
height: viewport.height || 600
};
widget.setViewport(newViewport);
}
}
// 方法2: 通过setPosition同步
if (widget.setPosition) {
widget.setPosition(scrollLeft || 0, scrollTop || 0);
}
// 方法3: 通过工具管理器同步
if (widget.getTool) {
const toolManager = widget.getTool();
if (toolManager && toolManager.setPosition) {
toolManager.setPosition(scrollLeft || 0, scrollTop || 0);
}
}
// 方法4: 通过Plot同步
if (widget.getPlot) {
const plot = widget.getPlot();
if (plot && plot.setViewport) {
const viewport = plot.getViewport();
if (viewport) {
const newViewport = {
x: scrollLeft || 0,
y: scrollTop || 0,
width: viewport.width || 800,
height: viewport.height || 600
};
plot.setViewport(newViewport);
}
}
}
// 强制重绘
if (widget.invalidate) {
widget.invalidate();
}
} catch (e) {
console.warn('同步GeoToolkit内部视图失败:', e);
}
},
// 启动外层滚动条同步监控(GeoToolkit 3.2.80兼容)
startOuterScrollbarSyncMonitor() {
if (this._outerScrollbarSyncInterval) {
clearInterval(this._outerScrollbarSyncInterval);
}
this._outerScrollbarSyncInterval = setInterval(() => {
try {
this.forceOuterScrollbarSync();
} catch (e) {
console.warn('外层滚动条同步监控失败:', e);
}
}, 50); // 每50ms检查一次,提高响应性
},
// 强制外层滚动条同步(GeoToolkit 3.2.80兼容)
forceOuterScrollbarSync() {
try {
if (!this._seismicWidget || !this._seismicWidgetBottom) return;
// 获取两个widget的外层滚动容器
const topContainer = this.getOuterScrollContainer(this._seismicWidget);
const bottomContainer = this.getOuterScrollContainer(this._seismicWidgetBottom);
if (!topContainer || !bottomContainer) return;
// 检查是否有滚动位置不同步
if (topContainer.scrollLeft !== bottomContainer.scrollLeft) {
if (this._lastTopScrollLeft !== topContainer.scrollLeft) {
bottomContainer.scrollLeft = topContainer.scrollLeft;
this._lastTopScrollLeft = topContainer.scrollLeft;
// 同步GeoToolkit内部视图
this.syncGeoToolkitView(this._seismicWidgetBottom, topContainer.scrollLeft, topContainer.scrollTop);
} else if (this._lastBottomScrollLeft !== bottomContainer.scrollLeft) {
topContainer.scrollLeft = bottomContainer.scrollLeft;
this._lastBottomScrollLeft = bottomContainer.scrollLeft;
// 同步GeoToolkit内部视图
this.syncGeoToolkitView(this._seismicWidget, bottomContainer.scrollLeft, bottomContainer.scrollTop);
}
}
if (topContainer.scrollTop !== bottomContainer.scrollTop) {
if (this._lastTopScrollTop !== topContainer.scrollTop) {
bottomContainer.scrollTop = topContainer.scrollTop;
this._lastTopScrollTop = topContainer.scrollTop;
// 同步GeoToolkit内部视图
this.syncGeoToolkitView(this._seismicWidgetBottom, topContainer.scrollLeft, topContainer.scrollTop);
} else if (this._lastBottomScrollTop !== bottomContainer.scrollTop) {
topContainer.scrollTop = bottomContainer.scrollTop;
this._lastBottomScrollTop = bottomContainer.scrollTop;
// 同步GeoToolkit内部视图
this.syncGeoToolkitView(this._seismicWidget, bottomContainer.scrollLeft, bottomContainer.scrollTop);
}
}
} catch (e) {
console.warn('强制外层滚动条同步失败:', e);
}
},
// 停止外层滚动条同步监控
stopOuterScrollbarSyncMonitor() {
if (this._outerScrollbarSyncInterval) {
clearInterval(this._outerScrollbarSyncInterval);
this._outerScrollbarSyncInterval = null;
}
},
// 强制隐藏所有内部滚动条
forceHideAllInternalScrollbars() {
try {
// 方法1: 禁用widget滚动条
if (this._seismicWidget) {
this.disableWidgetScrollbar(this._seismicWidget);
}
if (this._seismicWidgetBottom) {
this.disableWidgetScrollbar(this._seismicWidgetBottom);
}
// 方法2: 强制隐藏所有滚动条DOM元素
this.forceHideAllScrollbars();
// 方法3: 添加全局CSS样式
this.addGlobalScrollbarHideCSS();
// 方法4: 启动强力隐藏监控
this.startAggressiveScrollbarHideMonitor();
console.log('已强制隐藏所有内部滚动条');
} catch (e) {
console.warn('强制隐藏内部滚动条失败:', e);
}
},
// 启动强力滚动条隐藏监控
startAggressiveScrollbarHideMonitor() {
if (this._scrollbarHideInterval) {
clearInterval(this._scrollbarHideInterval);
}
// 只执行一次,不循环
try {
// 强制隐藏所有滚动条
this.forceHideAllScrollbars();
// 添加CSS样式
this.addGlobalScrollbarHideCSS();
// 禁用滚动条交互
this.disableScrollbarInteractions();
console.log('滚动条隐藏监控已执行一次');
} catch (e) {
console.warn('滚动条隐藏监控失败:', e);
}
},
// 禁用滚动条交互
disableScrollbarInteractions() {
try {
const scrollbarElements = document.querySelectorAll('[class*="scrollbar"], [class*="Scrollbar"], [class*="scroll"], [class*="Scroll"], [class*="geotoolkit.controls.tools.scroll"]');
scrollbarElements.forEach(element => {
// 禁用所有交互
element.style.pointerEvents = 'none';
element.style.userSelect = 'none';
element.style.touchAction = 'none';
// 隐藏元素
element.style.display = 'none';
element.style.visibility = 'hidden';
element.style.opacity = '0';
element.style.width = '0';
element.style.height = '0';
element.style.position = 'absolute';
element.style.left = '-9999px';
element.style.top = '-9999px';
element.style.zIndex = '-9999';
// 禁用滚动事件
element.addEventListener('scroll', (e) => {
e.preventDefault();
e.stopPropagation();
return false;
}, { passive: false });
element.addEventListener('wheel', (e) => {
e.preventDefault();
e.stopPropagation();
return false;
}, { passive: false });
});
} catch (e) {
console.warn('禁用滚动条交互失败:', e);
}
},
// 停止滚动条隐藏监控
stopScrollbarHideMonitor() {
if (this._scrollbarHideInterval) {
clearInterval(this._scrollbarHideInterval);
this._scrollbarHideInterval = null;
}
},
// 测试外层滚动条同步(GeoToolkit 3.2.80兼容)
testOuterScrollbarSync() {
try {
console.log('=== 测试外层滚动条同步 ===');
// 获取外层滚动容器
const topContainer = this.getOuterScrollContainer(this._seismicWidget);
const bottomContainer = this.getOuterScrollContainer(this._seismicWidgetBottom);
console.log('顶部容器:', topContainer);
console.log('底部容器:', bottomContainer);
if (topContainer && bottomContainer) {
console.log('顶部容器滚动位置:', { scrollLeft: topContainer.scrollLeft, scrollTop: topContainer.scrollTop });
console.log('底部容器滚动位置:', { scrollLeft: bottomContainer.scrollLeft, scrollTop: bottomContainer.scrollTop });
// 测试同步
const testScrollLeft = 100;
const testScrollTop = 50;
topContainer.scrollLeft = testScrollLeft;
topContainer.scrollTop = testScrollTop;
console.log('设置顶部容器滚动位置:', { scrollLeft: testScrollLeft, scrollTop: testScrollTop });
// 检查同步是否生效
setTimeout(() => {
console.log('同步后底部容器滚动位置:', {
scrollLeft: bottomContainer.scrollLeft,
scrollTop: bottomContainer.scrollTop
});
if (bottomContainer.scrollLeft === testScrollLeft && bottomContainer.scrollTop === testScrollTop) {
console.log('✅ 外层滚动条同步测试成功!');
} else {
console.log('❌ 外层滚动条同步测试失败!');
}
}, 100);
} else {
console.log('❌ 未找到外层滚动容器');
}
} catch (e) {
console.error('测试外层滚动条同步失败:', e);
}
},
// 测试内部滚动条是否被隐藏
testInternalScrollbarHidden() {
try {
console.log('=== 测试内部滚动条是否被隐藏 ===');
// 查找所有可能的滚动条元素
const scrollbarSelectors = [
'[class*="scrollbar"]',
'[class*="Scrollbar"]',
'[class*="scroll"]',
'[class*="Scroll"]',
'[class*="geotoolkit.controls.tools.scroll"]',
'.gt-scrollbar',
'.scrollbar'
];
let foundScrollbars = [];
scrollbarSelectors.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(el => {
if (el.offsetWidth > 0 || el.offsetHeight > 0) {
foundScrollbars.push({
element: el,
selector: selector,
visible: el.style.display !== 'none' && el.style.visibility !== 'hidden',
dimensions: { width: el.offsetWidth, height: el.offsetHeight }
});
}
});
});
if (foundScrollbars.length === 0) {
console.log('✅ 未找到任何可见的内部滚动条!');
} else {
console.log('❌ 发现以下可见的内部滚动条:');
foundScrollbars.forEach((item, index) => {
console.log(`${index + 1}. 选择器: ${item.selector}`);
console.log(` 可见性: ${item.visible ? '可见' : '隐藏'}`);
console.log(` 尺寸: ${item.dimensions.width}x${item.dimensions.height}`);
console.log(` 元素:`, item.element);
});
// 尝试强制隐藏这些滚动条
foundScrollbars.forEach(item => {
this.hideScrollbarElement(item.element);
});
console.log('已尝试强制隐藏发现的滚动条');
}
} catch (e) {
console.error('测试内部滚动条隐藏失败:', e);
}
},
// 强制禁用内部滚动条(GeoToolkit 3.2.80兼容)
forceDisableInternalScrollbars() {
try {
if (!this._seismicWidget || !this._seismicWidgetBottom) return;
// 方法1: 通过setOptions禁用
this._seismicWidget.setOptions({
'tools': {
'scrollbar': {
'enabled': false,
'visible': false
}
}
});
this._seismicWidgetBottom.setOptions({
'tools': {
'scrollbar': {
'enabled': false,
'visible': false
}
}
});
// 方法2: 通过工具管理器禁用
if (this._seismicWidget.getTool) {
const topToolManager = this._seismicWidget.getTool();
if (topToolManager && topToolManager.setScrollbarTool) {
const topScrollbar = topToolManager.getScrollbarTool();
if (topScrollbar && topScrollbar.setEnabled) {
topScrollbar.setEnabled(false);
}
}
}
if (this._seismicWidgetBottom.getTool) {
const bottomToolManager = this._seismicWidgetBottom.getTool();
if (bottomToolManager && bottomToolManager.setScrollbarTool) {
const bottomScrollbar = bottomToolManager.getScrollbarTool();
if (bottomScrollbar && bottomScrollbar.setEnabled) {
bottomScrollbar.setEnabled(false);
}
}
}
// 方法3: 通过CSS强制隐藏
this.addForceHideScrollbarCSS();
console.log('已强制禁用内部滚动条');
} catch (error) {
console.warn('强制禁用内部滚动条失败:', error);
}
},
// 启动滚动条同步状态监控
startScrollbarSyncStatusMonitor() {
// 已禁用内部滚动条同步,直接返回
return;
},
// 确保滚动条同步(已禁用内部同步,直接返回)
ensureScrollbarSync() {
return;
},
// 停止滚动条同步状态监控
stopScrollbarSyncStatusMonitor() {
if (this._scrollbarSyncStatusInterval) {
clearInterval(this._scrollbarSyncStatusInterval);
this._scrollbarSyncStatusInterval = null;
}
},
// 添加强制隐藏滚动条的CSS(GeoToolkit 3.2.80兼容)
addForceHideScrollbarCSS() {
try {
// 检查是否已经添加过
if (document.getElementById('force-hide-scrollbar-css')) {
return;
}
const style = document.createElement('style');
style.id = 'force-hide-scrollbar-css';
style.textContent = `
/* 强制隐藏所有GeoToolkit内部滚动条 */
*[class*="geotoolkit.controls.tools.scroll"],
*[class*="ScrollTool"],
*[class*="scroll-tool"],
*[class*="ScrollBar"],
*[class*="scroll-bar"],
*[class*="ScrollbarTool"],
*[class*="scrollbar-tool"],
.gt-scrollbar,
.gt-scrollbar-horizontal,
.gt-scrollbar-vertical,
[class*="scrollbar"],
[class*="Scrollbar"],
.scrollbar,
.scrollbar-horizontal,
.scrollbar-vertical,
[class*="Scroll"],
[class*="scroll"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
pointer-events: none !important;
z-index: -9999 !important;
}
/* 隐藏滚动条滑块和轨道 */
.scrollbar-thumb,
.scrollbar-track,
.gt-scrollbar-thumb,
.gt-scrollbar-track,
[class*="thumb"],
[class*="track"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
pointer-events: none !important;
}
/* 确保滚动条容器也被隐藏 */
[class*="scroll-container"],
*[class*="ScrollContainer"],
.scroll-container {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
pointer-events: none !important;
}
/* 隐藏可能的滚动条容器和包装器 */
[class*="scroll-wrapper"],
*[class*="ScrollWrapper"],
*[class*="scroll-area"],
*[class*="ScrollArea"] {
overflow: hidden !important;
}
/* 针对GeoToolkit 3.2.80的特定滚动条类名 */
*[class="geotoolkit.controls.tools.scroll.HorizontalScroll"],
*[class="geotoolkit.controls.tools.scroll.VerticalScroll"],
*[class*="geotoolkit.controls.tools.scroll.HorizontalScroll"],
*[class*="geotoolkit.controls.tools.scroll.VerticalScroll"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
pointer-events: none !important;
z-index: -9999 !important;
}
`;
document.head.appendChild(style);
console.log('已添加强制隐藏滚动条的CSS');
} catch (error) {
console.warn('添加强制隐藏滚动条CSS失败:', error);
}
},
// 启动强力滚动条监控
startAggressiveScrollbarMonitor() {
// 使用 MutationObserver 监控 DOM 变化
if (this._scrollbarObserver) {
this._scrollbarObserver.disconnect();
}
this._scrollbarObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
this.hideScrollbarElement(node);
// 递归检查子元素
const scrollbarElements = node.querySelectorAll('[class*="scrollbar"], [class*="Scrollbar"], [class*="scroll"], [class*="Scroll"], [class*="geotoolkit.controls.tools.scroll"]');
scrollbarElements.forEach(el => this.hideScrollbarElement(el));
}
});
}
});
});
// 开始观察
this._scrollbarObserver.observe(document.body, {
childList: true,
subtree: true
});
// 定期强制隐藏滚动条(更频繁)
this._aggressiveScrollbarInterval = setInterval(() => {
this.forceHideAllScrollbars();
this.forceDisableInternalScrollbars();
}, 100); // 每100ms检查一次
},
// 隐藏单个滚动条元素
hideScrollbarElement(element) {
if (!element || !element.classList) return;
const classList = Array.from(element.classList);
const isScrollbar = classList.some(cls =>
cls.toLowerCase().includes('scrollbar') ||
cls.toLowerCase().includes('scroll') ||
cls.includes('geotoolkit.controls.tools.scroll')
);
if (isScrollbar) {
element.style.display = 'none';
element.style.visibility = 'hidden';
element.style.opacity = '0';
element.style.width = '0';
element.style.height = '0';
element.style.position = 'absolute';
element.style.left = '-9999px';
element.style.top = '-9999px';
element.style.pointerEvents = 'none';
}
},
// 强制隐藏所有滚动条
forceHideAllScrollbars() {
const selectors = [
'[class*="scrollbar"]',
'[class*="Scrollbar"]',
'[class*="scroll"]',
'[class*="Scroll"]',
'[class*="geotoolkit.controls.tools.scroll"]',
'.gt-scrollbar',
'.gt-scrollbar-horizontal',
'.gt-scrollbar-vertical'
];
selectors.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(element => {
this.hideScrollbarElement(element);
});
});
},
// 停止强力滚动条监控
stopAggressiveScrollbarMonitor() {
if (this._scrollbarObserver) {
this._scrollbarObserver.disconnect();
this._scrollbarObserver = null;
}
if (this._aggressiveScrollbarInterval) {
clearInterval(this._aggressiveScrollbarInterval);
this._aggressiveScrollbarInterval = null;
}
},
// 强制禁用所有滚动条
forceDisableAllScrollbars() {
try {
// 禁用widget滚动条
if (this._seismicWidget) {
this.disableWidgetScrollbar(this._seismicWidget);
}
if (this._seismicWidgetBottom) {
this.disableWidgetScrollbar(this._seismicWidgetBottom);
}
// 强制隐藏所有滚动条DOM元素
this.forceHideAllScrollbars();
// 添加CSS样式来隐藏滚动条
this.addGlobalScrollbarHideCSS();
console.log('已强制禁用所有内部滚动条');
} catch (e) {
console.warn('强制禁用滚动条失败:', e);
}
},
// 添加全局滚动条隐藏CSS
addGlobalScrollbarHideCSS() {
try {
// 检查是否已经添加过样式
if (document.getElementById('geotoolkit-scrollbar-hide')) {
return;
}
const style = document.createElement('style');
style.id = 'geotoolkit-scrollbar-hide';
style.textContent = `
/* 强制隐藏所有GeoToolkit滚动条 */
*[class*="scrollbar"],
*[class*="Scrollbar"],
*[class*="scroll"],
*[class*="Scroll"],
*[class*="geotoolkit.controls.tools.scroll"],
.gt-scrollbar,
.gt-scrollbar-horizontal,
.gt-scrollbar-vertical,
[class*="scrollbar-tool"],
[class*="ScrollbarTool"],
[class*="scroll-tool"],
[class*="ScrollTool"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
pointer-events: none !important;
z-index: -9999 !important;
}
`;
document.head.appendChild(style);
} catch (e) {
console.warn('添加全局滚动条隐藏CSS失败:', e);
}
},
createScene(canvas) { createScene(canvas) {
try { try {
const autoFormat = new AutoNumberFormat(4); const autoFormat = new AutoNumberFormat(4);
...@@ -934,6 +2406,9 @@ export default { ...@@ -934,6 +2406,9 @@ export default {
// 注册自定义颜色映射 // 注册自定义颜色映射
this.registerColorMaps(this.colorProvider); this.registerColorMaps(this.colorProvider);
// 使用CSS方法彻底禁用内部滚动条
this.setScrollbarCSS(this._seismicWidget);
// 初始化默认的颜色映射,使用256色以获得更平滑的渐变 // 初始化默认的颜色映射,使用256色以获得更平滑的渐变
this._colorMap = this.colorProvider.createNamedColorMap('WhiteBlack', 256); this._colorMap = this.colorProvider.createNamedColorMap('WhiteBlack', 256);
...@@ -967,8 +2442,21 @@ export default { ...@@ -967,8 +2442,21 @@ export default {
// 初始化缩放基础高度 // 初始化缩放基础高度
this.$nextTick(() => { this.$nextTick(() => {
const ch = this.$refs.plot && (this.$refs.plot.clientHeight || 0); this.updateBaseCanvasSize();
if (ch > 0) this.baseCanvasHeight = ch; // 延迟初始化滚动区域尺寸,给数据加载更多时间
setTimeout(() => {
// 只在用户主动操作后才更新滚动区域
// 初始加载时不调用 updateScrollAreaSize
console.log('数据加载完成,保持初始尺寸');
}, 1000);
// 强制禁用内部滚动条
this.forceDisableInternalScrollbars(this._seismicWidget);
// 额外禁用滚动条工具
this.disableScrollbarTools();
// 启用内部滚动条同步
this.enableInternalScrollbarSync();
}); });
}); });
}); });
...@@ -1106,8 +2594,31 @@ export default { ...@@ -1106,8 +2594,31 @@ export default {
console.warn('Failed to add Reverse:', e); console.warn('Failed to add Reverse:', e);
} }
this._seismicWidget.fitToBounds(); // 先设置就绪状态,但不立即调用fitToBounds
this.isWidgetReady = true; this.isWidgetReady = true;
// 强制禁用内部滚动条
this.forceDisableInternalScrollbars();
// 延迟调用fitToBounds,确保初始状态稳定
setTimeout(() => {
this._seismicWidget.fitToBounds();
console.log('数据加载完成,调用fitToBounds');
// 再次确保内部滚动条被禁用
this.setScrollbarCSS(this._seismicWidget);
this.forceDisableInternalScrollbars();
// 再延迟标记初始加载结束
setTimeout(() => {
this._isInitialLoad = false;
console.log('初始加载完成,启用滚动区域更新');
// 最终确认内部滚动条被禁用
this.setScrollbarCSS(this._seismicWidget);
this.forceDisableInternalScrollbars();
}, 1000);
}, 500);
resolve(); resolve();
}); });
}); });
...@@ -1259,6 +2770,11 @@ export default { ...@@ -1259,6 +2770,11 @@ export default {
this.isWidgetReady = true; this.isWidgetReady = true;
console.log('注释工具初始化完成'); console.log('注释工具初始化完成');
// 强制禁用底部widget的内部滚动条
if (this._seismicWidgetBottom) {
this.forceDisableInternalScrollbars();
}
// 恢复保存的标注 // 恢复保存的标注
this.restoreAnnotations(); this.restoreAnnotations();
} catch (error) { } catch (error) {
...@@ -2982,10 +4498,52 @@ export default { ...@@ -2982,10 +4498,52 @@ export default {
} }
return changes; return changes;
},
// 切换内部滚动条同步
toggleInternalScrollbarSync() {
this.internalScrollbarSyncEnabled = !this.internalScrollbarSyncEnabled;
if (this.internalScrollbarSyncEnabled) {
// 启用内部滚动条同步
this.enableInternalScrollbarSync();
this.$message.success('已启用内部滚动条同步 - 两个面板的滚动条将同步移动');
} else {
// 禁用内部滚动条同步,清除监听器
this.clearInternalScrollbarListeners();
// 禁用内部滚动条,使用CSS方法隐藏
this.disableScrollbarTools();
this.$message.info('已禁用内部滚动条同步 - 使用外部滚动条控制');
}
} }
}, },
beforeDestroy() { beforeDestroy() {
// 清理内部滚动条监听器
this.clearInternalScrollbarListeners();
// 清理外层滚动条监听器(GeoToolkit 3.2.80兼容)
this.clearOuterScrollbarListeners();
// 清理DOM滚动条监听器
this.clearDOMScrollbarListeners();
// 停止滚动条同步监控
this.stopScrollbarSyncMonitor();
// 停止外层滚动条同步监控(GeoToolkit 3.2.80兼容)
this.stopOuterScrollbarSyncMonitor();
// 停止滚动条隐藏监控
this.stopScrollbarHideMonitor();
// 停止滚动条同步状态监控
this.stopScrollbarSyncStatusMonitor();
// 停止强力滚动条监控
this.stopAggressiveScrollbarMonitor();
// 清理资源 // 清理资源
if (this.plots) { if (this.plots) {
this.plots.dispose(); this.plots.dispose();
...@@ -3016,6 +4574,9 @@ export default { ...@@ -3016,6 +4574,9 @@ export default {
if (this.timerInterval) { if (this.timerInterval) {
clearTimeout(this.timerInterval); clearTimeout(this.timerInterval);
} }
// 停止滚动条监控
this.stopScrollbarMonitor();
} }
} }
</script> </script>
...@@ -3031,13 +4592,55 @@ export default { ...@@ -3031,13 +4592,55 @@ export default {
.sync-section { .sync-section {
width: 100%; width: 100%;
height: calc(42vh - 20px); height: calc(42vh - 20px);
overflow: auto; overflow-x: auto;
overflow-y: auto;
border: 1px solid #eee; border: 1px solid #eee;
background: #fff; background: #fff;
} }
/* 彻底隐藏 GeoToolkit-js 2.0 内部滚动条 */
.sync-section *[class*="scrollbar"],
.sync-section *[class*="Scrollbar"],
.sync-section *[class*="scroll"],
.sync-section *[class*="Scroll"],
.sync-section *[class*="geotoolkit.controls.tools.scroll"],
.sync-section .gt-scrollbar,
.sync-section .gt-scrollbar-horizontal,
.sync-section .gt-scrollbar-vertical {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
pointer-events: none !important;
}
/* 全局隐藏所有可能的滚动条元素 */
*[class*="scrollbar"],
*[class*="Scrollbar"],
*[class*="scroll"],
*[class*="Scroll"],
*[class*="geotoolkit.controls.tools.scroll"],
.gt-scrollbar,
.gt-scrollbar-horizontal,
.gt-scrollbar-vertical {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
pointer-events: none !important;
}
.zoom-wrapper { .zoom-wrapper {
width: 100%; width: 100%;
display: inline-block;
transform-origin: top left; transform-origin: top left;
} }
...@@ -3045,6 +4648,7 @@ export default { ...@@ -3045,6 +4648,7 @@ export default {
width: 100% !important; width: 100% !important;
height: calc(85vh - 35px) !important; height: calc(85vh - 35px) !important;
margin-top: 20px; margin-top: 20px;
transform-origin: top left;
} }
.toolbar { .toolbar {
...@@ -3482,4 +5086,106 @@ export default { ...@@ -3482,4 +5086,106 @@ export default {
.gt-statusbar-section:last-child { .gt-statusbar-section:last-child {
margin-right: 0 !important; margin-right: 0 !important;
} }
/* 隐藏 GeoToolkit 内部滚动条,仅使用外层滚动 */
.gt-scrollbar,
.gt-scrollbar-horizontal,
.gt-scrollbar-vertical,
[class*="scrollbar"],
[class*="Scrollbar"],
.scrollbar,
.scrollbar-horizontal,
.scrollbar-vertical,
[class*="Scroll"],
[class*="scroll"] {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
overflow: hidden !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
}
/* 隐藏滚动条滑块和轨道 */
.scrollbar-thumb,
.scrollbar-track,
.gt-scrollbar-thumb,
.gt-scrollbar-track,
[class*="thumb"],
[class*="track"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
pointer-events: none !important;
}
/* 隐藏滚动条容器 */
[class*="scroll-container"],
[class*="ScrollContainer"],
.scroll-container {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
pointer-events: none !important;
}
/* 隐藏所有可能的滚动条容器 */
.gt-widget [class*="scrollbar"],
.gt-plot [class*="scrollbar"],
.gt-seismic [class*="scrollbar"],
.gt-widget [class*="Scroll"],
.gt-plot [class*="Scroll"],
.gt-seismic [class*="Scroll"] {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
}
/* 针对GeoToolkit特定滚动条类名的强制隐藏 */
*[class="geotoolkit.controls.tools.scroll.HorizontalScroll"],
*[class="geotoolkit.controls.tools.scroll.VerticalScroll"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
pointer-events: none !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
}
/* 确保外层滚动区域可以接收鼠标事件 */
.sync-section {
pointer-events: auto !important;
}
.sync-section::-webkit-scrollbar {
width: 12px;
height: 12px;
}
.sync-section::-webkit-scrollbar-track {
background: #f1f1f1;
}
.sync-section::-webkit-scrollbar-thumb {
background: #888;
border-radius: 6px;
}
.sync-section::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style> </style>
<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="项目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-input v-model="queryParams.wjmc" placeholder="请输入文件名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="资料类型" prop="zllx">
<el-input v-model="queryParams.zllx" placeholder="请输入资料类型" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="文件路径" prop="wjlj">
<el-input
v-model="queryParams.wjlj"
placeholder="请输入文件路径"
clearable
@keyup.enter.native="handleQuery"
/>
</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 label="备用3" prop="ext3">
<el-input
v-model="queryParams.ext3"
placeholder="请输入备用3"
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-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['yscgWjscqk:wjscqk:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['yscgWjscqk:wjscqk:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['yscgWjscqk:wjscqk:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['yscgWjscqk:wjscqk:export']">导出</el-button>
</el-form-item>
</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-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="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="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">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['yscgWjscqk:wjscqk:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['yscgWjscqk:wjscqk:remove']">删除</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" />
<!-- 添加或修改成果管理对话框 -->
<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-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-input v-model="form.zllx" placeholder="请输入资料类型" />
</el-form-item>
<el-form-item label="文件路径" prop="wjlj">
<el-input v-model="form.wjlj" placeholder="请输入文件路径" />
</el-form-item>
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listWjscqk, getWjscqk, delWjscqk, addWjscqk, updateWjscqk } from "@/api/yscgWjscqk/wjscqk"
export default {
name: "Wjscqk",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 成果管理表格数据
wjscqkList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
xmid: null,
wjmc: null,
zllx: null,
wjlj: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null
},
// 表单参数
form: {},
// 表单校验
rules: {
}
}
},
created() {
this.getList()
},
methods: {
/** 查询成果管理列表 */
getList() {
this.loading = true
listWjscqk(this.queryParams).then(response => {
this.wjscqkList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
xmid: null,
wjmc: null,
zllx: null,
wjlj: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
ext1: null,
ext2: null,
ext3: null
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加成果管理"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getWjscqk(id).then(response => {
this.form = response.data
this.open = true
this.title = "修改成果管理"
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateWjscqk(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addWjscqk(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除成果管理编号为"' + ids + '"的数据项?').then(function () {
return delWjscqk(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
/** 导出按钮操作 */
handleExport() {
this.download('yscgWjscqk/wjscqk/export', {
...this.queryParams
}, `wjscqk_${new Date().getTime()}.xlsx`)
}
}
}
</script>
<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="id">
<el-input
v-model="queryParams.id"
placeholder="请输入主键"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> -->
<el-form-item label="类型名称" prop="lxmc">
<el-input v-model="queryParams.lxmc" placeholder="请输入类型名称" clearable @keyup.enter.native="handleQuery" />
</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 label="备用3" prop="ext3">
<el-input
v-model="queryParams.ext3"
placeholder="请输入备用3"
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-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['yscgZllx:zllx:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['yscgZllx:zllx:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['yscgZllx:zllx:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['yscgZllx:zllx:export']">导出</el-button>
</el-form-item>
</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="zllxList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
<el-table-column label="类型名称" align="center" prop="lxmc" min-width="140" show-overflow-tooltip />
<el-table-column label="备注" align="center" prop="bz" min-width="180" 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="120" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['yscgZllx:zllx:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['yscgZllx:zllx:remove']">删除</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" />
<!-- 添加或修改资料类型对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="类型名称" prop="lxmc">
<el-input v-model="form.lxmc" placeholder="请输入类型名称" />
</el-form-item>
<el-form-item label="备注" prop="bz">
<el-input v-model="form.bz" type="textarea" placeholder="请输入内容" />
</el-form-item>
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listZllx, getZllx, delZllx, addZllx, updateZllx } from "@/api/yscgZllx/zllx"
export default {
name: "Zllx",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 资料类型表格数据
zllxList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
id: null,
lxmc: null,
bz: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null
},
// 表单参数
form: {},
// 表单校验
rules: {
}
}
},
created() {
this.getList()
},
methods: {
/** 查询资料类型列表 */
getList() {
this.loading = true
listZllx(this.queryParams).then(response => {
this.zllxList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
lxmc: null,
bz: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
ext1: null,
ext2: null,
ext3: null
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加资料类型"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getZllx(id).then(response => {
this.form = response.data
this.open = true
this.title = "修改资料类型"
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateZllx(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addZllx(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除资料类型编号为"' + ids + '"的数据项?').then(function () {
return delZllx(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
/** 导出按钮操作 */
handleExport() {
this.download('yscgZllx/zllx/export', {
...this.queryParams
}, `zllx_${new Date().getTime()}.xlsx`)
}
}
}
</script>
<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
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<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="xmzt">
<el-select v-model="queryParams.xmzt" placeholder="请选择项目状态" clearable>
<el-option v-for="dict in dict.type.ys_xmzt" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</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 label="结合单位" prop="jhdw">
<el-input v-model="queryParams.jhdw" placeholder="请输入结合单位" clearable @keyup.enter.native="handleQuery" />
</el-form-item> -->
<!-- <el-form-item label="甲方单位" prop="jfdw">
<el-input v-model="queryParams.jfdw" placeholder="请输入甲方单位" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="x轴最小值" prop="xmin">
<el-input v-model="queryParams.xmin" placeholder="请输入x轴最小值" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="x轴最大值" prop="xmax">
<el-input v-model="queryParams.xmax" placeholder="请输入x轴最大值" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="y轴最小值" prop="ymin">
<el-input v-model="queryParams.ymin" placeholder="请输入y轴最小值" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="y轴最大值" prop="ymax">
<el-input v-model="queryParams.ymax" placeholder="请输入y轴最大值" clearable @keyup.enter.native="handleQuery" />
</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 label="备用3" prop="ext3">
<el-input v-model="queryParams.ext3" placeholder="请输入备用3" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="项目状态" prop="xmzt">
<el-input v-model="queryParams.xmzt" 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-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['ysqqXmxx:ysqqXmxx:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['ysqqXmxx:ysqqXmxx:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['ysqqXmxx:ysqqXmxx:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['ysqqXmxx:ysqqXmxx:export']">导出</el-button>
</el-form-item>
</el-form>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
</el-col>
<el- :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="ysqqXmxxList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
<el-table-column label="项目名称" align="center" prop="xmmc" min-width="100" show-overflow-tooltip />
<el-table-column label="项目日期" align="center" prop="xmrq" min-width="100" show-overflow-tooltip />
<el-table-column label="区块" align="center" prop="qk" min-width="70" show-overflow-tooltip />
<el-table-column label="项目简介" align="center" prop="xmjj" min-width="120" show-overflow-tooltip />
<el-table-column label="结合单位" align="center" prop="jhdw" min-width="90" show-overflow-tooltip />
<el-table-column label="甲方单位" align="center" prop="jfdw" min-width="90" show-overflow-tooltip />
<el-table-column label="项目状态" align="center" prop="xmzt" min-width="90" show-overflow-tooltip>
<template slot-scope="scope">
<dict-tag :options="dict.type.ys_xmzt" :value="scope.row.xmzt" />
</template>
</el-table-column>
<!-- <el-table-column label="x轴最小值" align="center" prop="xmin" min-width="90" show-overflow-tooltip />
<el-table-column label="x轴最大值" align="center" prop="xmax" min-width="90" show-overflow-tooltip />
<el-table-column label="y轴最小值" align="center" prop="ymin" min-width="90" show-overflow-tooltip />
<el-table-column label="y轴最大值" align="center" prop="ymax" min-width="90" 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="项目状态" align="center" prop="xmzt" /> -->
<el-table-column label="操作" min-width="200" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<!-- 未提交状态:显示所有操作按钮 -->
<template v-if="scope.row.xmzt === '未提交'">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['ysqqXmxx:ysqqXmxx:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['ysqqXmxx:ysqqXmxx:remove']">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-upload2" @click="handleSubmit(scope.row)"
v-hasPermi="['ysqqXmxx:ysqqXmxx:submit']">提交</el-button>
<el-button size="mini" type="text" icon="el-icon-odometer" @click="handleJxxInfo(scope.row)">井信息</el-button>
<el-button size="mini" type="text" icon="el-icon-files"
@click="handleSegyInfo(scope.row)">segy信息</el-button>
<el-button size="mini" type="text" icon="el-icon-location"
@click="handleYsgcInfo(scope.row)">导航图</el-button>
</template>
<!-- 待验收状态:显示查看、井信息、segy信息和撤回按钮 -->
<template v-else-if="scope.row.xmzt === '待验收'">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">查看</el-button>
<el-button size="mini" type="text" icon="el-icon-odometer" @click="handleJxxInfo(scope.row)">井信息</el-button>
<el-button size="mini" type="text" icon="el-icon-files"
@click="handleSegyInfo(scope.row)">segy信息</el-button>
<el-button size="mini" type="text" icon="el-icon-back" @click="handleWithdraw(scope.row)"
v-hasPermi="['ysqqXmxx:ysqqXmxx:withdraw']">撤回</el-button>
<el-button size="mini" type="text" icon="el-icon-location"
@click="handleYsgcInfo(scope.row)">导航图</el-button>
</template>
<!-- 已验收和已归档状态:只显示查看按钮 -->
<template v-else>
<el-button size="mini" type="text" icon="el-icon-odometer" @click="handleJxxInfo(scope.row)">井信息</el-button>
<el-button size="mini" type="text" icon="el-icon-files"
@click="handleSegyInfo(scope.row)">segy信息</el-button>
<el-button size="mini" type="text" icon="el-icon-location"
@click="handleYsgcInfo(scope.row)">导航图</el-button>
</template>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改验收前期-项目信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="60%" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="98px">
<el-row>
<el-col :span="12">
<el-form-item label="项目名称" prop="xmmc">
<el-input v-model="form.xmmc" placeholder="请输入项目名称" :disabled="isReadOnly" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="区块" prop="qk">
<el-input v-model="form.qk" placeholder="请输入区块" :disabled="isReadOnly" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="项目日期" prop="xmrq">
<el-date-picker clearable v-model="form.xmrq" type="date" value-format="yyyy-MM-dd" placeholder="请选择时间"
style="width: 100%;" :disabled="isReadOnly">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结合单位" prop="jhdw">
<el-input v-model="form.jhdw" placeholder="请输入结合单位" :disabled="isReadOnly" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="甲方单位" prop="jfdw">
<el-input v-model="form.jfdw" placeholder="请输入甲方单位" :disabled="isReadOnly" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目简介" prop="xmjj">
<el-input v-model="form.xmjj" type="textarea" placeholder="请输入内容" :disabled="isReadOnly" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="x轴最小值" prop="xmin">
<el-input v-model="form.xmin" placeholder="请输入x轴最小值" :disabled="isReadOnly" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="x轴最大值" prop="xmax">
<el-input v-model="form.xmax" placeholder="请输入x轴最大值" :disabled="isReadOnly" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="y轴最小值" prop="ymin">
<el-input v-model="form.ymin" placeholder="请输入y轴最小值" :disabled="isReadOnly" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="y轴最大值" prop="ymax">
<el-input v-model="form.ymax" placeholder="请输入y轴最大值" :disabled="isReadOnly" />
</el-form-item>
</el-col>
</el-row>
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
<!-- <el-form-item label="项目状态" prop="xmzt">
<el-select v-model="form.xmzt" placeholder="请选择项目状态" clearable>
<el-option v-for="dict in dict.type.ys_xmzt" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button v-if="!isReadOnly" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">{{ isReadOnly ? '关 闭' : '取 消' }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listYsqqXmxx, getYsqqXmxx, delYsqqXmxx, addYsqqXmxx, updateYsqqXmxx, startConvert, withdraw } from "@/api/ysqqXmxx/ysqqXmxx"
export default {
name: "YsqqXmxx",
dicts: ['ys_xmzt'],
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 验收前期-项目信息表格数据
ysqqXmxxList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
id: null,
xmmc: null,
qk: null,
xmjj: null,
jhdw: null,
jfdw: null,
xmin: null,
xmax: null,
ymin: null,
ymax: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null,
xmzt: null
},
// 表单参数
form: {},
// 表单校验
rules: {
xmmc: [
{ required: true, message: "项目名称不能为空", trigger: "blur" }
],
xmrq: [
{ required: true, message: "项目日期不能为空", trigger: "blur" }
],
xmin: [
{ required: true, message: "x轴最小值不能为空", trigger: "blur" }
],
xmax: [
{ required: true, message: "x轴最大值不能为空", trigger: "blur" }
],
ymin: [
{ required: true, message: "y轴最小值不能为空", trigger: "blur" }
],
ymax: [
{ required: true, message: "y轴最大值不能为空", trigger: "blur" }
],
},
// 是否只读模式
isReadOnly: false
}
},
created() {
this.getList()
},
methods: {
/** 查询验收前期-项目信息列表 */
getList() {
this.loading = true
listYsqqXmxx(this.queryParams).then(response => {
this.ysqqXmxxList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
xmmc: null,
qk: null,
xmjj: null,
jhdw: null,
jfdw: null,
xmin: null,
xmax: null,
ymin: null,
ymax: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
ext1: null,
ext2: null,
ext3: null,
xmzt: '未提交' // 新增时默认为未提交状态
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加验收前期-项目信息"
// 设置为编辑模式
this.isReadOnly = false
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getYsqqXmxx(id).then(response => {
this.form = response.data
this.open = true
this.title = "修改验收前期-项目信息"
// 设置为编辑模式
this.isReadOnly = false
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateYsqqXmxx(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addYsqqXmxx(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除验收前期-项目信息编号为"' + ids + '"的数据项?').then(function () {
return delYsqqXmxx(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
/** 导出按钮操作 */
handleExport() {
this.download('ysqqXmxx/ysqqXmxx/export', {
...this.queryParams
}, `ysqqXmxx_${new Date().getTime()}.xlsx`)
},
/** 井信息按钮操作 */
handleJxxInfo(row) {
this.$router.push({
path: '/ysqqXmxxJxx/jxx/index',
query: {
zbid: row.id,
status: row.xmzt // 传递项目状态
}
})
},
/** segy信息按钮操作 */
handleSegyInfo(row) {
this.$router.push({
path: '/ysqqXmxxSegy/segy/index',
query: {
zbid: row.id,
status: row.xmzt // 传递项目状态
}
})
},
/** 导航图按钮操作 */
handleYsgcInfo(row) {
this.$router.push({
path: '/ysqqXmxx/ysgc/index',
query: {
zbid: row.id,
status: row.xmzt // 传递项目状态
}
})
},
/** 提交按钮操作 */
handleSubmit(row) {
this.$modal.confirm('是否确认提交项目"' + row.xmmc + '"?').then(() => {
return startConvert(row.id)
}).then(() => {
this.getList()
this.$modal.msgSuccess("提交成功")
}).catch(() => { })
},
/** 查看按钮操作 */
handleView(row) {
this.reset()
const id = row.id || this.ids
getYsqqXmxx(id).then(response => {
this.form = response.data
this.open = true
this.title = "查看验收前期-项目信息"
// 设置为只读模式
this.isReadOnly = true
})
},
/** 撤回按钮操作 */
handleWithdraw(row) {
this.$modal.confirm('是否确认撤回项目"' + row.xmmc + '"?').then(() => {
return withdraw(row.id)
}).then(() => {
this.getList()
this.$modal.msgSuccess("撤回成功")
}).catch(() => { })
}
}
}
</script>
<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="id">
<el-input
v-model="queryParams.id"
placeholder="请输入主键"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="主表id" prop="zbid">
<el-input
v-model="queryParams.zbid"
placeholder="请输入主表id"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> -->
<el-form-item label="井号" prop="jh">
<el-input v-model="queryParams.jh" placeholder="请输入井号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="x轴坐标" prop="x">
<el-input v-model="queryParams.x" placeholder="请输入x轴坐标" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="y轴坐标" prop="y">
<el-input v-model="queryParams.y" placeholder="请输入y轴坐标" clearable @keyup.enter.native="handleQuery" />
</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 label="备用3" prop="ext3">
<el-input v-model="queryParams.ext3" placeholder="请输入备用3" 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-button v-if="projectStatus === '未提交'" type="primary" plain icon="el-icon-plus" size="mini"
@click="handleAdd" v-hasPermi="['ysqqXmxxJxx:jxx:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single || projectStatus !== '未提交'"
@click="handleUpdate" v-hasPermi="['ysqqXmxxJxx:jxx:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple || projectStatus !== '未提交'"
@click="handleDelete" v-hasPermi="['ysqqXmxxJxx:jxx:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['ysqqXmxxJxx:jxx:export']">导出</el-button>
</el-form-item>
</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="jxxList" @selection-change="handleSelectionChange">
<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="zbid" /> -->
<el-table-column label="井号" align="center" prop="jh" min-width="150" show-overflow-tooltip />
<el-table-column label="x轴坐标" align="center" prop="x" min-width="150" show-overflow-tooltip />
<el-table-column label="y轴坐标" align="center" prop="y" min-width="150" 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="100" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<!-- 未提交状态:显示修改和删除按钮 -->
<template v-if="projectStatus === '未提交'">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['ysqqXmxxJxx:jxx:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['ysqqXmxxJxx:jxx:remove']">删除</el-button>
</template>
<!-- 其他状态(待验收、已验收、已归档):只显示查看按钮 -->
<template v-else>
<el-button size="mini" type="text" icon="el-icon-view" @click="handleUpdate(scope.row)">查看</el-button>
</template>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改验收前期-项目信息-井信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="主表id" prop="zbid">
<el-input v-model="form.zbid" placeholder="请输入主表id" />
</el-form-item> -->
<el-form-item label="井号" prop="jh">
<el-input v-model="form.jh" placeholder="请输入井号" :disabled="isReadOnly" />
</el-form-item>
<el-form-item label="x轴坐标" prop="x">
<el-input v-model="form.x" placeholder="请输入x轴坐标" :disabled="isReadOnly" />
</el-form-item>
<el-form-item label="y轴坐标" prop="y">
<el-input v-model="form.y" placeholder="请输入y轴坐标" :disabled="isReadOnly" />
</el-form-item>
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button v-if="!isReadOnly" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel">{{ isReadOnly ? '关 闭' : '取 消' }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listJxx, getJxx, delJxx, addJxx, updateJxx } from "@/api/ysqqXmxxJxx/jxx"
export default {
name: "Jxx",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 验收前期-项目信息-井信息表格数据
jxxList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
id: null,
zbid: null,
jh: null,
x: null,
y: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null
},
// 表单参数
form: {},
// 表单校验
rules: {
},
// 项目状态
projectStatus: null,
// 是否只读模式
isReadOnly: false
}
},
created() {
// 获取路由参数中的zbid和项目状态
if (this.$route.query.zbid) {
this.queryParams.zbid = this.$route.query.zbid
}
if (this.$route.query.status) {
this.projectStatus = this.$route.query.status
}
this.getList()
},
methods: {
/** 查询验收前期-项目信息-井信息列表 */
getList() {
this.loading = true
listJxx(this.queryParams).then(response => {
this.jxxList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
zbid: this.$route.query.zbid || null,
jh: null,
x: null,
y: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
ext1: null,
ext2: null,
ext3: null
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加验收前期-项目信息-井信息"
},
/** 修改/查看按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getJxx(id).then(response => {
this.form = response.data
this.open = true
// 根据项目状态决定是查看还是修改
if (this.projectStatus === '未提交') {
this.title = "修改验收前期-项目信息-井信息"
this.isReadOnly = false
} else {
this.title = "查看验收前期-项目信息-井信息"
this.isReadOnly = true
}
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateJxx(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addJxx(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除验收前期-项目信息-井信息编号为"' + ids + '"的数据项?').then(function () {
return delJxx(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
/** 导出按钮操作 */
handleExport() {
this.download('ysqqXmxxJxx/jxx/export', {
...this.queryParams
}, `jxx_${new Date().getTime()}.xlsx`)
}
}
}
</script>
<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="id">
<el-input
v-model="queryParams.id"
placeholder="请输入主键"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="主表id" prop="zbid">
<el-input
v-model="queryParams.zbid"
placeholder="请输入主表id"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> -->
<!-- <el-form-item label="旧版segy路径" prop="jbsegy">
<el-input
v-model="queryParams.jbsegy"
placeholder="请输入旧版segy路径"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="新版segy路径" prop="xbsegy">
<el-input
v-model="queryParams.xbsegy"
placeholder="请输入新版segy路径"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item> -->
<el-form-item label="坐标信息" prop="x">
<el-input v-model="queryParams.x" placeholder="请输入坐标信息" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="y轴坐标" prop="y">
<el-input v-model="queryParams.y" placeholder="请输入y轴坐标" clearable @keyup.enter.native="handleQuery" />
</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 label="备用3" prop="ext3">
<el-input v-model="queryParams.ext3" placeholder="请输入备用3" 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-button v-if="projectStatus === '未提交'" type="primary" plain icon="el-icon-plus" size="mini"
@click="handleAdd" v-hasPermi="['ysqqXmxxSegy:segy:add']">新增</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single || projectStatus !== '未提交'"
@click="handleUpdate" v-hasPermi="['ysqqXmxxSegy:segy:edit']">修改</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple || projectStatus !== '未提交'"
@click="handleDelete" v-hasPermi="['ysqqXmxxSegy:segy:remove']">删除</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['ysqqXmxxSegy:segy:export']">导出</el-button>
</el-form-item>
</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="segyList" @selection-change="handleSelectionChange">
<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="zbid" /> -->
<el-table-column label="旧版segy路径" align="center" prop="jbsegyName" min-width="170" show-overflow-tooltip />
<el-table-column label="新版segy路径" align="center" prop="xbsegyName" min-width="170" show-overflow-tooltip />
<el-table-column label="坐标信息" align="center" prop="x" min-width="140" show-overflow-tooltip />
<!-- <el-table-column label="y轴坐标" align="center" prop="y" min-width="140" 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="100" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<!-- 未提交状态:显示修改和删除按钮 -->
<template v-if="projectStatus === '未提交'">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['ysqqXmxxSegy:segy:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['ysqqXmxxSegy:segy:remove']">删除</el-button>
</template>
<!-- 其他状态(待验收、已验收、已归档):只显示查看按钮 -->
<template v-else>
<el-button size="mini" type="text" icon="el-icon-view" @click="handleUpdate(scope.row)">查看</el-button>
</template>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改segy信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="110px">
<!-- <el-form-item label="主表id" prop="zbid">
<el-input v-model="form.zbid" placeholder="请输入主表id" />
</el-form-item> -->
<el-form-item label="旧版segy文件" prop="jbsegy">
<el-upload ref="jbsegyUpload" :limit="1" :on-exceed="handleExceed" :before-upload="beforeUpload"
:on-success="(response, file) => handleUploadSuccess(response, file, 'jbsegy')"
:on-remove="() => handleRemove('jbsegy')" :on-error="handleUploadError" :file-list="jbsegyFileList"
:action="uploadUrl" :headers="uploadHeaders" accept=".segy,.sgy" drag :disabled="isReadOnly">
<i class="el-icon-upload"></i>
<div class="el-upload__text">segy文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传segysgy文件</div>
</el-upload>
</el-form-item>
<el-form-item label="新版segy文件" prop="xbsegy">
<el-upload ref="xbsegyUpload" :limit="1" :on-exceed="handleExceed" :before-upload="beforeUpload"
:on-success="(response, file) => handleUploadSuccess(response, file, 'xbsegy')"
:on-remove="() => handleRemove('xbsegy')" :on-error="handleUploadError" :file-list="xbsegyFileList"
:action="uploadUrl" :headers="uploadHeaders" accept=".segy,.sgy" drag :disabled="isReadOnly">
<i class="el-icon-upload"></i>
<div class="el-upload__text">segy文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传segysgy文件</div>
</el-upload>
</el-form-item>
<el-form-item label="坐标信息" prop="x" v-if="form.id">
<el-input v-model="form.x" placeholder="请输入坐标信息" :disabled="isReadOnly" />
</el-form-item>
<!-- <el-form-item label="y轴坐标" prop="y">
<el-input v-model="form.y" placeholder="请输入y轴坐标" :disabled="isReadOnly" />
</el-form-item> -->
<!-- <el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-date-picker clearable v-model="form.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="form.ext1" placeholder="请输入备用1" />
</el-form-item>
<el-form-item label="备用2" prop="ext2">
<el-input v-model="form.ext2" placeholder="请输入备用2" />
</el-form-item>
<el-form-item label="备用3" prop="ext3">
<el-input v-model="form.ext3" placeholder="请输入备用3" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button v-if="!isReadOnly" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel">{{ isReadOnly ? '关 闭' : '取 消' }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listSegy, getSegy, delSegy, addSegy, updateSegy } from "@/api/ysqqXmxxSegy/segy"
import { getToken } from "@/utils/auth"
export default {
name: "Segy",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// segy信息表格数据
segyList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
id: null,
zbid: null,
jbsegy: null,
xbsegy: null,
x: null,
y: null,
createdBy: null,
createdTime: null,
ext1: null,
ext2: null,
ext3: null
},
// 表单参数
form: {},
// 表单校验
rules: {
jbsegy: [
{ required: true, message: "旧版segy文件不能为空", trigger: "blur" }
]
,
xbsegy: [
{ required: true, message: "新版segy文件不能为空", trigger: "blur" }
]
},
// 文件列表
jbsegyFileList: [],
xbsegyFileList: [],
// 上传配置
uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload",
uploadHeaders: {
Authorization: "Bearer " + getToken(),
},
// 项目状态
projectStatus: null,
// 是否只读模式
isReadOnly: false
}
},
created() {
// 获取路由参数中的zbid和项目状态
if (this.$route.query.zbid) {
this.queryParams.zbid = this.$route.query.zbid
}
if (this.$route.query.status) {
this.projectStatus = this.$route.query.status
}
this.getList()
},
methods: {
/** 查询segy信息列表 */
getList() {
this.loading = true
listSegy(this.queryParams).then(response => {
this.segyList = response.rows
this.total = response.total
this.loading = false
})
},
// 取消按钮
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.form = {
id: null,
zbid: this.$route.query.zbid || null,
jbsegy: null,
xbsegy: null,
jbsegyName: null,
xbsegyName: null,
x: null,
y: null,
createdBy: null,
createdTime: null,
updateBy: null,
updateTime: null,
ext1: null,
ext2: null,
ext3: null
}
// 清空文件列表
this.jbsegyFileList = []
this.xbsegyFileList = []
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加segy信息"
},
/** 修改/查看按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getSegy(id).then(response => {
this.form = response.data
// 设置文件列表,显示已上传的文件
if (this.form.jbsegy) {
this.jbsegyFileList = [{
name: this.form.jbsegyName || this.getFileNameFromPath(this.form.jbsegy),
url: this.form.jbsegy,
status: 'success'
}]
}
if (this.form.xbsegy) {
this.xbsegyFileList = [{
name: this.form.xbsegyName || this.getFileNameFromPath(this.form.xbsegy),
url: this.form.xbsegy,
status: 'success'
}]
}
this.open = true
// 根据项目状态决定是查看还是修改
if (this.projectStatus === '未提交') {
this.title = "修改segy信息"
this.isReadOnly = false
} else {
this.title = "查看segy信息"
this.isReadOnly = true
}
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateSegy(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addSegy(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm('是否确认删除segy信息编号为"' + ids + '"的数据项?').then(function () {
return delSegy(ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => { })
},
/** 导出按钮操作 */
handleExport() {
this.download('ysqqXmxxSegy/segy/export', {
...this.queryParams
}, `segy_${new Date().getTime()}.xlsx`)
},
/** 文件上传前检查 */
beforeUpload(file) {
const fileName = file.name.toLowerCase()
const isSegy = fileName.endsWith('.segy') || fileName.endsWith('.sgy')
if (!isSegy) {
this.$modal.msgError('只能上传segy或sgy格式的文件!')
return false
}
// 限制文件大小不超过 100MB
const maxSizeMB = 100
const isLt = file.size / 1024 / 1024 <= maxSizeMB
if (!isLt) {
this.$modal.msgError(`上传文件大小不能超过 ${maxSizeMB} MB!`)
return false
}
return true
},
/** 文件上传成功回调 */
handleUploadSuccess(response, file, type) {
if (response.code === 200) {
// 将服务器返回的文件名保存到form中
this.form[type] = response.fileName
// 根据上传类型,将原始文件名保存到对应的Name字段
if (type === 'jbsegy') {
this.form.jbsegyName = file.name // 保存原始文件名
// 更新文件列表显示
this.jbsegyFileList = [{
name: file.name,
url: response.fileName,
status: 'success'
}]
} else if (type === 'xbsegy') {
this.form.xbsegyName = file.name // 保存原始文件名
// 更新文件列表显示
this.xbsegyFileList = [{
name: file.name,
url: response.fileName,
status: 'success'
}]
}
this.$modal.msgSuccess('文件上传成功')
} else {
this.$modal.msgError(response.msg || '文件上传失败')
// 移除失败的文件
if (type === 'jbsegy') {
this.$refs.jbsegyUpload.clearFiles()
} else if (type === 'xbsegy') {
this.$refs.xbsegyUpload.clearFiles()
}
}
},
/** 文件移除回调 */
handleRemove(type) {
this.form[type] = null
if (type === 'jbsegy') {
this.form.jbsegyName = null // 清空原始文件名
this.jbsegyFileList = []
} else if (type === 'xbsegy') {
this.form.xbsegyName = null // 清空原始文件名
this.xbsegyFileList = []
}
},
/** 文件数量超出限制 */
handleExceed(files, fileList) {
this.$modal.msgWarning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
/** 文件上传错误处理 */
handleUploadError(err, file, fileList) {
this.$modal.msgError('文件上传失败,请重试')
console.error('上传错误:', err)
},
/** 从文件路径中提取文件名 */
getFileNameFromPath(filePath) {
if (!filePath) return ''
// 从完整路径中提取文件名
const fileName = filePath.split('/').pop()
return fileName || filePath
}
}
}
</script>
...@@ -29,7 +29,7 @@ module.exports = { ...@@ -29,7 +29,7 @@ module.exports = {
lintOnSave: process.env.NODE_ENV === "development", lintOnSave: process.env.NODE_ENV === "development",
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
productionSourceMap: false, productionSourceMap: false,
transpileDependencies: ["quill"], transpileDependencies: ["quill", "@jsonforms/core", "jsonforms-vue"],
// webpack-dev-server 相关配置 // webpack-dev-server 相关配置
devServer: { devServer: {
host: "0.0.0.0", host: "0.0.0.0",
...@@ -38,8 +38,9 @@ module.exports = { ...@@ -38,8 +38,9 @@ module.exports = {
proxy: { proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: { [process.env.VUE_APP_BASE_API]: {
// target: `http://192.168.31.108:8999`, //井测试 // target: `http://192.168.31.108:8999`,
target: `http://192.168.31.190:8999`, //井测试 target: `http://192.168.110.69:8999`,
// target: `http://192.168.31.12:8999`,
changeOrigin: true, changeOrigin: true,
pathRewrite: { pathRewrite: {
["^" + process.env.VUE_APP_BASE_API]: "", ["^" + process.env.VUE_APP_BASE_API]: "",
......
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