forked from xxhjsb/hbt-prevention-ui
feat:地图逻辑添加
parent
3813275c4e
commit
9d7c8d661c
|
@ -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>
|
|
||||||
```
|
|
37
README.md
37
README.md
|
@ -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>
|
||||||
|
```
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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]: {
|
||||||
|
|
Loading…
Reference in New Issue