项目列表上传DXF文件并显示
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "2.3.1",
|
"@element-plus/icons-vue": "2.3.1",
|
||||||
"@highlightjs/vue-plugin": "2.1.0",
|
"@highlightjs/vue-plugin": "2.1.0",
|
||||||
|
"@turf/turf": "^7.2.0",
|
||||||
"@vueup/vue-quill": "1.2.0",
|
"@vueup/vue-quill": "1.2.0",
|
||||||
"@vueuse/core": "11.3.0",
|
"@vueuse/core": "11.3.0",
|
||||||
"animate.css": "4.1.1",
|
"animate.css": "4.1.1",
|
||||||
@ -38,6 +39,7 @@
|
|||||||
"highlight.js": "11.9.0",
|
"highlight.js": "11.9.0",
|
||||||
"image-conversion": "2.1.1",
|
"image-conversion": "2.1.1",
|
||||||
"js-cookie": "3.0.5",
|
"js-cookie": "3.0.5",
|
||||||
|
"js-md5": "^0.8.3",
|
||||||
"jsencrypt": "3.3.2",
|
"jsencrypt": "3.3.2",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
|
37
src/App.vue
37
src/App.vue
@ -1,11 +1,6 @@
|
|||||||
<template loading="true">
|
<template loading="true">
|
||||||
<el-config-provider :locale="appStore.locale" :size="appStore.size">
|
<el-config-provider :locale="appStore.locale" :size="appStore.size">
|
||||||
<router-view />
|
<router-view />
|
||||||
<div>123</div>
|
|
||||||
<div v-for="item in aarr">
|
|
||||||
1<span v-for="itm in item.features">{{ itm.geometry.coordinates }}1</span>
|
|
||||||
</div>
|
|
||||||
<el-button type="primary" size="default" @click="a" class="ml-100" v-loading.fullscreen.lock="fullscreenLoading">123</el-button>
|
|
||||||
</el-config-provider>
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -14,22 +9,7 @@ import useSettingsStore from '@/store/modules/settings';
|
|||||||
import { handleThemeStyle } from '@/utils/theme';
|
import { handleThemeStyle } from '@/utils/theme';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { getProjectTeam } from './utils/projectTeam';
|
import { getProjectTeam } from './utils/projectTeam';
|
||||||
import request from '@/utils/request';
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const fullscreenLoading = ref(false);
|
|
||||||
const aarr = ref([]);
|
|
||||||
const a = () => {
|
|
||||||
fullscreenLoading.value = true;
|
|
||||||
request({
|
|
||||||
url: '/project/project/json',
|
|
||||||
method: 'get'
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
aarr.value = res.data.layers;
|
|
||||||
|
|
||||||
fullscreenLoading.value = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -39,3 +19,20 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
-webkit-touch-callout: none; /*系统默认菜单被禁用*/
|
||||||
|
-webkit-user-select: none; /*webkit浏览器*/
|
||||||
|
-khtml-user-select: none; /*早期浏览器*/
|
||||||
|
-moz-user-select: none; /*火狐*/
|
||||||
|
-ms-user-select: none; /*IE10*/
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
-webkit-user-select: auto; /*webkit浏览器*/
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
-webkit-user-select: auto; /*webkit浏览器*/
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -16,6 +16,19 @@ export const listProject = (query?: ProjectQuery): AxiosPromise<ProjectVO[]> =>
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询项目dxf
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listDXFProject = (id: string | number): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/project/projectFile/json/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询项目详细
|
* 查询项目详细
|
||||||
* @param id
|
* @param id
|
||||||
@ -51,6 +64,18 @@ export const updateProject = (data: ProjectForm) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传dxf文件
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const upLoadProjectDXF = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/project/projectFile/upload/dxf',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除项目
|
* 删除项目
|
||||||
* @param id
|
* @param id
|
||||||
|
@ -2,7 +2,7 @@ export interface ProjectVO {
|
|||||||
/**
|
/**
|
||||||
* id
|
* id
|
||||||
*/
|
*/
|
||||||
id: string | number;
|
id: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目名称
|
* 项目名称
|
||||||
@ -13,7 +13,7 @@ export interface ProjectVO {
|
|||||||
* 项目简称
|
* 项目简称
|
||||||
*/
|
*/
|
||||||
shortName: string;
|
shortName: string;
|
||||||
|
designId: string;
|
||||||
/**
|
/**
|
||||||
* 父项目id
|
* 父项目id
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ol-map" id="olMap"></div>
|
<div class="flex justify-between">
|
||||||
|
<el-tree
|
||||||
|
style="width: 340px; height: 500px; overflow-y: auto"
|
||||||
|
show-checkbox
|
||||||
|
:data="jsonData"
|
||||||
|
@check-change="handleCheckChange"
|
||||||
|
@node-contextmenu="nodeMenu"
|
||||||
|
>
|
||||||
|
<template #default="{ node, data }">
|
||||||
|
<span @dblclick="handlePosition(data)">{{ data.name }}</span>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
<div class="ol-map" id="olMap"></div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -9,17 +22,69 @@ import { Tile as TileLayer } from 'ol/layer'; // OpenLayers的瓦片图层类
|
|||||||
import { XYZ, OSM } from 'ol/source'; // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源
|
import { XYZ, OSM } from 'ol/source'; // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源
|
||||||
import { fromLonLat, toLonLat } from 'ol/proj'; // OpenLayers的投影转换函数,用于经纬度坐标和投影坐标之间的转换
|
import { fromLonLat, toLonLat } from 'ol/proj'; // OpenLayers的投影转换函数,用于经纬度坐标和投影坐标之间的转换
|
||||||
import { defaults as defaultInteractions, DragRotateAndZoom } from 'ol/interaction'; // OpenLayers的交互类,包括默认的交互集合和特定的旋转缩放交互
|
import { defaults as defaultInteractions, DragRotateAndZoom } from 'ol/interaction'; // OpenLayers的交互类,包括默认的交互集合和特定的旋转缩放交互
|
||||||
import { defaults, FullScreen, MousePosition, ScaleLine } from 'ol/control'; // OpenLayers的控件类,包括默认的控件集合和特定的全屏、鼠标位置、比例尺控件
|
import { defaults as defaultControls, defaults, FullScreen, MousePosition, ScaleLine } from 'ol/control'; // OpenLayers的控件类,包括默认的控件集合和特定的全屏、鼠标位置、比例尺控件
|
||||||
import Feature from 'ol/Feature'; // OpenLayers的要素类,表示地图上的一个对象或实体
|
import Feature from 'ol/Feature'; // OpenLayers的要素类,表示地图上的一个对象或实体
|
||||||
import Point from 'ol/geom/Point'; // OpenLayers的点几何类,用于表示点状的地理数据
|
import Point from 'ol/geom/Point'; // OpenLayers的点几何类,用于表示点状的地理数据
|
||||||
import { Vector as VectorLayer } from 'ol/layer'; // OpenLayers的矢量图层类,用于显示矢量数据
|
import { Vector as VectorLayer } from 'ol/layer'; // OpenLayers的矢量图层类,用于显示矢量数据
|
||||||
import { Vector as VectorSource } from 'ol/source'; // OpenLayers的矢量数据源类,用于管理和提供矢量数据
|
import { Vector as VectorSource } from 'ol/source'; // OpenLayers的矢量数据源类,用于管理和提供矢量数据
|
||||||
import { Circle as CircleStyle, Style, Stroke, Fill, Icon } from 'ol/style'; // OpenLayers的样式类,用于定义图层的样式,包括圆形样式、基本样式、边框、填充和图标
|
import { Circle, Style, Stroke, Fill, Icon } from 'ol/style'; // OpenLayers的样式类,用于定义图层的样式,包括圆形样式、基本样式、边框、填充和图标
|
||||||
import LineString from 'ol/geom/LineString'; // OpenLayers的线几何类,用于表示线状的地理数据
|
import LineString from 'ol/geom/LineString'; // OpenLayers的线几何类,用于表示线状的地理数据
|
||||||
import tb from '@/assets/image/hyfw.png'; // 导入一个图片资源
|
|
||||||
import Polygon from 'ol/geom/Polygon'; // OpenLayers的多边形几何类,用于表示面状的地理数据
|
import Polygon from 'ol/geom/Polygon'; // OpenLayers的多边形几何类,用于表示面状的地理数据
|
||||||
|
import * as turf from '@turf/turf';
|
||||||
|
import { Snowflake } from '@/utils/snowflake';
|
||||||
|
const props = defineProps({
|
||||||
|
treeData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
projectId: String
|
||||||
|
});
|
||||||
|
const snowflake = new Snowflake(1, 1);
|
||||||
let map: any = null;
|
let map: any = null;
|
||||||
|
|
||||||
|
const layerData = reactive<any>({});
|
||||||
|
const centerPosition = ref(fromLonLat([107.12932603888963, 23.80590052110889]));
|
||||||
|
const nodeMenu = (e: any) => {
|
||||||
|
console.log(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
const jsonData = computed(() => {
|
||||||
|
props.treeData.forEach((item: any) => {
|
||||||
|
item.features.forEach((itm, idx) => {
|
||||||
|
itm.geometry.id = snowflake.nextId();
|
||||||
|
itm.geometry.coordinates = convertStrToNum(itm.geometry.coordinates);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return props.treeData;
|
||||||
|
});
|
||||||
|
console.log(jsonData);
|
||||||
|
|
||||||
|
const handlePosition = (data: any) => {
|
||||||
|
//切换中心点
|
||||||
|
centerPosition.value = fromLonLat(turf.center(data).geometry.coordinates);
|
||||||
|
console.log(turf.center(data));
|
||||||
|
|
||||||
|
map.getView().setCenter(centerPosition.value);
|
||||||
|
};
|
||||||
|
const handleCheckChange = (data: any, bool) => {
|
||||||
|
if (bool) {
|
||||||
|
if (!layerData[data.features[0].properties.id]) {
|
||||||
|
data.features.forEach((item: any) => {
|
||||||
|
creatPoint(item.geometry.coordinates, item.geometry.type, item.geometry.id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data.features.forEach((item: any) => {
|
||||||
|
map.addLayer(layerData[item.geometry.id]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data.features.forEach((item, index) => {
|
||||||
|
map.removeLayer(layerData[item.geometry.id]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// creatPoint(fromLonLat(data.geometry.coordinates), data.geometry.type);
|
||||||
|
};
|
||||||
function initOLMap() {
|
function initOLMap() {
|
||||||
// 创造地图实例
|
// 创造地图实例
|
||||||
map = new Map({
|
map = new Map({
|
||||||
@ -32,7 +97,7 @@ function initOLMap() {
|
|||||||
new TileLayer({
|
new TileLayer({
|
||||||
// 设置图层的数据源为XYZ类型。XYZ是一个通用的瓦片图层源,它允许你通过URL模板来获取瓦片
|
// 设置图层的数据源为XYZ类型。XYZ是一个通用的瓦片图层源,它允许你通过URL模板来获取瓦片
|
||||||
source: new XYZ({
|
source: new XYZ({
|
||||||
url: 'http://t4.tianditu.com/DataServer?T=img_c&tk=ebc08347687dacd6c8feed51ffb4f9fc&x={x}&y={y}&l={z}'
|
url: 'https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
@ -40,31 +105,42 @@ function initOLMap() {
|
|||||||
// View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。
|
// View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。
|
||||||
view: new View({
|
view: new View({
|
||||||
// fromLonLat是一个函数,用于将经纬度坐标转换为地图的坐标系统。
|
// fromLonLat是一个函数,用于将经纬度坐标转换为地图的坐标系统。
|
||||||
center: fromLonLat([104.924652, 76.208527]), //地图中心点
|
center: centerPosition.value, //地图中心点
|
||||||
zoom: 15, // 缩放级别
|
zoom: 15, // 缩放级别
|
||||||
minZoom: 0, // 最小缩放级别
|
minZoom: 0, // 最小缩放级别
|
||||||
maxZoom: 18, // 最大缩放级别
|
// maxZoom: 18, // 最大缩放级别
|
||||||
constrainResolution: true // 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
|
constrainResolution: true // 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
|
||||||
|
// projection: 'EPSG:4326' // 投影坐标系,默认是3857
|
||||||
}),
|
}),
|
||||||
// 按住shift进行旋转
|
// 按住shift进行旋转
|
||||||
interactions: defaultInteractions().extend([new DragRotateAndZoom()]),
|
// interactions: defaultInteractions().extend([new DragRotateAndZoom()]),
|
||||||
// 控件
|
// 控件
|
||||||
controls: defaults().extend([
|
// controls: defaults().extend([
|
||||||
// new FullScreen(), // 全屏
|
// new FullScreen(), // 全屏
|
||||||
// new MousePosition(), // 显示鼠标当前位置的地图坐标
|
// new MousePosition(), // 显示鼠标当前位置的地图坐标
|
||||||
// new ScaleLine() // 显示比例尺
|
// new ScaleLine() // 显示比例尺
|
||||||
|
|
||||||
|
// ])
|
||||||
|
|
||||||
|
//加载控件到地图容器中
|
||||||
|
controls: defaultControls({
|
||||||
|
zoom: false,
|
||||||
|
rotate: false,
|
||||||
|
attribution: false
|
||||||
|
}).extend([
|
||||||
|
new FullScreen() // 全屏
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
|
|
||||||
// 事件
|
// 事件
|
||||||
map.on('moveend', (e: any) => {
|
map.on('moveend', (e: any) => {
|
||||||
console.log('地图移动', e);
|
// console.log('地图移动', e);
|
||||||
// 获取当前缩放级别
|
// 获取当前缩放级别
|
||||||
var zoomLevel = map.getView().getZoom();
|
var zoomLevel = map.getView().getZoom();
|
||||||
console.log('当前缩放级别:', zoomLevel);
|
// console.log('当前缩放级别:', zoomLevel);
|
||||||
});
|
});
|
||||||
map.on('rendercomplete', () => {
|
map.on('rendercomplete', () => {
|
||||||
console.log('渲染完成');
|
// console.log('渲染完成');
|
||||||
});
|
});
|
||||||
map.on('click', (e: any) => {
|
map.on('click', (e: any) => {
|
||||||
var coordinate = e.coordinate;
|
var coordinate = e.coordinate;
|
||||||
@ -76,66 +152,102 @@ function initOLMap() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//递归字符串数组变成数字
|
||||||
|
function convertStrToNum(arr) {
|
||||||
|
if (typeof arr === 'string') {
|
||||||
|
const num = Number(arr);
|
||||||
|
return isNaN(num) ? arr : num;
|
||||||
|
} else if (Array.isArray(arr)) {
|
||||||
|
return arr.map((item) => convertStrToNum(item));
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date:2024/3/26
|
* Date:2024/3/26
|
||||||
* Author:zx
|
* Author:zx
|
||||||
* Function:【面】
|
* Function:【面】
|
||||||
* @param 无
|
* @param 无
|
||||||
*/
|
*/
|
||||||
const faceMethod = () => {
|
|
||||||
// 定义多边形的坐标数组,这里使用一个简单的正方形作为示例
|
|
||||||
let coordinates = [
|
|
||||||
[
|
|
||||||
fromLonLat([104.92463054232786, 76.20886348492309]),
|
|
||||||
fromLonLat([104.93329367029872, 76.20920235946437]),
|
|
||||||
fromLonLat([104.93078312266078, 76.20792354487821]),
|
|
||||||
fromLonLat([104.92466768610683, 76.20791331389265]),
|
|
||||||
fromLonLat([104.92463054232786, 76.20886348492309])
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
|
const creatPoint = (pointObj: Array<any>, type: string, id: string) => {
|
||||||
// 创建多边形的几何对象
|
// 创建多边形的几何对象
|
||||||
let polygon = new Polygon(coordinates);
|
let polygon;
|
||||||
|
if (type === 'Point') {
|
||||||
|
polygon = new Point(fromLonLat(pointObj));
|
||||||
|
} else if (type === 'LineString') {
|
||||||
|
const lineStringData = pointObj.map((arr: any) => fromLonLat(arr));
|
||||||
|
polygon = new Polygon([lineStringData]);
|
||||||
|
} else {
|
||||||
|
const polygonData = pointObj.map((arr: any) => arr.map((i: any) => fromLonLat(i)));
|
||||||
|
polygon = new Polygon(polygonData);
|
||||||
|
}
|
||||||
// 创建特征(Feature)
|
// 创建特征(Feature)
|
||||||
let polygonFeature = new Feature({
|
let polygonFeature = new Feature({
|
||||||
geometry: polygon
|
geometry: polygon
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置多边形的样式(Style)
|
const pointStyle = new Style({
|
||||||
polygonFeature.setStyle(
|
image: new Circle({
|
||||||
new Style({
|
radius: 2,
|
||||||
stroke: new Stroke({
|
|
||||||
color: 'red', // 多边形边界线的颜色
|
|
||||||
width: 2 // 多边形边界线的宽度
|
|
||||||
}),
|
|
||||||
fill: new Fill({
|
fill: new Fill({
|
||||||
color: 'rgba(255, 0, 0, 0.1)' // 多边形填充颜色,这里设置为半透明红色
|
color: 'red'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
});
|
||||||
|
const polygonStyle = new Style({
|
||||||
|
stroke: new Stroke({
|
||||||
|
color: type === 'LineString' ? 'skyblue' : 'purple', // 多边形边界线的颜色
|
||||||
|
width: 2 // 多边形边界线的宽度
|
||||||
|
}),
|
||||||
|
fill: new Fill({
|
||||||
|
color: 'transparent' // 多边形填充颜色,这里设置为半透明红色
|
||||||
|
})
|
||||||
|
});
|
||||||
|
// 设置多边形的样式(Style)
|
||||||
|
polygonFeature.setStyle(type === 'Point' ? pointStyle : polygonStyle);
|
||||||
// 创建和添加特征到源(Source)
|
// 创建和添加特征到源(Source)
|
||||||
let source = new VectorSource();
|
let source = new VectorSource();
|
||||||
source.addFeature(polygonFeature);
|
source.addFeature(polygonFeature);
|
||||||
|
|
||||||
// 创建图层并设置源(Layer)
|
// 创建图层并设置源(Layer)
|
||||||
let layer = new VectorLayer();
|
layerData[id] = new VectorLayer();
|
||||||
layer.setSource(source);
|
layerData[id].setSource(source);
|
||||||
|
|
||||||
// 将图层添加到地图上
|
map.addLayer(layerData[id]);
|
||||||
map.addLayer(layer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 地图初始化
|
// 地图初始化
|
||||||
initOLMap();
|
initOLMap();
|
||||||
faceMethod();
|
});
|
||||||
|
|
||||||
|
onDeactivated(() => {
|
||||||
|
console.log('地图销毁');
|
||||||
|
|
||||||
|
map.getOverlays().clear();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.ol-map {
|
.ol-map {
|
||||||
height: 450px;
|
height: 450px;
|
||||||
width: 1000px;
|
width: 950px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
.ol-custome-full-screen {
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 5px 11px;
|
||||||
|
height: 24px;
|
||||||
|
background-color: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
&:active {
|
||||||
|
background-color: #337ecc;
|
||||||
|
border-color: #66b1ff;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: #79bbff;
|
||||||
|
border-color: #79bbff;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
71
src/utils/snowflake.ts
Normal file
71
src/utils/snowflake.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
export class Snowflake {
|
||||||
|
private startTimeStamp: number = 1609459200000;
|
||||||
|
private workerIdBits: number = 5;
|
||||||
|
private dataCenterIdBits: number = 5;
|
||||||
|
private sequenceBits: number = 12;
|
||||||
|
|
||||||
|
private maxWorkerId: number = -1 ^ (-1 << this.workerIdBits);
|
||||||
|
private maxDataCenterId: number = -1 ^ (-1 << this.dataCenterIdBits);
|
||||||
|
|
||||||
|
private workerIdShift: number = this.sequenceBits;
|
||||||
|
private dataCenterIdShift: number = this.sequenceBits + this.workerIdBits;
|
||||||
|
private timestampLeftShift: number = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits;
|
||||||
|
private sequenceMask: number = -1 ^ (-1 << this.sequenceBits);
|
||||||
|
|
||||||
|
private workerId: number;
|
||||||
|
private dataCenterId: number;
|
||||||
|
private sequence: number = 0;
|
||||||
|
private lastTimestamp: number = -1;
|
||||||
|
|
||||||
|
constructor(workerId: number, dataCenterId: number) {
|
||||||
|
if (workerId > this.maxWorkerId || workerId < 0) {
|
||||||
|
throw new Error(`Worker ID 不能大于 ${this.maxWorkerId} 或小于 0`);
|
||||||
|
}
|
||||||
|
if (dataCenterId > this.maxDataCenterId || dataCenterId < 0) {
|
||||||
|
throw new Error(`数据中心 ID 不能大于 ${this.maxDataCenterId} 或小于 0`);
|
||||||
|
}
|
||||||
|
this.workerId = workerId;
|
||||||
|
this.dataCenterId = dataCenterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public nextId(): number {
|
||||||
|
let timestamp = this.getCurrentTimestamp();
|
||||||
|
if (timestamp < this.lastTimestamp) {
|
||||||
|
throw new Error('检测到时钟回拨,拒绝生成 ID');
|
||||||
|
}
|
||||||
|
if (timestamp === this.lastTimestamp) {
|
||||||
|
this.sequence = (this.sequence + 1) & this.sequenceMask;
|
||||||
|
if (this.sequence === 0) {
|
||||||
|
timestamp = this.waitNextMillis(this.lastTimestamp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.sequence = 0;
|
||||||
|
}
|
||||||
|
this.lastTimestamp = timestamp;
|
||||||
|
return (
|
||||||
|
((timestamp - this.startTimeStamp) << this.timestampLeftShift) |
|
||||||
|
(this.dataCenterId << this.dataCenterIdShift) |
|
||||||
|
(this.workerId << this.workerIdShift) |
|
||||||
|
this.sequence
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getCurrentTimestamp(): number {
|
||||||
|
return Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
private waitNextMillis(lastTimestamp: number): number {
|
||||||
|
let timestamp = this.getCurrentTimestamp();
|
||||||
|
while (timestamp <= lastTimestamp) {
|
||||||
|
timestamp = this.getCurrentTimestamp();
|
||||||
|
}
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用示例
|
||||||
|
// const workerId: number = 1;
|
||||||
|
// const dataCenterId: number = 1;
|
||||||
|
// const snowflake = new Snowflake(workerId, dataCenterId);
|
||||||
|
// const id: number = snowflake.nextId();
|
||||||
|
// console.log('生成的唯一 ID:', id);
|
@ -16,7 +16,6 @@
|
|||||||
<p>{{ visitCount }}</p>
|
<p>{{ visitCount }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<openLayersMap></openLayersMap>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -69,12 +69,34 @@
|
|||||||
<el-table-column label="开工时间" align="center" prop="onStreamTime" width="120" />
|
<el-table-column label="开工时间" align="center" prop="onStreamTime" width="120" />
|
||||||
<el-table-column label="打卡范围" align="center" prop="punchRange" />
|
<el-table-column label="打卡范围" align="center" prop="punchRange" />
|
||||||
<el-table-column label="设计总量" align="center" prop="designTotal" />
|
<el-table-column label="设计总量" align="center" prop="designTotal" />
|
||||||
|
<el-table-column label="是否上传DXF" align="center" prop="designId" width="140">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-link
|
||||||
|
:type="scope.row.designId ? 'primary' : 'default'"
|
||||||
|
:disabled="!scope.row.designId"
|
||||||
|
@click="handleOpenLayer(scope.row)"
|
||||||
|
v-loading.fullscreen.lock="fullscreenLoading"
|
||||||
|
>{{ scope.row.designId ? '已上传' : '未上传' }}</el-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="备注" align="center" prop="remark" />
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
|
||||||
<el-table-column fixed="right" label="操作" align="center" class-name="small-padding fixed-width" width="260">
|
<el-table-column fixed="right" label="操作" align="center" class-name="small-padding fixed-width" width="400">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-space>
|
<el-space>
|
||||||
<el-button link type="primary" icon="FolderOpened" @click="handleShowUpload(scope.row)">导入安全协议书 </el-button>
|
<el-button link type="primary" icon="FolderOpened" @click="handleShowUpload(scope.row)">导入安全协议书 </el-button>
|
||||||
|
<file-upload
|
||||||
|
:limit="1"
|
||||||
|
:fileSize="200"
|
||||||
|
:fileType="['dxf']"
|
||||||
|
v-model:model-value="dxfFile"
|
||||||
|
uploadUrl="/project/projectFile/upload/dxf"
|
||||||
|
:data="{ projectId: scope.row.id }"
|
||||||
|
>
|
||||||
|
<el-button link type="primary" icon="upload">上传DXF </el-button>
|
||||||
|
</file-upload>
|
||||||
|
|
||||||
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:project:edit']">修改 </el-button>
|
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:project:edit']">修改 </el-button>
|
||||||
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:project:remove']">删除 </el-button>
|
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:project:remove']">删除 </el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
@ -232,20 +254,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- //选取项目地址弹窗 -->
|
||||||
<el-dialog v-model="amapStatus" :title="form.projectName + '-获取经纬度'" width="80%">
|
<el-dialog v-model="amapStatus" :title="form.projectName + '-获取经纬度'" width="80%">
|
||||||
<amap height="620px" @setLocation="setPoi"></amap>
|
<amap height="620px" @setLocation="setPoi"></amap>
|
||||||
<!-- <template #footer>
|
</el-dialog>
|
||||||
<div class="dialog-footer">
|
<!-- 选取方阵地址 -->
|
||||||
<el-button v-loading="buttonLoading" type="primary" @click="amapStatus = false"> 确定</el-button>
|
<el-dialog title="设置方阵" v-model="polygonStatus" width="1400px">
|
||||||
<el-button @click="amapStatus = false">取消</el-button>
|
<open-layers-map :tree-data="jsonData" :project-id="projectId"></open-layers-map>
|
||||||
</div>
|
<template #footer>
|
||||||
</template> -->
|
<span>
|
||||||
|
<el-button @click="polygonStatus = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Project" lang="ts">
|
<script setup name="Project" lang="ts">
|
||||||
import { addProject, delProject, getProject, listProject, updateProject } from '@/api/project/project';
|
import { addProject, delProject, getProject, listDXFProject, listProject, updateProject } from '@/api/project/project';
|
||||||
import { ProjectForm, ProjectQuery, ProjectVO, locationType } from '@/api/project/project/types';
|
import { ProjectForm, ProjectQuery, ProjectVO, locationType } from '@/api/project/project/types';
|
||||||
import amap from '@/components/amap/index.vue';
|
import amap from '@/components/amap/index.vue';
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -266,10 +294,15 @@ const total = ref(0);
|
|||||||
const amapStatus = ref(false);
|
const amapStatus = ref(false);
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const projectFormRef = ref<ElFormInstance>();
|
const projectFormRef = ref<ElFormInstance>();
|
||||||
|
const polygonStatus = ref(false);
|
||||||
|
const dxfFile = ref(null);
|
||||||
|
const projectId = ref<string>('');
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
const jsonData = ref(null);
|
||||||
|
const fullscreenLoading = ref(false);
|
||||||
|
|
||||||
const initFormData: ProjectForm = {
|
const initFormData: ProjectForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@ -426,6 +459,15 @@ const handleShowUpload = (row?: ProjectVO) => {
|
|||||||
uploadVisible.value = true;
|
uploadVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOpenLayer = async (row: ProjectVO) => {
|
||||||
|
fullscreenLoading.value = true;
|
||||||
|
const res = await listDXFProject(row.designId);
|
||||||
|
projectId.value = row.id;
|
||||||
|
jsonData.value = res.data.layers;
|
||||||
|
polygonStatus.value = true;
|
||||||
|
fullscreenLoading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
const updateProjectFile = async () => {
|
const updateProjectFile = async () => {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
await updateProject(fileUploadParam.value);
|
await updateProject(fileUploadParam.value);
|
||||||
|
Reference in New Issue
Block a user