feat:地图逻辑添加

master
吴延福 2023-06-07 16:20:24 +08:00
parent 3813275c4e
commit 9d7c8d661c
5 changed files with 157 additions and 68 deletions

View File

@ -1,36 +0,0 @@
# hbt-template-ui
## 环境
1. 下载并安装nodeJS环境
2. 安装nrm, 使用nrm将npm仓库配置为公司仓库
3.1 使用npm install -g nrm 全局安装
3.2 使用nrm add hbt-npm http://81.70.119.104:8081/repository/npm-public-hbt/ 增加公司镜像地址
3.3 使用nrm use hbt-npm 切换到公司镜像
3.4 使用nrm ls 查看全部仓库源 *为当前使用源
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### 本框架采用ts与法 具体依赖vue-property-decorator
```
see vue-property-decorator用法详解 https://blog.csdn.net/weixin_44116302/article/details/111225763#PropSync_141
```
### 采用模块联邦
```
远程引用需要先在global.d.ts中注册
例:如需使用远程地图
1.在global.d.ts中注册 declare module 'common/map';
2.在页面中引用
@Component({
components:{MapComponent:()=>import("common/map") }
})
3.在html中应用 <MapComponent :id="'testID'" @onMapLoaded="getMap($event)"></MapComponent>
```

View File

@ -1,3 +1,36 @@
# hbt-prevention-ui
# hbt-template-ui
双重预防前端
## 环境
1. 下载并安装nodeJS环境
2. 安装nrm, 使用nrm将npm仓库配置为公司仓库
3.1 使用npm install -g nrm 全局安装
3.2 使用nrm add hbt-npm http://81.70.119.104:8081/repository/npm-public-hbt/ 增加公司镜像地址
3.3 使用nrm use hbt-npm 切换到公司镜像
3.4 使用nrm ls 查看全部仓库源 *为当前使用源
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### 本框架采用ts与法 具体依赖vue-property-decorator
```
see vue-property-decorator用法详解 https://blog.csdn.net/weixin_44116302/article/details/111225763#PropSync_141
```
### 采用模块联邦
```
远程引用需要先在global.d.ts中注册
例:如需使用远程地图
1.在global.d.ts中注册 declare module 'common/map';
2.在页面中引用
@Component({
components:{MapComponent:()=>import("common/map") }
})
3.在html中应用 <MapComponent :id="'testID'" @onMapLoaded="getMap($event)"></MapComponent>
```

View File

@ -10,6 +10,7 @@
},
"dependencies": {
"@mapbox/mapbox-gl-draw": "^1.4.1",
"@turf/turf": "^6.5.0",
"@types/webpack-env": "^1.18.0",
"axios": "^1.3.4",
"core-js": "^3.8.3",

View File

@ -10,7 +10,8 @@
<div class="content-box">
<div class="update-box">
<div class="form-box">
<FormComponent labelWidth="56px" :fullBtn="true" :btnPosition="'center'" @change="change" :data.sync="updateParams" @actionCallback="callback" :options="options" :actions="actions"></FormComponent>
<FormComponent v-if="viewModel!=='list'" labelWidth="56px" :fullBtn="true" :btnPosition="'center'" @change="change" :data.sync="updateParams" @actionCallback="callback" :options="options" :actions="actions"></FormComponent>
<FormComponent v-else labelWidth="56px" @change="change" :data.sync="listParams" :options="listForm" ></FormComponent>
</div>
<div class="tree-box" v-if="viewModel==='list'">
<el-tree :data="treeData" :expand-on-click-node="false" default-expand-all highlight-current
@ -20,13 +21,12 @@
<span class="text-block">{{ node.label }}</span>
<span>
<el-button
v-if="node.geoJson==='[]'"
type="text"
size="mini"
@click="() => append(data)">
@click="() => drawNode(data)">
绘制
</el-button>
<el-tag v-else size="mini" type="success">已绘制</el-tag>
<!-- <el-tag v-else size="mini" type="success">已绘制</el-tag> -->
</span>
</span>
</el-tree>
@ -45,6 +45,7 @@ import MapComponent from './map.component.vue';
import screenfull from "screenfull"
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import * as turf from '@turf/turf'
@Component({
components:{
MapComponent,
@ -64,14 +65,28 @@ export default class DrawComponent extends Vue {
})
public params!:any;
public fromList = false;
@Watch("params",{immediate:true,deep:true})
onChanges(newVal,odlVal){
console.log(this.draw)
this.updateParams = JSON.parse(JSON.stringify(newVal))
this.positions = JSON.parse(newVal.geoJson);
this.positions.forEach(feature=>{
this.draw.add(feature)
})
if(newVal.geoJson){
this.positions = JSON.parse(newVal.geoJson);
this.positions.forEach(feature=>{
this.draw.add(feature)
})
const center = turf.centerOfMass(turf.featureCollection(this.positions));
this.map.flyTo({center:center.geometry.coordinates,zoom:17})
}
}
@Watch("viewModel",{immediate:true,deep:true})
onModelChanges(newVal){
if(newVal==="list"){
this.fromList = true;
}
this.buildUpdate()
}
public modelMap = {
@ -80,6 +95,17 @@ export default class DrawComponent extends Vue {
unit:"单元绘制"
}
public listForm = [{
name:"关键词",
key:"keyword",
width:"100%",
type:"text",
placeholder:"请输入名称关键词",
}];
public listParams = {
keyword:""
}
public map:any;
public center = [-91.874, 42.76];
@ -152,6 +178,61 @@ export default class DrawComponent extends Vue {
}
}
public getAllFeatures(datas,result?){
if(!result){
result = []
}
datas.forEach((item)=>{
result.push(...JSON.parse(item.geoJson));
if(item.children){
result = this.getAllFeatures(item.children,result)
}
});
return result
}
public addAllPolygon(){
const features = this.getAllFeatures(this.treeData);
const featureCollection = turf.featureCollection(features);
const center = turf.centerOfMass(featureCollection);
this.map.flyTo({center:center.geometry.coordinates,zoom:12})
if(!this.map.getSource('allDataSource')){
this.map.addSource("allDataSource", {
type: "geojson",
data: featureCollection,
});
this.map.addLayer({
id:"allDataLayer",
source:"allDataSource",
type:"fill-extrusion",
paint:{
"fill-extrusion-color":"#38fcf9",
"fill-extrusion-base":["get","bottomHeight"],
"fill-extrusion-height":["get","topHeight"],
"fill-extrusion-opacity":0.6
}
});
this.map.addLayer({
"id": "textLayer",
"type": "symbol",
"source": "polygonSource",
"layout": {
"text-field": ["get", "text"],
"text-size": 24,
"text-allow-overlap": true
},
"paint": {
"text-color": "#FFF",
"text-halo-color": "#000",
"text-halo-width": 5
}
})
}else{
this.map.getSource("allDataSource").setData(featureCollection)
}
}
public drawCallback(e){
if(e.type ==="draw.create"){
this.positions = this.positions.concat(e.features)
@ -181,10 +262,19 @@ export default class DrawComponent extends Vue {
}
public handleNodeClick(node){
console.log(node)
this.positions = JSON.parse(node.geoJson);
}
public drawNode(data){
if(data.area_id){
this.viewModel = "unit"
}else{
this.viewModel = "area"
}
}
public callback(action){
if(action.value==="draw"){
if(!this.map){
@ -209,20 +299,30 @@ export default class DrawComponent extends Vue {
this.positions.forEach(feature=>{
feature.properties = this.updateParams
})
this.updateParams.geoJson = JSON.stringify(this.positions)
this.updateParams.geoJson = JSON.stringify(this.positions);
if(this.fromList){
this.viewModel = "list"
}else{
this.visible = false;
}
}else {
this.removeMap()
this.visible = false;
if(this.fromList){
this.viewModel = "list";
this.draw.deleteAll()
}else{
this.visible = false;
}
this.updateParams = {} as any;
}
}
mounted(){
public buildUpdate(){
this.options = [{
name:"区域名称",
width:"100%",
hide:this.viewModel !== "area",
hide:this.viewModel === "unit",
key:"name",
disable:true,
type:"text",
@ -230,29 +330,20 @@ export default class DrawComponent extends Vue {
},{
name:"单元名称",
key:"unitName",
hide:this.viewModel !== "unit",
hide:this.viewModel === "area",
width:"100%",
disable:true,
type:"text",
placeholder:"请输入单元名称",
},{
name:"关键词",
key:"keyword",
hide:this.viewModel !== "list",
width:"100%",
type:"text",
placeholder:"请输入名称关键词",
},{
name:"顶部高度",
key:"topHeight",
hide:this.viewModel === "list",
width:"100%",
type:"number",
placeholder:"",
},{
name:"底部高度",
key:"bottomHeight",
hide:this.viewModel === "list",
width:"100%",
type:"number",
placeholder:"",
@ -261,23 +352,23 @@ export default class DrawComponent extends Vue {
this.actions = [{
name:"绘制",
value:"draw",
hide:this.viewModel === "list",
icon:"el-icon-edit",
type:"primary"
},{
name:"保存",
value:"save",
hide:this.viewModel === "list",
icon:"el-icon-s-order",
type:"primary"
},{
name:"取消",
hide:this.viewModel === "list",
icon:"el-icon-tickets",
value:"cancel"
}] as any;
}
mounted(){
}
public removeMap(){
this.map.off('draw.create', this.drawCallback);
this.map.off('draw.delete', this.drawCallback);

View File

@ -65,9 +65,9 @@ module.exports = defineConfig({
.end()
},
devServer: {
// client: {
// overlay: false,
// },
client: {
overlay: false,
},
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_GATEWAY_URL]: {