123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565 |
- <template>
- <div class="coord" v-drag="'.coord .ant-card-head'">
- <a-card v-show='value' title="定位" style="width: 315px; box-shadow: 0 0 5px #357ee5;">
- <a-icon slot="extra" type="close" style='cursor: pointer; color: #FFFFFF;' @click="$emit('input',false)"/>
- <a-form-model ref="ruleForm" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
- <a-form-model-item style="margin-bottom: 10px" ref="locate" label="输入坐标" prop="locate">
- <a-input v-model.trim="form.locate" @pressEnter='onSubmit' placeholder='请输入坐标' allow-clear @blur="
- () => {
- $refs.locate.onFieldBlur();
- }
- "/>
- </a-form-model-item>
- <template v-if="data.length>1">
- <a-list style='margin-top: 20px;' item-layout="horizontal" :data-source="data">
- <a-list-item @click="handleCoordsItem(index)" slot="renderItem" slot-scope="item, index">
- <a-list-item-meta >
- <span slot="title">{{ item}}</span>
- <a-avatar slot="avatar" class="result" :src="require(`@/assets/result${index+1}.png`)">
- </a-avatar>
- </a-list-item-meta>
- </a-list-item>
- </a-list>
- </template>
- <template v-else>
- <a-form-model-item style="margin-bottom: 5px" v-show='!isGeodetic&&coordsArr.length>0' label="经纬度:">
- <span class="ant-form-text text">
- {{ form.geodetic }}
- </span>
- </a-form-model-item>
- <a-form-model-item style="margin-bottom: 5px" v-show='!isDegree&&coordsArr.length>0' label="度分秒:">
- <span class="ant-form-text text">
- {{ form.degree }}
- </span>
- </a-form-model-item>
- <a-form-model-item style="margin-bottom: 10px" v-show='!isProjCoord&&coordsArr.length>0' label="投影坐标:">
- <span class="ant-form-text text">
- {{ form.projCoord }}
- </span>
- </a-form-model-item>
- </template>
- <a-form-model-item :wrapper-col="{ span: 17, offset: 6 }">
- <a-button type="primary" @click="onSubmit">
- 定 位
- </a-button>
- <a-button style="margin-left: 5px;" @click="resetForm">
- 重 置
- </a-button>
- <a-button style="margin-left: 5px;" type="link" @click="handleHistory" >
- 历史记录
- </a-button>
- </a-form-model-item>
- </a-form-model>
- <a-list v-show="history" style='margin-top: 10px;border-top: 1px solid #8a8af4; max-height: 550px ' item-layout="horizontal" :data-source="historyList" :pagination="pagination">
- <a-list-item slot="renderItem" style="display:block;cursor: auto" slot-scope="item, index" :key="item.id" >
- <a-list-item-meta :description="item.inputval" >
- <span style=" display: inline-block; word-break: break-all;white-space: normal; cursor: text; color: #333" slot="title">{{ item.name||'未命名'}}</span>
- </a-list-item-meta>
- <a slot="actions" @click="handleHistoryLocate(item)">定位</a>
- <a slot="actions" @click="showModal(item,index)">编辑</a>
- <a-popconfirm slot="actions" title="确定删除吗?" @confirm="() => handleRemove(item.id,index)">
- <a>删除</a>
- </a-popconfirm>
- </a-list-item>
- </a-list>
- <a-modal
- title="编辑"
- :visible="visible"
- :confirm-loading="confirmLoading"
- @ok="handleOk"
- @cancel="handleCancel"
- >
- <a-form-model >
- <a-row>
- <a-col :span="24">
- <a-form-model-item label="名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
- <a-input v-model="model.name"></a-input>
- </a-form-model-item>
- </a-col>
- <a-col :span="24">
- <a-form-model-item label="坐标" :labelCol="labelCol" :wrapperCol="wrapperCol">
- <a-input v-model="model.inputval" disabled rows="4" />
- </a-form-model-item>
- </a-col>
- </a-row>
- </a-form-model>
- </a-modal>
- </a-card>
- </div>
- </template>
- <script>
- import {transform} from 'ol/proj';
- import proj4 from 'proj4';
- import {register} from "ol/proj/proj4";
- import SimpleMarker from "@/components/BasicMap/Tools/SimpleMarker.vue";
- import Feature from "ol/Feature";
- import {Vector as VectorLayer} from "ol/layer";
- import {Vector as VectorSource, Cluster} from "ol/source";
- import Point from "ol/geom/Point";
- import {
- Icon,
- Style,
- Fill,
- Text,
- } from "ol/style";
- import * as olEasing from "ol/easing";
- import {deleteAction, getAction, postAction} from "../../../api/manage";
- export default {
- name: 'CoordsLocate',
- beforeCreate() {
- proj4.defs("EPSG:4548",
- "+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
- proj4.defs("EPSG:4527",
- "+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=39500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
- register(proj4);
- },
- data() {
- //校验
- let validateLocate = (rule, value, callback) => {
- if (value === '') {
- callback(new Error('请输入坐标!'));
- } else {
- // let reg1 = /[^\d\,\,\°\′\″\ \t]/g
- let reg2 = /^(\-|\+)?\d+(\.\d+)?[\uff0c\,\ \t](\-|\+)?\d+(\.\d+)?$/;//4180693.903 541105.228
- // let reg2 = /^[\-\+]?(180|1?[0-7]?\d)*([.][0-9]+)?[\uff0c\,\ \t][\-\+]?(90|[0-8]?\d)([.][0-9]+)?$/;
- let reg3 = this.reg3;
- if (value.indexOf(';') !== -1 || value.indexOf(';') !== -1) {
- value.replace(';', ';');
- this.coordsArr = value.split(';');
- this.coordsArr.forEach((item, index) => {
- if (reg2.test(item) || reg3.test(item)) {
- } else {
- callback(new Error('请输入规范的坐标(只允许输入数字,空格,逗号,与度分秒)!多个坐标请用分号(;)分隔'));
- }
- })
- callback();
- } else {
- if (reg2.test(value) || reg3.test(value)) {
- if (reg3.test(value)) {
- this.isDegree = true;
- } else {
- this.isDegree = false;
- }
- callback();
- } else {
- callback(new Error('请输入规范的坐标(只允许输入数字,空格,逗号,与度分秒)!多个坐标请用分号(;)分隔'));
- }
- }
- }
- }
- return {
- map: {},
- model:{
- },
- labelCol: {span: 6},
- wrapperCol: {span: 17},
- visible: false,
- confirmLoading: false,
- currentIndex:'',
- form: {
- locate: '',
- geodetic: '',
- projCoord: '',
- degree: '',
- },
- pagination: {
- onChange: page => {
- this.pagination.current=page;
- this.getHistory();
- },
- disabled: false,
- pageSize: 10,
- total: 0,
- size: 'small',
- current:1
- },
- reg3: /^[\-\+]?(180|1?[0-7]?\d)°([1-5]?[0-9]?\d)′([1-5]?[0-9]?\d(\.\d+)?)″[\uff0c\,\ \t][\-\+]?(90|[0-8]?\d)°([1-5]?[0-9]?\d)′([1-5]?[0-9]?\d(\.\d+)?)″$/,
- coordsArr: [],
- coords:'',
- clusterSource: '',
- clusters: '',
- data:[],
- isDegree: true,
- isGeodetic: true,
- isProjCoord: true,
- history:false,
- historyList:[],
- rules: {
- locate: [{
- validator: validateLocate,
- trigger: 'blur'
- }],
- },
- };
- },
- props: {
- value: {
- type: Boolean,
- default: false,
- required: true
- }
- },
- watch:{
- value:function (newValue) {
- if(newValue===false){
- // this.resetForm();
- this.history=false;
- }
- }
- },
- inject: ['baseMap'],
- methods: {
- handleHistoryLocate(item){
- this.form.locate= item.inputval;
- this.onSubmit();
- },
- onSubmit() {
- this.coordsArr = [];
- this.map = this.baseMap.map;
- this.$refs.ruleForm.validate((valid) => {
- if (valid) {
- let arrLo;
- if (this.coordsArr.length !== 0) {
- this.coordsArr.forEach((item, index) => {
- this.coordsArr[index] = this.replaceLocate(item);
- });
- } else {
- arrLo = this.replaceLocate(this.form.locate);
- this.coordsArr.push(arrLo);
- }
- if(this.coordsArr.length>10){
- this.$message.error('最多支持同时查询十个点!');
- return;
- }
- this.data = this.coordsArr.slice(0);
- this.coordsArr.forEach((item, index) => {
- if (this.reg3.test(item)) {
- this.isGeodetic = false;
- this.isDegree = true;
- this.isProjCoord = false;
- item.forEach((itemA, index) => {
- itemA = itemA.replace('°', ',');
- itemA = itemA.replace('′', ',');
- itemA = itemA.replace('″', ',');
- itemA = this.changeDegree(itemA);
- item[index] = itemA;
- });
- } else {
- this.isGeodetic = true;
- this.isDegree = false;
- this.isProjCoord = false;
- }
- // 将字符串类型转换为数字类型
- item.forEach((itemB, index) => {
- item[index] = parseFloat(itemB);
- })
- // 默认按从大到小排
- item.sort((a, b) => {
- return b - a;
- });
- let projCoord
- if (item[0] > 39000000) {
- this.isGeodetic = false;
- this.isDegree = false;
- this.isProjCoord = true;
- item.forEach((itemC, index) => {
- item[index] = parseFloat(itemC.toFixed(3));
- });
- this.form.projCoord = item.join(',').slice(2);
- item = transform(item, 'EPSG:4527', 'EPSG:4490');
- } else if (item[0] > 180) {
- this.isGeodetic = false;
- this.isDegree = false;
- this.isProjCoord = true;
- item.forEach((itemD, index) => {
- item[index] = parseFloat(itemD.toFixed(3))
- });
- this.form.projCoord = item.join(',');
- item.reverse();
- item = transform(item, 'EPSG:4548', 'EPSG:4490');
- } else {
- projCoord = transform(item, 'EPSG:4490', 'EPSG:4548');
- projCoord.forEach((item, index) => {
- projCoord[index] = parseFloat(item.toFixed(3));
- });
- this.form.projCoord = projCoord.join(',');
- }
- this.coordsArr[index] = item;
- this.form.geodetic = item.map((item, index) => {
- return item = parseFloat(item.toFixed(6));
- }).join(',');
- this.form.degree = item.map((item) => {
- return item = this.formatDegree(item)
- }).join(',');
- if (item[0] > 180 || item[1] > 90) {
- this.$message.error('输入数据有误!');
- }
- });
- this.locateByCoords();
- } else {
- return false;
- }
- });
- },
- replaceLocate(loc) {
- // 将英文空格转换为,
- let locate = loc;
- if (loc.includes(' ')) {
- locate = loc.replace(' ', ',');
- } else if (loc.includes(',')) {
- locate = loc.replace(',', ',');
- } else if (loc.includes(' ')) {
- locate = loc.replace(' ', ',');
- }else if(loc.includes('\t')) {
- locate = loc.replace('\t', ',');
- }
- let it = locate.split(',');
- return it;
- },
- //度分秒转换为度
- changeDegree(coord) {
- let arr = coord.split(',');
- let miao = arr[2];
- let fen = arr[1];
- let du = arr[0];
- var mFen = 0;
- if (miao != null && miao !== '') {
- mFen = Number(miao / 60);
- }
- var fDu = 0;
- if (fen != null && fen != '') {
- fDu = (Number(fen) + mFen) / 60;
- } else {
- fDu = mFen;
- }
- var lDu = 0;
- if (du != null && du != '') {
- lDu = (Number(du) + fDu).toFixed(6);
- } else {
- lDu = fDu.toFixed(6);
- }
- return lDu;
- },
- formatDegree(value) {
- if (value != null && value != '') {
- ///<summary>将度转换成为度分秒</summary>
- value = Math.abs(value); //返回数的绝对值
- var v1 = Math.floor(value); //度 //对数进行下舍入
- var v2 = Math.floor((value - v1) * 60); //分
- var v3 = Math.round((value - v1) * 3600 % 60); //秒 //把数四舍五入为最接近的整数
- return v1 + '°' + v2 + '′' + v3 + '″';
- } else {
- return '' + ';' + '' + ';' + '' + ';';
- }
- },
- async locateByCoords() {
- if(this.coords.toString()===this.coordsArr.toString()){
- this.locateFit();
- return;
- }
- this.coords = this.coordsArr;
- let {success,message} = await postAction('hzz.lochistory/locHistory/add',{inputval:this.form.locate});
- if(!success){
- this.$message.error(message);
- return;
- }
- // 移除之前的
- if (this.clusters) {
- this.clusterSource.getSource().clear(); //移除聚合标注数据源中的所有要素
- this.map.removeLayer(this.clusters);
- this.clusters='';
- this.clusterSource=''
- }
- this.locateFit();
- setTimeout(() => {
- var source = new VectorSource({
- features: this.features,
- });
- // 聚合标注数据源
- this.clusterSource = new Cluster({
- distance: 0, //这个是通过 distance 来控制两个点聚合的间距
- source: source,
- });
- // 加载聚合标注的矢量图层
- var styleCache = {}; //用于保存特定数量的聚合群的要素样式
- this.clusters = new VectorLayer({
- source: this.clusterSource,
- style: function (feature, resolution) {
- var size = feature.get("features").length; //获取该要素所在聚合群的要素数量
- var style = styleCache[size];
- if (!style) {
- style = [
- new Style({
- image: new Icon({
- src: require(`../../../assets/result${feature.get("features")[0].values_.name.toString()}.png`),
- displacement: [0, 16.5]
- })
- }),
- ];
- }
- return style;
- },
- zIndex: 999,
- });
- this.map.addLayer(this.clusters);
- }, 500);
- },
- handleCoordsItem(index){
- let coords = this.coordsArr[index];
- let view = this.baseMap.map.getView();
- const zoom = view.getZoom();
- view.animate({
- zoom: zoom - 1,
- duration: 300
- }, {
- center: coords,
- zoom: 16,
- duration: 2000
- })
- },
- locateFit(){
- let lng = [];
- let lat = [];
- this.features = [];
- this.coords.forEach((item, index) => {
- lng.push(item[0]);
- lat.push(item[1]);
- this.features.push(
- new Feature({
- geometry: new Point(item),
- name: index + 1,
- })
- );
- });
- lng.sort();
- lat.sort();
- let extent = [lng[0], lat[0], lng[lat.length-1],lat[lat.length-1] ];
- let view = this.baseMap.map.getView();
- const zoom = view.getZoom();
- view.animate({
- zoom: zoom - 1,
- duration: 300
- });
- view.fit(extent, {
- // size:[500,300],
- duration: 2000,
- padding: [100, 100, 100, 100],
- // easing: olEasing.inAndOut
- })
- },
- showModal(item,index) {
- this.visible = true;
- this.model.name = item.name;
- this.model.inputval = item.inputval;
- this.model.id = item.id;
- this.currentIndex = index;
- },
- async handleOk(e) {
- this.confirmLoading = true;
- let {success,result,message} = await postAction('hzz.lochistory/locHistory/edit',{...this.model})
- if(success){
- this.visible = false;
- this.confirmLoading = false;
- this.historyList[this.currentIndex].name = this.model.name;
- }else {
- this.$message.error(message)
- }
- },
- handleCancel(e) {
- this.visible = false;
- },
- async handleRemove(id,index) {
- let {success,result,message} = await deleteAction('hzz.lochistory/locHistory/delete',{id})
- if(success){
- this.$message.success('删除成功');
- this.historyList.splice(index,1);
- }else {
- this.$message.error(message);
- }
- },
- resetForm() {
- this.$refs.ruleForm.resetFields();
- this.isDegree = true;
- this.isGeodetic = true;
- this.isProjCoord = true;
- this.coordsArr=[];
- this.data=[];
- if (this.clusters) {
- this.clusters.setSource(null)
- this.map.removeLayer(this.clusters);
- this.clusters='';
- this.clusterSource=''
- }
- this.coords = "";
- },
- handleHistory(){
- if(this.history){
- this.history=false;
- }else {
- this.history=true;
- this.getHistory();
- }
- },
- async getHistory(){
- // console.log(this.$store.getters.userinfo)
- let {success,result,message} = await getAction('hzz.lochistory/locHistory/list',{createBy:this.$store.state.user.info.username,pageNo: this.pagination.current,column: 'createTime',order: 'desc',field: 'id,,,createBy,createTime,name,inputval,action',});
- if(success){
- this.historyList=result.records;
- this.pagination.total = parseInt(result.total);
- }else {
- this.$message.error(message);
- }
- },
- },
- }
- </script>
- <style>
- .coord .ant-list-item-meta-description {
- word-break: break-all;
- white-space: normal;
- cursor: text;
- user-select: text;
- }
- .coord .ant-spin-nested-loading {
- max-height: 200px;
- overflow-y: auto;
- }
- .coord .ant-card-body {
- padding: 1em;
- }
- .coord .ant-list-item-action {
- text-align: end;
- }
- .coord .ant-form-item-children{
- display: flex;
- justify-content: space-around;
- align-items: center;
- }
- .coord .text {
- cursor: text;
- color: rgba(0, 0, 0, .65);
- font-weight: 400;
- font-size: 14px;
- padding: 4px 11px;
- background-color: #fafafa;
- border: 1px solid #d9d9d9;
- border-radius: 4px;
- transition: all .3s;
- width: 100%;
- height: 32px;
- line-height: 1.5;
- display: inline-block;
- user-select: text;
- }
- </style>
|