添加地图点击基地,数据填报bug修改

This commit is contained in:
扈兆增 2026-05-11 17:45:09 +08:00
parent 2eb818b61d
commit 7ab91f158e
12 changed files with 51718 additions and 51262 deletions

View File

@ -22,7 +22,9 @@
<a-button v-else type="primary" size="small" class="mr-2" @click="saveBtn">
保存信息
</a-button>
<a-button type="primary" size="small"> 修改记录 </a-button>
<a-button type="primary" size="small" @click="recordBtn">
修改记录
</a-button>
</div>
</div>
<div class="col-left" v-if="item.visible">
@ -69,6 +71,15 @@
</div>
</a-col>
</a-row>
<a-modal
v-model:open="visible"
title="修改记录"
:footer="null"
width="900px"
:zIndex="2000"
>
123
</a-modal>
</div>
</a-spin>
</template>
@ -87,7 +98,7 @@ const props = defineProps({
default: "",
},
});
const value1 = ref(dayjs("2009-04-01"));
const visible = ref(false);
const loading = ref(false);
const tabledata = ref([]);
console.log(BasicColumns);
@ -114,6 +125,9 @@ const saveBtn = () => {
isEdit.value = false;
console.log(tabledata.value);
};
const recordBtn = () => {
visible.value = true;
};
onMounted(() => {
loading.value = true;
const data = {

View File

@ -28,8 +28,8 @@
<a-button type="primary" :disabled="isEngConfig">
<i class="icon iconfont icon-topic mr-[5px]"></i>
电站专题
</a-button
></a-tooltip>
</a-button></a-tooltip
>
</template>
</a-tabs>
</a-modal>
@ -68,12 +68,11 @@ const props = defineProps<{
// 'update:activeKey' v-model:active-key
const emit = defineEmits<{
(e: "update:visible", value: boolean): void;
(e: "update:activeKey", key: string): void;
(e: "change", key: string): void;
}>();
// activeKey
const currentActiveKey = ref<string>(props.activeKey || "");
const currentActiveKey = ref<string>("");
// activeKey
watch(
@ -89,6 +88,8 @@ watch(
() => modelStore.params,
(newVal) => {
tabsConfig.value = handleTabs(newVal);
let value = tabsConfig.value.find((item: any) => item.default);
currentActiveKey.value = value?.key;
},
{ deep: true, immediate: true }
);
@ -96,7 +97,6 @@ watch(
const onTabChange = (key: string) => {
currentActiveKey.value = key;
// activeKey ( v-model)
emit("update:activeKey", key);
// ()
emit("change", key);
};

View File

@ -17,7 +17,8 @@ const ENGTabs: Array<any> = [
name: '基础信息',
key: 'basicInfo',
type: 'basic',
url: '/bbi/siteBipc/getSiteBasicInfo'
url: '/bbi/siteBipc/getSiteBasicInfo',
default: true // 默认显示
},
{
name: '阶段属性',

View File

@ -41,6 +41,9 @@ import {
} from "./gisUtils";
import { MapClass } from "./map.class";
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
const JidiSelectEventStore = useJidiSelectEventStore();
const mapStore: any = useMapStore();
const route = useRoute();
// const router = useRouter();
@ -56135,30 +56138,6 @@ const fetchPointData = _.debounce(async () => {
matrixIds_index: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
tileMatrixSetID: "EPSG:3857_qgc_sx_gjjdx_arcgistiles_l13",
});
// setTimeout(() => {
//
// mapClass.addBaseDataLayer({
// "id": "hydropBase",
// "key": "hydropBase",
// "urlType": "gisurl",
// "url": "https://211.99.26.225:18085/geoserver/gwc/service/tms/1.0.0/qgc%3AstationEra1117@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf",
// "geojson_url": "https://211.99.26.225:18085/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEra1117&maxFeatures=50&outputFormat=application/json&token=bearer a9a0f227-1df3-4e68-b380-2eca5bb49bd1",
// "url_3d": "https://211.99.26.225:18085/geoserver/qgc/wms",
// "_layer": "stationEra1117",
// "layers": "qgc:stationEra1117",
// "rasteropacity": 0.5,
// "visible": true,
// "minZoom": 0,
// "maxZoom": 20,
// "type": "vector",
// "layerType": "line",
// "paint": {
// "line-color": "#C5C6F3",
// "line-width": 1,
// "line-opacity": 1
// }
// })
// }, 2000);
//
// mapClass.addBaseDataLayer(
@ -56358,6 +56337,7 @@ const handleMapController = (e: any) => {
break;
}
};
watch(
() => mapIsInited.value,
(newVal) => {
@ -56368,6 +56348,42 @@ watch(
}
}
);
//
watch(
() => JidiSelectEventStore.selectedItem,
(newVal) => {
console.log(newVal);
if (newVal) {
// if (newVal.wbsCode == "all") {
// } else {
// mapClass.addBaseDataLayer({
// id: "hydropBase",
// key: "hydropBase",
// urlType: "gisurl",
// url:
// "https://211.99.26.225:18085/geoserver/gwc/service/tms/1.0.0/qgc%3AstationEra1117@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf",
// geojson_url:
// "https://211.99.26.225:18085/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEra1117&maxFeatures=50&outputFormat=application/json&token=bearer a9a0f227-1df3-4e68-b380-2eca5bb49bd1",
// url_3d: "https://211.99.26.225:18085/geoserver/qgc/wms",
// _layer: "stationEra1117",
// layers: "qgc:stationEra1117",
// rasteropacity: 0.5,
// visible: true,
// minZoom: 0,
// maxZoom: 20,
// type: "vector",
// layerType: "line",
// paint: {
// "line-color": "#C5C6F3",
// "line-width": 1,
// "line-opacity": 1,
// },
// });
// }
}
},
{ deep: true }
);
onMounted(() => {
init();
@ -56385,6 +56401,8 @@ onUnmounted(() => {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
visibility: visible;
}
#mapContainer {

View File

@ -67,7 +67,9 @@ export class MapOl implements MapInterface {
private pointLayerRegistry: Map<string, VectorLayer> = new Map();
geoJsonData: any = null;
geoJsonData1: any = null;
// ✅ 新增:声明用于存储 mask 事件监听器的引用,以便后续移除
private _maskPrerender: any = null;
private _maskPostrender: any = null;
// private BASEID: string = '01';
constructor() {
this.loadGeoJsonData();
@ -75,18 +77,31 @@ export class MapOl implements MapInterface {
}
private async loadGeoJsonData(): Promise<void> {
try {
const response = await fetch('/data/geoJson.json')
this.geoJsonData = await response.json()
const response = await fetch('/data/geoJson.json');
this.geoJsonData = await response.json();
} catch (error) {
console.error('配置加载失败:', error)
console.error('配置加载失败:', error);
}
}
private async loadGeoJsonData1(): Promise<void> {
try {
const response = await fetch('/data/geoJson1.json')
this.geoJsonData1 = await response.json()
const response = await fetch('/data/geoJson1.json');
let res = await response.json();
let json1 = {
crs: res.crs,
features: [],
totalFeatures: res.totalFeatures,
type: res.type
};
for (let i = 0; i < res.features.length; i++) {
if (res.features[i].properties.BASEID === '12') {
json1.features.push(res.features[i]);
}
}
console.log(json1);
this.geoJsonData1 = json1;
} catch (error) {
console.error('配置加载失败:', error)
console.error('配置加载失败:', error);
}
}
//地图初始化
@ -238,14 +253,7 @@ export class MapOl implements MapInterface {
const features: Feature[] = [];
dataArray.forEach((item: any) => {
const {
lgtd,
lttd,
stnm,
iconCode,
titleName,
ennm
} = item;
const { lgtd, lttd, stnm, iconCode, titleName, ennm } = item;
if (lgtd == null || lttd == null) {
return;
@ -464,23 +472,25 @@ export class MapOl implements MapInterface {
})
}),
// ✅ 3. 调整 zIndex确保在底图之上可见
zIndex: 100,
zIndex: 101,
visible: true
});
// 监听数据加载完成事件
// vectorSource.on('featuresloadend', () => {
// // 获取所有加载的要素
// const features = vectorSource.getFeatures();
// const feature = features[0];
// const geometry = feature.getGeometry();
// console.log(geometry)
// // this.addClipToRasterLayer(this.layerRegistry.get(this.REGISTRY_KEY), geometry);
// // this.applyMapMask(geometry);
// });
vectorSource.on('featuresloadend', () => {
// 获取所有加载的要素
const features = vectorSource.getFeatures();
const feature = features[0];
const geometry = feature.getGeometry();
console.log(geometry);
// this.addClipToRasterLayer(this.layerRegistry.get(this.REGISTRY_KEY), geometry);
// this.applyMapMask(geometry);
});
// 4. 注册与添加
this.layerRegistry.set(layer.key, vectorLayer);
this.map.addLayer(vectorLayer);
// this.map.addLayer(vectorLayer);
layer._layer = vectorLayer;
const targetBaseLayer = this.layerRegistry.get(this.REGISTRY_KEY);
this.applyMapMask(targetBaseLayer as TileLayer, this.geoJsonData1);
console.log(`矢量图层 [${layer.key}] 已加载: ${layer.url}`);
}
@ -570,6 +580,24 @@ export class MapOl implements MapInterface {
// }
// });
// }
// 在 addBaseDataLayer 方法的 vector 分支末尾,或者专门提供一个方法来激活遮罩
enableNortheastMask(): void {
// 1. 获取全量底图图层
const baseLayer = this.layerRegistry.get(this.REGISTRY_KEY);
// 2. 检查是否已加载东北边界数据
if (!this.geoJsonData1) {
console.warn('东北边界数据尚未加载');
return;
}
if (baseLayer && baseLayer instanceof TileLayer) {
console.log('正在应用东北区域遮罩...');
this.applyMapMask(baseLayer, this.geoJsonData1);
} else {
console.warn('未找到全量底图图层或图层类型错误');
}
}
/**
*
* @param regionId ID ( "hebei", "13", "01" Key )
@ -1188,7 +1216,156 @@ export class MapOl implements MapInterface {
container.appendChild(closeBtn);
this.map.addOverlay(overlay);
}
/**
*
* @param rasterLayer (TileLayer)
* @param clipGeoJson GeoJSON
*/
private applyMapMask(rasterLayer: TileLayer, clipGeoJson: any): void {
if (!rasterLayer || !clipGeoJson) return;
// 1. 解析 GeoJSON
const features = new GeoJSON().readFeatures(clipGeoJson, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
});
// if (!features || features.length === 0) {
// console.warn('裁切数据为空');
// return;
// }
// // ✅ 调试:添加绿线图层
// const debugVectorSource = new VectorSource({ features: features });
// let debugLayer = this.map!.getLayers()
// .getArray()
// .find((l: any) => l.get('isDebugMask'));
// if (debugLayer) {
// this.map!.removeLayer(debugLayer);
// }
// debugLayer = new VectorLayer({
// source: debugVectorSource,
// style: new Style({
// stroke: new Stroke({ color: '#00FF00', width: 2 }),
// fill: new Fill({ color: 'rgba(0, 255, 0, 0.1)' })
// }),
// zIndex: 9999,
// visible: true
// });
// debugLayer.set('isDebugMask', true);
// this.map!.addLayer(debugLayer);
// 移除旧监听器
if (this._maskPrerender) {
rasterLayer.un('prerender', this._maskPrerender);
}
if (this._maskPostrender) {
rasterLayer.un('postrender', this._maskPostrender);
}
const maskPrerender = (event: any) => {
const context = event.context;
if (!context || !this.map) return;
const frameState = event.frameState;
if (!frameState) return;
context.save();
context.setTransform(1, 0, 0, 1, 0, 0);
context.beginPath();
let hasPath = false;
for (const feature of features) {
const geom: any = feature.getGeometry();
if (!geom) continue;
const type = geom.getType();
if (type === 'Polygon') {
const rings = geom.getCoordinates() as number[][][];
for (const ring of rings) {
// ✅ 传递 frameState 给 drawRing
this.drawRing(context, ring, frameState);
hasPath = true;
}
} else if (type === 'MultiPolygon') {
const polygons = geom.getCoordinates() as number[][][][];
for (const polygonRings of polygons) {
for (const ring of polygonRings) {
// ✅ 传递 frameState 给 drawRing
this.drawRing(context, ring, frameState);
hasPath = true;
}
}
}
}
if (hasPath) {
context.strokeStyle = 'red';
context.lineWidth = 2;
context.stroke();
context.fillStyle = 'rgba(255, 255, 0, 0.2)';
context.fill();
// context.clip();
} else {
}
context.restore();
};
const maskPostrender = (event: any) => {
if (event.context) {
event.context.restore();
}
};
this._maskPrerender = maskPrerender;
this._maskPostrender = maskPostrender;
rasterLayer.on('prerender', this._maskPrerender);
rasterLayer.on('postrender', this._maskPostrender);
rasterLayer.changed();
}
private drawRing(
context: CanvasRenderingContext2D,
ring: number[][],
frameState: any
) {
if (!ring || ring.length === 0) return;
// ✅ 关键:获取当前 Canvas 的像素比(高清屏通常为 2
// frameState.pixelRatio 是 OL 内部使用的像素比
const pixelRatio = frameState.pixelRatio || window.devicePixelRatio || 1;
for (let i = 0; i < ring.length; i++) {
const coord = ring[i];
if (!this.map || !Array.isArray(coord) || typeof coord[0] !== 'number')
continue;
// ✅ 1. 获取相对于地图容器的 CSS 像素坐标
const cssPixel = this.map.getPixelFromCoordinate(
coord as [number, number]
);
if (!cssPixel) continue;
// ✅ 2. 转换为 Canvas 内部物理像素坐标
// 因为我们在 maskPrerender 中执行了 context.setTransform(1, 0, 0, 1, 0, 0);
// 此时 Canvas 的原点是左上角,单位是物理像素。
// 而 getPixelFromCoordinate 返回的是 CSS 像素。
// 所以必须乘以 pixelRatio。
const canvasX = cssPixel[0] * pixelRatio;
const canvasY = cssPixel[1] * pixelRatio;
if (i === 0) {
context.moveTo(canvasX, canvasY);
} else {
context.lineTo(canvasX, canvasY);
}
}
context.closePath();
}
/**
* ()
*/
@ -1219,9 +1396,11 @@ export class MapOl implements MapInterface {
// 1. 清除量算相关资源
this.removeQueryLayer();
this._maskPrerender = null;
this._maskPostrender = null;
// 2. 清除所有通过 layerRegistry 管理的图层
if (this.layerRegistry) {
this.layerRegistry.forEach((layer) => {
this.layerRegistry.forEach(layer => {
if (this.map && this.map.getLayers().getArray().includes(layer)) {
this.map.removeLayer(layer);
}
@ -1231,7 +1410,7 @@ export class MapOl implements MapInterface {
// ✅ 3. 清除点图层 Registry
if (this.pointLayerRegistry) {
this.pointLayerRegistry.forEach((layer) => {
this.pointLayerRegistry.forEach(layer => {
if (this.map && this.map.getLayers().getArray().includes(layer)) {
this.map.removeLayer(layer);
}

View File

@ -4,7 +4,7 @@ import { useTagsViewStore } from "@/store/modules/tagsView";
import { useRoute } from "vue-router";
import MapModal from "@/components/MapModal/index.vue";
import { useModelStore } from "@/store/modules/model";
// import GisView from "@/components/gis/GisView.vue";
import GisView from "@/components/gis/GisView.vue";
const modelStore = useModelStore();
@ -29,7 +29,6 @@ const routeKey = computed(() => router.path + Math.random());
<MapModal
v-model:visible="modelStore.modalVisible"
v-model:active-key="modelStore.currentTabKey"
:title="modelStore.title"
:tabs-config="modelStore.tabList"
/>

View File

@ -11,6 +11,26 @@ const permissionStore = usePermissionStoreHook();
// 白名单路由
const whiteList = ['/login', '/register']; //login
// ✅ 新增:递归标准化路由路径,确保所有 path 以 '/' 开头
function normalizeRoutes(routes: any[]): any[] {
return routes.map(route => {
// 创建副本以避免直接修改原始数据(可选,视具体需求而定)
const normalizedRoute = { ...route };
// 修正当前路由的 path
if (normalizedRoute.path && !normalizedRoute.path.startsWith('/')) {
normalizedRoute.path = `/${normalizedRoute.path}`;
}
// 递归修正子路由
if (normalizedRoute.children && normalizedRoute.children.length > 0) {
normalizedRoute.children = normalizeRoutes(normalizedRoute.children);
}
return normalizedRoute;
});
}
// 查找第一个可用路由
function findFirstAvailableRoute(routes: any[]): string | undefined {
for (const route of routes) {
@ -35,11 +55,11 @@ router.beforeEach(async (to, from, next) => {
if (userStore.Token) {
// 登录成功,跳转到首页
if (to.path === '/login') {//login
if (to.path === '/login') {
//login
next({ path: '/' });
NProgress.done();
} else {
const hasGetUserInfo = userStore.roles.length > 0;
if (hasGetUserInfo) {
// 已获取用户信息,检查路由匹配
@ -60,7 +80,11 @@ router.beforeEach(async (to, from, next) => {
} else {
try {
const { roles } = await userStore.getInfo();
const accessRoutes: RouteRecordRaw[] = await permissionStore.generateRoutes(roles);
let accessRoutes: RouteRecordRaw[] =
await permissionStore.generateRoutes(roles);
// ✅ 关键修复:在添加路由前,标准化所有路径
accessRoutes = normalizeRoutes(accessRoutes);
accessRoutes.forEach((route: any) => {
router.addRoute(route);
@ -85,7 +109,6 @@ router.beforeEach(async (to, from, next) => {
}
}
}
} else {
// 未登录可以访问白名单页面
if (whiteList.indexOf(to.path) !== -1) {

View File

@ -15,7 +15,7 @@ const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
// ✅ 保存原始名称到 meta用于菜单显示
tmp.meta = {
...tmp.meta,
title: tmp.name || tmp.menuName, // 原始名称用于显示
title: tmp.name || tmp.menuName // 原始名称用于显示
};
// ✅ name 使用路径生成唯一值
tmp.name = tmp.path || tmp.opturl;
@ -32,7 +32,7 @@ const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
tmp.component = modules[`../../views/error-page/404.vue`];
}
}
res.push(tmp)
res.push(tmp);
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles);
}

View File

@ -7,7 +7,7 @@ import router from '@/router';
// 创建 axios 实例
const service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 300000, // 5分钟
timeout: 15000, // 15秒
headers: { 'Content-Type': 'application/json;charset=utf-8' }
});
@ -58,15 +58,15 @@ service.interceptors.response.use(
// token 过期,重新登录
if (status === '403') {
Modal.confirm({
title: "提示",
content: "当前页面已失效,请重新登录",
okText: "确定",
title: '提示',
content: '当前页面已失效,请重新登录',
okText: '确定',
cancelButtonProps: { disabled: false },
onOk: () => {
localStorage.clear();
router.push('/login');
window.location.href = '/';
},
}
});
} else {
message.error(msg || '当前页面已失效');

View File

@ -34,7 +34,7 @@ const showMapModal = () => {
};
const showMapModal1 = () => {
modelStore.modalVisible = true;
modelStore.params.sttp = "ENG";
modelStore.params.sttp = "zh";
modelStore.title = "三峡222 详情信息";
modelStore.currentTabKey = "basicInfo";
modelStore.isBasicEdit = false;

View File

@ -723,6 +723,7 @@ const fileChange = (file: File) => {
const formData = new FormData();
formData.append("file", file);
await importFishZip(formData);
if (visible.value) importBtn();
});
};
//

File diff suppressed because it is too large Load Diff