<template>
<template v-if="videoPlayList.length">
<template v-for="(item, index) in videoPlayList">
<VideosPlay :data="item" :index="index" />
</template>
</template>
<div class="box">
<div class="top-select">
<el-select
v-model="selectedLayer"
placeholder="影像图层"
class="select-1"
:show-arrow="false"
clearable
@change="handleLayerChange"
@clear="clearLayer"
>
<el-option
v-for="(item, index) in layers"
:key="item.id"
:label="item.title"
:value="item.id"
/>
</el-select>
<el-select
v-model="baseMap"
placeholder="矢量地图"
:show-arrow="false"
class="select-2"
@change="handleBaseMapChange"
value-key="id"
multiple
collapse-tags
>
<el-option
v-for="item in baseMapList"
:key="item.name"
:label="item.name"
:value="item"
/>
</el-select>
<el-select
v-model="selectedTile"
placeholder="实景三维"
class="select-2"
@change="handle3dSwitchChange"
multiple
collapse-tags
:show-arrow="false"
value-key="id"
>
<el-option
v-for="tile in tileList"
:key="tile.id"
:label="tile.title"
:value="tile"
/>
</el-select>
<el-select
v-model="selectedCommunity"
placeholder="动态监测"
class="select-3"
@change="handleCommunityChange"
:show-arrow="false"
>
<el-option
v-for="community in communityList"
:key="community.name"
:label="community.name"
:value="community.name"
/>
</el-select>
</div>
</div>
<!-- 坐标系转换弹窗 -->
<el-dialog
v-model="showCoordinateModal"
title="坐标系转换"
width="400px"
@close="resetCoordinateForm"
>
<el-form :model="coordForm" label-width="100px">
<!-- 源坐标系下拉菜单 -->
<el-form-item label="源坐标系">
<el-select
v-model="coordForm.source"
placeholder="请选择源坐标系"
clearable
class="coord-select"
>
<el-option label="WGS84" value="WGS84"></el-option>
<el-option label="GCJ02(火星)" value="GCJ02"></el-option>
<el-option label="BD09(百度)" value="BD09"></el-option>
</el-select>
</el-form-item>
<!-- 目标坐标系下拉菜单 -->
<el-form-item label="目标坐标系">
<el-select
v-model="coordForm.target"
placeholder="请选择目标坐标系"
clearable
class="coord-select"
>
<el-option label="WGS84" value="WGS84"></el-option>
<el-option label="GCJ02(火星)" value="GCJ02"></el-option>
<el-option label="BD09(百度)" value="BD09"></el-option>
</el-select>
</el-form-item>
<el-form-item label="经度">
<el-input
v-model.number="coordForm.lng"
placeholder="输入经度"
clearable
></el-input>
</el-form-item>
<el-form-item label="纬度">
<el-input
v-model.number="coordForm.lat"
placeholder="输入纬度"
clearable
></el-input>
</el-form-item>
<el-form-item label="转换结果">
<el-input
:value="coordForm.result"
readonly
placeholder="转换结果将显示在这里"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="showCoordinateModal = false">取消</el-button>
<el-button type="primary" @click="convertCoordinates">转换</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { onMounted, ref, onUnmounted } from "vue";
import { $prototype } from "../../main.ts";
import { getVeidoDetail } from "@/service/index";
import { ElMessage } from "element-plus";
import MVTImageryProvider from "mvt-imagery-provider";
import "/public/lib/video/mpegts/mpegts.js";
import "/public/img/div-graphic/divGraphic.css";
import { vectorLayes } from "@/config/index.ts";
import VideosPlay from "@/components/video/index.vue";
import { RefreshLeft } from "@element-plus/icons-vue";
var viewer: any;
const selectedLayer = ref("baseImagery");
const selectedTile = ref([]);
const selectedCommunity = ref("");
const baseMap = ref([]);
const videoPlayList = ref([]);
const addedTilesets = ref<Record<string, Cesium.Cesium3DTileset[]>>({});
const addedMvtLayers = ref<Record<string, Cesium.ImageryLayer[]>>({});
// 坐标系转换相关
const showCoordinateModal = ref(false);
const coordForm = ref({
source: "", // 源坐标系
target: "", // 目标坐标系
lng: 0, // 经度
lat: 0, // 纬度
result: "" // 转换结果
});
const layers = [
{ id: "baseImagery", title: "卫星" },
{ id: "zhuzhou_beidou:GF01", title: "高分1号卫星遥感影像" },
{ id: "zhuzhou_beidou:GF02", title: "高分2号卫星遥感影像" },
{ id: "zhuzhou_beidou:GF06", title: "高分6号卫星遥感影像" },
{ id: "zhuzhou_beidou:GF07", title: "高分7号卫星遥感影像" },
{ id: "zhuzhou_beidou:lkyx", title: "渌口区影像" },
];
const tileList = [
{
id: "tile1",
url: [
"http://124.232.190.30:9000/proxy/pk1725973637070/map/3dmode/20220312-1302/tileset.json",
"http://124.232.190.30:9000/proxy/pk1725973591120/map/3dmode/20220312-1301/tileset.json",
"http://124.232.190.30:9000/proxy/pk1725973529125/map/3dmode/2022022101/tileset.json",
"http://124.232.190.30:9000/proxy/pk1725973404863/map/3dmode/2022011302/tileset.json",
"http://124.232.190.30:9000/proxy/pk1725973226672/map/3dmode/20220312/tileset.json",
"http://124.232.190.30:9000/proxy/pk1725952405569/map/3dmode/20220221/tileset.json",
"http://124.232.190.30:9000/proxy/pk1725952315227/map/3dmode/20220220/tileset.json",
],
title: "会展中心",
},
{
id: "tile2",
url: [
"http://124.232.190.30:9000/proxy/pk1725804650206/map/3dmode/hhhg/tileset.json",
],
title: "园区",
},
];
const communityList = [
{ name: "铁塔视频" },
];
const baseMapList = [
{ id: "geomeg", name: "基础地图", url: "http://124.232.190.30:3011//yjy_pbf/{z}/{x}/{y}.pbf", type: "fill" },
{ id: "lukou_farmland", name: "耕地", url: "http://124.232.190.30:9059/lukou_farmland/{z}/{x}/{y}", type: "fill" },
{ id: "lukou_ecology", name: "生态", url: "http://124.232.190.30:9059/lukou_ecology/{z}/{x}/{y}", type: "fill" },
{ id: "natural_", name: "自然区", url: "http://124.232.190.30:9059/natural_/{z}/{x}/{y}", type: "fill" },
{ id: "lushui_river", name: "渌水流域", url: "http://124.232.190.30:9059/lushui_river/{z}/{x}/{y}", type: "fill" },
{ id: "mishui_river", name: "洣水流域", url: "http://124.232.190.30:9059/mishui_river/{z}/{x}/{y}", type: "fill" },
];
const sprite = "http://124.232.190.67:5432/sprite/sprite";
const glyphs = "http://124.232.190.67:5432/font/mapbox_glyphs/{fontstack}/{range}.pbf";
const baseMapUrl = "http://124.232.190.30:3011//yjy_pbf/layers.json";
// 坐标系转换工具类
const CoordinateConverter = {
a: 6378245.0,
ee: 0.006693421622965943,
// 判断是否在国内
outOfChina(lng: number, lat: number): boolean {
return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271);
},
// 纬度转换
transformLat(x: number, y: number): number {
let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
return ret;
},
// 经度转换
transformLng(x: number, y: number): number {
let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
return ret;
},
// WGS84转GCJ02
wgs84ToGcj02(lng: number, lat: number): [number, number] {
if (this.outOfChina(lng, lat)) return [lng, lat];
let dLat = this.transformLat(lng - 105.0, lat - 35.0);
let dLng = this.transformLng(lng - 105.0, lat - 35.0);
const radLat = lat / 180.0 * Math.PI;
let magic = Math.sin(radLat);
magic = 1 - this.ee * magic * magic;
const sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtMagic) * Math.PI);
dLng = (dLng * 180.0) / (this.a / sqrtMagic * Math.cos(radLat) * Math.PI);
return [lng + dLng, lat + dLat];
},
// GCJ02转WGS84
gcj02ToWgs84(lng: number, lat: number): [number, number] {
if (this.outOfChina(lng, lat)) return [lng, lat];
let dLat = this.transformLat(lng - 105.0, lat - 35.0);
let dLng = this.transformLng(lng - 105.0, lat - 35.0);
const radLat = lat / 180.0 * Math.PI;
let magic = Math.sin(radLat);
magic = 1 - this.ee * magic * magic;
const sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtMagic) * Math.PI);
dLng = (dLng * 180.0) / (this.a / sqrtMagic * Math.cos(radLat) * Math.PI);
const mgLat = lat + dLat;
const mgLng = lng + dLng;
return [lng * 2 - mgLng, lat * 2 - mgLat];
},
// GCJ02转BD09
gcj02ToBd09(lng: number, lat: number): [number, number] {
const x = lng;
const y = lat;
const z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI * 3000.0 / 180.0);
const theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI * 3000.0 / 180.0);
return [z * Math.cos(theta) + 0.0065, z * Math.sin(theta) + 0.006];
},
// BD09转GCJ02
bd09ToGcj02(lng: number, lat: number): [number, number] {
const x = lng - 0.0065;
const y = lat - 0.006;
const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI * 3000.0 / 180.0);
const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI * 3000.0 / 180.0);
return [z * Math.cos(theta), z * Math.sin(theta)];
},
// WGS84转BD09
wgs84ToBd09(lng: number, lat: number): [number, number] {
const [gcjLng, gcjLat] = this.wgs84ToGcj02(lng, lat);
return this.gcj02ToBd09(gcjLng, gcjLat);
},
// BD09转WGS84
bd09ToWgs84(lng: number, lat: number): [number, number] {
const [gcjLng, gcjLat] = this.bd09ToGcj02(lng, lat);
return this.gcj02ToWgs84(gcjLng, gcjLat);
}
};
// 执行坐标系转换
function convertCoordinates() {
const { source, target, lng, lat } = coordForm.value;
// 验证输入
if (!source || !target) {
ElMessage.warning('请选择源坐标系和目标坐标系');
return;
}
if (source === target) {
ElMessage.info('源坐标系与目标坐标系相同,无需转换');
coordForm.value.result = `经度: ${lng.toFixed(6)}, 纬度: ${lat.toFixed(6)}`;
return;
}
if (!lng || !lat || isNaN(lng) || isNaN(lat)) {
ElMessage.warning('请输入有效的经纬度');
return;
}
if (lng < -180 || lng > 180 || lat < -90 || lat > 90) {
ElMessage.warning('经纬度超出有效范围');
return;
}
// 执行转换
let result: [number, number] = [0, 0];
switch (true) {
case source === "WGS84" && target === "GCJ02":
result = CoordinateConverter.wgs84ToGcj02(lng, lat);
break;
case source === "GCJ02" && target === "WGS84":
result = CoordinateConverter.gcj02ToWgs84(lng, lat);
break;
case source === "GCJ02" && target === "BD09":
result = CoordinateConverter.gcj02ToBd09(lng, lat);
break;
case source === "BD09" && target === "GCJ02":
result = CoordinateConverter.bd09ToGcj02(lng, lat);
break;
case source === "WGS84" && target === "BD09":
const gcj = CoordinateConverter.wgs84ToGcj02(lng, lat);
result = CoordinateConverter.gcj02ToBd09(gcj[0], gcj[1]);
break;
case source === "BD09" && target === "WGS84":
const gcj2 = CoordinateConverter.bd09ToGcj02(lng, lat);
result = CoordinateConverter.gcj02ToWgs84(gcj2[0], gcj2[1]);
break;
default:
ElMessage.error("不支持的转换类型");
return;
}
coordForm.value.result = `经度: ${result[0].toFixed(6)}, 纬度: ${result[1].toFixed(6)}`;
}
// 重置转换表单
function resetCoordinateForm() {
coordForm.value = {
source: "",
target: "",
lng: 0,
lat: 0,
result: ""
};
}
// 基础地图切换处理
function handleBaseMapChange(items: any) {
const currentSelectedIds = items.map((item: any) => item.id);
const mvtsToRemove = Object.keys(addedMvtLayers.value).filter(
(mvtId) => !currentSelectedIds.includes(mvtId)
);
mvtsToRemove.forEach((mvtId) => {
const layersToRemove = addedMvtLayers.value[mvtId];
if (layersToRemove && layersToRemove.length > 0) {
layersToRemove.forEach((layer) => {
try {
const layers = viewer.imageryLayers._layers;
for (let i = layers.length - 1; i >= 0; i--) {
if (layers[i]._imageryProvider?.id === mvtId) {
viewer.imageryLayers.remove(layers[i]);
}
}
} catch (e) {
console.error("Error removing MVT layer:", e);
}
});
delete addedMvtLayers.value[mvtId];
}
});
items.forEach((item: any) => {
if (!addedMvtLayers.value[item.id] || addedMvtLayers.value[item.id].length === 0) {
addedMvtLayers.value[item.id] = [];
loadVectorMvt(item.url, item.id, item.type);
}
});
}
// 视频关闭事件监听
$prototype.emitter.on("video-list-play-close", (_id) => {
videoPlayList.value = videoPlayList.value.filter((v) => v.id != _id);
});
// 加载矢量地图
async function loadVectorMvt(data, layerName, type) {
var tt = {
name: "maplibres_yw",
type: "vector",
tiles: [data],
bounds: [-180, -85.051129, 180, 85.051129],
scheme: "xyz",
};
var layersMapbox = [];
const sourcesMapbox: any = {};
if (layerName == "geomeg") {
await fetch(baseMapUrl)
.then((response) => response.json())
.then((data) => {
layersMapbox = JSON.parse(JSON.stringify(data.layers));
});
} else if (vectorLayes[layerName] == undefined) {
const currentLayers = JSON.parse(JSON.stringify(vectorLayes[layerName]));
currentLayers["id"] = currentLayers["id"] + layerName;
currentLayers["source-layer"] = layerName;
currentLayers["source"] = layerName;
layersMapbox.push(currentLayers);
} else {
layersMapbox = JSON.parse(JSON.stringify(vectorLayes[layerName]));
}
sourcesMapbox[layerName] = tt;
var exampleStyle = {
id: data.id,
name: "MapLibre",
zoom: 10,
layers: layersMapbox,
bearing: 0,
sources: sourcesMapbox,
version: 8,
metadata: { "maptiler:copyright": "cxwl" },
};
exampleStyle.glyphs = glyphs;
exampleStyle.sprite = sprite;
let provider = new MVTImageryProvider({ style: exampleStyle });
provider.id = layerName;
viewer.imageryLayers.addImageryProvider(provider);
addedMvtLayers.value[layerName].push(provider);
if (layerName === "lukou_farmland" || layerName === "lukou_ecology") {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(113.159047, 27.721148, 3270),
duration: 3,
});
} else {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(113.490927, 27.048641, 406000),
duration: 3,
});
}
}
// 动态监测处理
var videoData = [113.182301, 27.971201];
async function handleCommunityChange(item: any) {
if (item == "铁塔视频") {
var data = await getVeidoDetail();
if (data.data != null) {
addRandomGraphicByCount(videoData, data.data);
} else {
ElMessage.error(data.message);
}
}
}
// 添加铁塔标记
function addRandomGraphicByCount(position, url) {
viewer.entities.add({
id: "tietaId",
beof: "铁塔视频",
name: "铁塔视频001",
position: Cesium.Cartesian3.fromDegrees(position[0], position[1]),
billboard: {
image: "img/marker/mark-spjk.png",
width: 30,
height: 115,
scale: 1.0,
color: Cesium.Color.WHITE,
eyeOffset: new Cesium.Cartesian3(0, 0, -10),
},
label: {
text: "铁塔视频",
font: "14px sans-serif",
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -30),
},
properties: {
capacityResourceName: "铁塔视频",
url: url,
name: "铁塔视频",
id: "tieta_001",
},
});
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(position[0], position[1], 10000),
duration: 3,
});
}
// 3D模型切换处理
function handle3dSwitchChange(items: any) {
const currentSelectedIds = items.map((item: any) => item.id);
const tilesToRemove = Object.keys(addedTilesets.value).filter(
(tileId) => !currentSelectedIds.includes(tileId)
);
tilesToRemove.forEach((tileId) => {
addedTilesets.value[tileId].forEach((tileset) => {
try {
if (tileset && !tileset.isDestroyed()) {
tileset.destroy();
}
viewer.scene.primitives.remove(tileset);
} catch (e) {
console.error("Error removing tileset:", e);
}
});
delete addedTilesets.value[tileId];
});
items.forEach((item: any) => {
if (!addedTilesets.value[item.id]) {
addedTilesets.value[item.id] = [];
item.url.forEach((url: string) => {
const tileset = new Cesium.Cesium3DTileset({
url: url,
skipLevelOfDetail: true,
skipScreenSpaceErrorFactor: 16,
baseScreenSpaceError: 1024,
maximumScreenSpaceError: 10,
immediatelyLoadDesiredLevelOfDetail: false,
loadSiblings: false,
cullWithChildrenBounds: true,
cullRequestsWhileMoving: true,
cullRequestsWhileMovingMultiplier: 10,
preloadWhenHidden: true,
preferLeaves: true,
maximumMemoryUsage: 2048,
progressiveResolutionHeightFraction: 0.5,
dynamicScreenSpaceErrorDensity: 0.5,
dynamicScreenSpaceErrorFactor: 1,
dynamicScreenSpaceError: false,
});
var heightOffset = 0;
if (url.indexOf("20220220") >= 0) heightOffset = -32;
else if (url.indexOf("2022022101") >= 0) heightOffset = -50.4;
tileset.readyPromise
.then((palaceTileset) => {
viewer.scene.primitives.add(palaceTileset);
addedTilesets.value[item.id].push(palaceTileset);
const boundingSphere = palaceTileset.boundingSphere;
const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
palaceTileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
heightOffset + 10000
),
duration: 3,
});
})
.catch((error) => {
console.error("Error loading tileset:", error);
});
});
}
});
}
// 影像图层切换处理
var currentImageryLayer: Cesium.ImageryLayer | null = null;
var src;
function handleLayerChange(val: any) {
if (currentImageryLayer) {
viewer.imageryLayers.remove(currentImageryLayer);
currentImageryLayer = null;
}
if (!val) return;
if (val === "baseImagery") {
addImage(val);
}
if (val === "zhuzhou_beidou:GF07" || val === "zhuzhou_beidou:lkyx") {
src = "EPSG:4326";
} else if (val !== "baseImagery") {
src = "EPSG:4326x2";
}
var imageryProvider = new Cesium.WebMapTileServiceImageryProvider({
url: "http://124.232.190.14:3013/geoserver/gwc/service/wmts",
layer: val,
format: "image/png",
style: "",
tileMatrixSetID: src,
maximumLevel: 18,
tilingScheme: new Cesium.GeographicTilingScheme({
numberOfLevelZeroTilesX: 2,
numberOfLevelZeroTilesY: 1,
}),
tileMatrixLabels: [...Array(18).keys()].map((level) =>
(src + ":" + level).toString()
),
});
currentImageryLayer = viewer.imageryLayers.addImageryProvider(imageryProvider);
currentImageryLayer.id = val;
}
// 添加基础影像
async function addImage(val: any) {
var rightImageProvider = new Cesium.UrlTemplateImageryProvider({
name: "影像图",
type: "xyz",
layer: val,
url: "http://124.232.190.30:9000/proxy/pk1725866655224/map/zzzsyx_18/{z}/{x}/{y}.png",
minimumLevel: 1,
maximumLevel: 17,
crs: "EPSG:3857",
});
currentImageryLayer = viewer.imageryLayers.addImageryProvider(rightImageProvider);
currentImageryLayer.id = val;
rightImageProvider.splitDirection = Cesium.SplitDirection.right;
}
// 清除影像图层
function clearLayer() {
if (currentImageryLayer) {
viewer.imageryLayers.remove(currentImageryLayer);
currentImageryLayer = null;
}
selectedLayer.value = "";
}
// 组件挂载
onMounted(async () => {
viewer = $prototype.$map;
await addImage("baseImagery");
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
const scene = $prototype.$map.scene;
const ellipsoid = scene.globe.ellipsoid;
handler.setInputAction(function (click) {
const pick = $prototype.$map.scene.pick(click.position);
const cartesians = $prototype.$map.camera.pickEllipsoid(click.position, ellipsoid);
var data = null;
if (cartesians) {
const cartographic = ellipsoid.cartesianToCartographic(cartesians);
const longitude = Cesium.Math.toDegrees(cartographic.longitude).toFixed(6);
const latitude = Cesium.Math.toDegrees(cartographic.latitude).toFixed(6);
data = { longitude: longitude, latitude: latitude };
console.log(longitude + "," + latitude);
}
if (pick && pick.primitive._imageId != undefined && pick.primitive._imageId.indexOf("mark-spjk") >= 0) {
var obj = pick.id._properties;
videoPlayList.value.push({ name: obj.name, url: obj.url, id: obj.id });
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
});
// 组件卸载
onUnmounted(() => {
Object.values(addedTilesets.value).forEach((tilesets) => {
tilesets.forEach((tileset) => {
viewer.scene.primitives.remove(tileset);
});
});
addedTilesets.value = {};
});
</script>
<style lang="scss" scoped>
.box {
position: absolute;
top: 15%;
right: 80px;
overflow: hidden;
}
.top-select {
display: flex;
align-items: center;
justify-content: center;
gap: 0px;
}
.select-1,
.select-2,
.select-3 {
background: linear-gradient(180deg, #00f0f87f 10%, #173c6a 100%);
border-radius: 2px;
border: 1px solid #00f0f87f;
}
.select-1 {
width: 110px;
border-radius: 5px 0 0 5px;
}
.select-2 {
flex: 1;
width: 90px;
}
.select-3 {
flex: 1;
width: 180px;
}
/* 坐标系转换按钮样式 */
.coordinate-btn {
background: linear-gradient(180deg, #00f0f87f 10%, #173c6a 100%);
border: 1px solid #00f0f87f;
color: #b4fdff;
border-radius: 0 5px 5px 0;
padding: 0 15px;
display: flex;
align-items: center;
gap: 5px;
&:hover {
background: linear-gradient(180deg, #00f0f8 10%, #173c6a 100%);
color: #fff;
box-shadow: 0 0 10px rgba(0, 240, 248, 0.5);
}
}
/* 自定义Element组件样式 */
:deep(.el-select__wrapper) {
background: transparent !important;
box-shadow: none !important;
}
:deep(.el-select__caret) {
color: #3cffff;
}
:deep(.el-select__placeholder),
:deep(.el-select__selected-item),
:deep(.el-select-dropdown__item) {
color: #b4fdff !important;
}
:deep(.el-tag.el-tag--info) {
--el-tag-bg-color: #3cffff96 !important;
}
/* 确保下拉菜单正常显示 */
:deep(.el-select-dropdown) {
display: block !important;
background: rgba(1, 28, 82, 0.8) !important;
border: 1px solid #00f0f87f !important;
z-index: 9999 !important;
}
:deep(.el-select-dropdown__item) {
color: #b4fdff !important;
&:hover {
background: rgba(0, 240, 248, 0.2) !important;
}
&.selected {
background: rgba(0, 240, 248, 0.3) !important;
}
}
</style>
<style lang="scss">
/* 全局样式保持不变 */
.el-select-dropdown__item {
color: #b4fdff !important;
}
.el-select__popper.el-popper {
border: 1px solid #3f3f41 !important;
background: rgba(1, 28, 82, 0.8) !important;
}
.el-select-dropdown {
border: none !important;
background: rgba(1, 28, 82, 0.8) !important;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
&::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
&:hover {
background: rgba(255, 255, 255, 0.4);
}
}
}
.el-select-dropdown__item.is-hovering {
border: none !important;
background: rgba(1, 28, 82, 0.8) !important;
}
.is-focus .el-select__wrapper {
box-shadow: none !important;
}
/* ================= 坐标系转换弹窗样式优化 ================= */
.coordinate-dialog {
.el-dialog__headerbtn .el-dialog__close {
color: #b4fdff !important;
&:hover {
color: #fff !important;
}
}
/* 内容区域样式 */
.el-dialog__body {
padding: 20px;
background: transparent;
}
/* 表单样式 */
.coord-form {
.el-form-item {
margin-bottom: 20px;
}
.el-form-item__label {
color: #b4fdff;
font-weight: bold;
}
/* 输入框样式 */
.el-input {
.el-input__wrapper {
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(0, 240, 248, 0.5);
box-shadow: 0 0 5px rgba(0, 240, 248, 0.2) inset;
color: #b4fdff;
border-radius: 4px;
transition: all 0.3s;
&:hover {
border-color: #00f0f8;
box-shadow: 0 0 8px rgba(0, 240, 248, 0.4) inset;
}
&.is-focus {
border-color: #00f0f8;
box-shadow: 0 0 12px rgba(0, 240, 248, 0.6) inset;
}
}
.el-input__inner {
color: #b4fdff;
&::placeholder {
color: rgba(180, 253, 255, 0.6);
}
}
}
/* 结果输入框特殊样式 */
.el-form-item:last-child .el-input__wrapper {
background: rgba(0, 240, 248, 0.1) !important;
border: 1px solid rgba(0, 240, 248, 0.8) !important;
}
}
/* 底部按钮区域 */
.el-dialog__footer {
padding: 15px 20px;
background: linear-gradient(90deg, rgba(23, 60, 106, 0.5), rgba(0, 240, 248, 0.2));
border-top: 1px solid rgba(0, 240, 248, 0.3);
border-radius: 0 0 8px 8px;
}
/* 按钮样式 */
.cancel-btn {
background: transparent;
border: 1px solid rgba(0, 240, 248, 0.5);
color: #b4fdff;
&:hover {
background: rgba(0, 240, 248, 0.2);
border-color: #00f0f8;
color: #fff;
}
}
.convert-btn {
background: linear-gradient(90deg, rgba(0, 240, 248, 0.7), rgba(23, 60, 106, 0.9));
border: none;
color: #fff;
font-weight: bold;
box-shadow: 0 0 10px rgba(0, 240, 248, 0.5);
&:hover {
background: linear-gradient(90deg, rgba(0, 240, 248, 0.9), rgba(23, 60, 106, 1));
box-shadow: 0 0 15px rgba(0, 240, 248, 0.7);
transform: translateY(-1px);
}
&:active {
transform: translateY(1px);
}
}
}
</style>如上所示代码,其中我想知道卫星,矢量地图这些是使用了element的哪些组件布局,
最新发布