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": { "dependencies": {
"@mapbox/mapbox-gl-draw": "^1.4.1", "@mapbox/mapbox-gl-draw": "^1.4.1",
"@turf/turf": "^6.5.0",
"@types/webpack-env": "^1.18.0", "@types/webpack-env": "^1.18.0",
"axios": "^1.3.4", "axios": "^1.3.4",
"core-js": "^3.8.3", "core-js": "^3.8.3",

View File

@ -10,7 +10,8 @@
<div class="content-box"> <div class="content-box">
<div class="update-box"> <div class="update-box">
<div class="form-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>
<div class="tree-box" v-if="viewModel==='list'"> <div class="tree-box" v-if="viewModel==='list'">
<el-tree :data="treeData" :expand-on-click-node="false" default-expand-all highlight-current <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 class="text-block">{{ node.label }}</span>
<span> <span>
<el-button <el-button
v-if="node.geoJson==='[]'"
type="text" type="text"
size="mini" size="mini"
@click="() => append(data)"> @click="() => drawNode(data)">
绘制 绘制
</el-button> </el-button>
<el-tag v-else size="mini" type="success">已绘制</el-tag> <!-- <el-tag v-else size="mini" type="success">已绘制</el-tag> -->
</span> </span>
</span> </span>
</el-tree> </el-tree>
@ -45,6 +45,7 @@ import MapComponent from './map.component.vue';
import screenfull from "screenfull" import screenfull from "screenfull"
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'; import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxDraw from '@mapbox/mapbox-gl-draw'; import MapboxDraw from '@mapbox/mapbox-gl-draw';
import * as turf from '@turf/turf'
@Component({ @Component({
components:{ components:{
MapComponent, MapComponent,
@ -64,14 +65,28 @@ export default class DrawComponent extends Vue {
}) })
public params!:any; public params!:any;
public fromList = false;
@Watch("params",{immediate:true,deep:true}) @Watch("params",{immediate:true,deep:true})
onChanges(newVal,odlVal){ onChanges(newVal,odlVal){
console.log(this.draw) console.log(this.draw)
this.updateParams = JSON.parse(JSON.stringify(newVal)) this.updateParams = JSON.parse(JSON.stringify(newVal))
this.positions = JSON.parse(newVal.geoJson); if(newVal.geoJson){
this.positions.forEach(feature=>{ this.positions = JSON.parse(newVal.geoJson);
this.draw.add(feature) 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 = { public modelMap = {
@ -80,6 +95,17 @@ export default class DrawComponent extends Vue {
unit:"单元绘制" unit:"单元绘制"
} }
public listForm = [{
name:"关键词",
key:"keyword",
width:"100%",
type:"text",
placeholder:"请输入名称关键词",
}];
public listParams = {
keyword:""
}
public map:any; public map:any;
public center = [-91.874, 42.76]; 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){ public drawCallback(e){
if(e.type ==="draw.create"){ if(e.type ==="draw.create"){
this.positions = this.positions.concat(e.features) this.positions = this.positions.concat(e.features)
@ -181,10 +262,19 @@ export default class DrawComponent extends Vue {
} }
public handleNodeClick(node){ public handleNodeClick(node){
console.log(node)
this.positions = JSON.parse(node.geoJson); this.positions = JSON.parse(node.geoJson);
} }
public drawNode(data){
if(data.area_id){
this.viewModel = "unit"
}else{
this.viewModel = "area"
}
}
public callback(action){ public callback(action){
if(action.value==="draw"){ if(action.value==="draw"){
if(!this.map){ if(!this.map){
@ -209,20 +299,30 @@ export default class DrawComponent extends Vue {
this.positions.forEach(feature=>{ this.positions.forEach(feature=>{
feature.properties = this.updateParams 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 { }else {
this.removeMap() if(this.fromList){
this.visible = false; this.viewModel = "list";
this.draw.deleteAll()
}else{
this.visible = false;
}
this.updateParams = {} as any; this.updateParams = {} as any;
} }
} }
mounted(){
public buildUpdate(){
this.options = [{ this.options = [{
name:"区域名称", name:"区域名称",
width:"100%", width:"100%",
hide:this.viewModel !== "area", hide:this.viewModel === "unit",
key:"name", key:"name",
disable:true, disable:true,
type:"text", type:"text",
@ -230,29 +330,20 @@ export default class DrawComponent extends Vue {
},{ },{
name:"单元名称", name:"单元名称",
key:"unitName", key:"unitName",
hide:this.viewModel !== "unit", hide:this.viewModel === "area",
width:"100%", width:"100%",
disable:true, disable:true,
type:"text", type:"text",
placeholder:"请输入单元名称", placeholder:"请输入单元名称",
},{
name:"关键词",
key:"keyword",
hide:this.viewModel !== "list",
width:"100%",
type:"text",
placeholder:"请输入名称关键词",
},{ },{
name:"顶部高度", name:"顶部高度",
key:"topHeight", key:"topHeight",
hide:this.viewModel === "list",
width:"100%", width:"100%",
type:"number", type:"number",
placeholder:"", placeholder:"",
},{ },{
name:"底部高度", name:"底部高度",
key:"bottomHeight", key:"bottomHeight",
hide:this.viewModel === "list",
width:"100%", width:"100%",
type:"number", type:"number",
placeholder:"", placeholder:"",
@ -261,23 +352,23 @@ export default class DrawComponent extends Vue {
this.actions = [{ this.actions = [{
name:"绘制", name:"绘制",
value:"draw", value:"draw",
hide:this.viewModel === "list",
icon:"el-icon-edit", icon:"el-icon-edit",
type:"primary" type:"primary"
},{ },{
name:"保存", name:"保存",
value:"save", value:"save",
hide:this.viewModel === "list",
icon:"el-icon-s-order", icon:"el-icon-s-order",
type:"primary" type:"primary"
},{ },{
name:"取消", name:"取消",
hide:this.viewModel === "list",
icon:"el-icon-tickets", icon:"el-icon-tickets",
value:"cancel" value:"cancel"
}] as any; }] as any;
} }
mounted(){
}
public removeMap(){ public removeMap(){
this.map.off('draw.create', this.drawCallback); this.map.off('draw.create', this.drawCallback);
this.map.off('draw.delete', this.drawCallback); this.map.off('draw.delete', this.drawCallback);

View File

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