rt-sim-training-client/src/views/newMap/newMapdraft/index.vue
2020-05-09 17:32:13 +08:00

692 lines
28 KiB
Vue

<template>
<transition name="el-zoom-in-center">
<div class="mapPaint">
<div v-show="maskOpen" class="mask" />
<div class="map-view">
<div class="operation_box">
<el-button-group>
<el-button size="small" :disabled="!stepData.length" @click="revocation">撤销</el-button>
<el-button size="small" :disabled="!recoverStepData.length" @click="recover">恢复</el-button>
</el-button-group>
</div>
<div class="operation_box back_box">
<el-button size="small" @click="backRoute">返回</el-button>
<el-button size="small" @click="updateObjAxis">更新坐标</el-button>
</div>
<jlmap-visual ref="jlmapVisual" @onSelect="clickEvent" @onMenu="onContextmenu" />
</div>
<div class="map-draft">
<div v-show="viewDraft === 'draft'" class="box">
<map-operate
ref="mapOperate"
:map-info="mapInfo"
:selected="selected"
:map-saveing="mapSaveing"
@handleSelectPhysicalView="handleSelectPhysicalView"
@saveMapEvent="saveMapEvent"
@verifyMapEvent="verifyMapEvent"
@generateCIEvent="generateCIEvent"
@updateMapModel="updateMapModel"
@setCenter="setCenter"
@selectView="selectViewDraft"
@showMap="showMap"
/>
</div>
<div v-show="viewDraft != 'draft'" class="box">
<data-relation
ref="dataRelation"
:map-info="mapInfo"
:selected="selected"
@selectView="selectViewDraft"
@showMap="showMap"
/>
</div>
<config-map
ref="configMap"
@handleSelectPhysicalView="handleSelectPhysicalView"
/>
</div>
</div>
</transition>
</template>
<script>
import { saveMap, getMapDetail, verifyMap, postBuildMapImport, getRouteNewList, getAutoReentryList, generateCI } from '@/api/jmap/mapdraft';
import { ViewMode, TrainingMode, getDeviceMenuByDeviceType } from '@/scripts/ConstDic';
import { checkLoginLine } from '@/api/login';
import JlmapVisual from '@/views/newMap/jlmapNew/index';
import MapOperate from './mapoperate/index';
import { EventBus } from '@/scripts/event-bus';
import { mapGetters } from 'vuex';
import { } from '@/api/jmap/mapdraft';
import ConfigMap from './configMap';
import DataRelation from './dataRelation/index';
export default {
name: 'MapView',
components: {
JlmapVisual,
MapOperate,
DataRelation,
ConfigMap
},
data() {
return {
viewSelect: ViewMode.MIX,
mapSaveing: false,
ViewMode: ViewMode,
viewDraft: 'draft',
autoSaveTask: null,
selected: null,
mapInfo: { name: this.$t('map.pleaseSelectMap') },
timeDemon: null,
oldDevice: null,
size: {
width: document.documentElement.clientWidth - 521,
height: document.documentElement.clientHeight - 90
},
updtModel: {
code: '',
scaling: '',
origin: {
x: '',
y: ''
}
}
};
},
computed: {
...mapGetters('map', [
'stepData',
'recoverStepData'
]),
maskOpen() {
return this.$store.state.config.maskOpen;
}
},
watch: {
'$store.state.map.mapDataLoadedCount': function (val) {
this.initAutoSaveTask();
},
'$store.state.app.windowSizeCount': function() {
this.setWindowSize();
},
$route() {
this.clearAutoSave();
this.$nextTick(() => {
this.loadInitPage();
});
}
},
mounted() {
this.setWindowSize();
this.loadInitPage();
this.timeDemon = setInterval(() => {
checkLoginLine();
}, 5000 * 60);
EventBus.$on('SELECTON', () => {
this.selected = null;
});
},
beforeDestroy() {
EventBus.$off('SELECTON');
this.clearAutoSave();
this.$store.dispatch('map/mapClear');
if (this.timeDemon) {
clearTimeout(this.timeDemon);
}
},
methods: {
getMapOrigin() {
const dataZoom = this.$store.state.map.dataZoom;
if (dataZoom && dataZoom.offsetX) {
this.updtModel.origin.x = Number.parseInt(dataZoom.offsetX);
this.updtModel.origin.y = Number.parseInt(dataZoom.offsetY);
this.updtModel.scaling = dataZoom.scaleRate;
}
},
updateObjAxis() {
this.getMapOrigin();
this.$confirm('您确认按当前绘图位置更新坐标及缩放比例?', this.$t('tip.hint'), {
confirmButtonText: this.$t('tip.confirm'),
cancelButtonText: this.$t('tip.cancel'),
type: 'warning'
}).then(() => {
const map = this.$store.state.map.map;
console.log(map, '======');
this.$store.dispatch('map/saveMapDeviceDefaultRelations').then(() => {
const param = {
mapId: this.$route.params.mapId,
skinVO: {
code: this.$store.state.map.map.skinVO.code,
name: this.$store.state.map.map.skinVO.name,
origin: {
x: this.updtModel.origin.x,
y: this.updtModel.origin.y
},
scaling: this.updtModel.scaling
}
};
saveMap(Object.assign(map, param)).then(response => {
this.$message.success(this.$t('map.updateSuccessfully'));
}).catch(() => {
this.$messageBox(this.$t('map.updateFailed'));
});
});
}).catch(() => { });
},
setWindowSize() {
this.$nextTick(() => {
const width = this.$store.state.app.width - 521;
const height = this.$store.state.app.height - 90;
this.$store.dispatch('config/resize', { width, height });
});
},
endViewLoading(isSuccess) {
if (!isSuccess) {
this.$store.dispatch('map/mapClear');
}
this.$nextTick(() => {
EventBus.$emit('viewLoading', false);
});
},
showMap() { // 显示地图元素
this.$refs.configMap.doShow();
},
selectViewDraft(data) {
this.viewDraft = data;
if (data != 'draft') {
this.$refs.dataRelation.initLoad();
}
},
loadInitPage() {
this.$store.dispatch('training/changeMode', { mode: TrainingMode.MAP_EDIT });
this.mapInfo = { name: this.$t('map.pleaseSelectMap'), id: this.$route.params.mapId };
if (parseInt(this.mapInfo.id)) {
this.mapInfo.name = this.$route.query.name;
getMapDetail(this.$route.params.mapId).then(response => {
this.$store.dispatch('map/setMapData', response.data).then(resp => {
this.$store.dispatch('training/setMapDefaultState');
});
this.setDelayUnlockStatus(response.data, '00');
this.initAutoSaveTask();
}).catch((error) => {
console.log(error, '加载地图错误提示');
this.$message.error(this.$t('tip.failedLoadMap'));
this.endViewLoading();
});
} else {
this.endViewLoading();
}
},
initAutoSaveTask() {
const timeout = 1000 * 60 * 3;
this.clearAutoSave(this.autoSaveTask);
if (this.viewDraft == 'draft') {
this.autoSaveTask = setInterval(this.saveMapEvent, timeout);
}
},
clearAutoSave() {
if (this.autoSaveTask) {
clearInterval(this.autoSaveTask);
this.autoSaveTask = null;
}
},
generateCIEvent() {
this.$confirm('生成联锁关系会删除旧的联锁关系,是否继续生成', {
confirmButtonText: '继续',
cancelButtonText: this.$t('tip.cancel'),
type: 'warning'
}).then(() => {
generateCI(this.$route.params.mapId).then(resp => {
this.$message.success('生成并保存联锁关系成功!');
}).catch(()=> {
this.$message.error('生成并保存联锁关系失败!');
});
});
},
handleSelectControlPage (model) {
if (this.$refs.mapOperate) {
this.$refs.mapOperate.handleSelectControlPage(model);
this.$store.dispatch('menuOperation/setMapDrawSelectCount');
}
},
handleSelectPhysicalView(handle) {
if (this.$refs.jlmapVisual) {
this.$refs.jlmapVisual.setLevelVisible(handle);
}
},
clickEvent(em) {
const device = this.getDeviceByEm(em);
this.deviceHighLight(this.oldDevice, false);
this.deviceHighLight(device, true);
this.oldDevice = device;
this.onSelect(device);
if (this.$refs.dataRelation && this.viewDraft != 'draft') {
this.$refs.dataRelation.setSelected(device);
}
},
// 获取设备数据
getDeviceByEm(em) {
var device = this.$store.getters['map/getDeviceByCode'](em.deviceCode) || null;
if (device) {
device._viewVal = em.val;
}
return device;
},
onSelect(device) {
this.selected = device || null;
this.selected && this.handleSelectControlPage(device);
},
onContextmenu(em) {
this.point = {
x: em.clientX,
y: em.clientY
};
if (!em.deviceType) {
var menu = getDeviceMenuByDeviceType('Cancel');
this.$store.dispatch('menuOperation/setPopMenu', { position: this.point, menu: menu });
}
},
verifySectionPoint(map) { // 校验区段坐标不为空
let flag = true;
map.sectionList.forEach(elem => {
if (elem.points.length > 0) {
for (let index = 0; index < elem.points.length; index++) {
if (String(elem.points[index].x) == 'undefined' || String(elem.points[index].y) == 'undefined') {
this.$message(`${elem.name}${this.$t('tip.sectionPointsDeficiency')}`);
flag = false;
}
}
} else {
this.$message(this.$t('tip.sectionPointsDeficiency'));
flag = false;
}
});
return flag;
},
verifySectionRelation(map) {
let flag = true;
const tipInfoList = [];
map.sectionList.forEach(section => {
section.type === '01' && map.sectionList.forEach(item => {
if (section.code !== item.code && item.type === '01' && this.checkSectionPointsHasCoincide(section.points, item.points) && !this.checkCorrelation(section, item)) {
tipInfoList.push('区段' + section.name + '(' + section.code + '): 或者区段' + item.name + '(' + item.code + ')' + '关联关系设置错误!' );
}
});
});
if (!tipInfoList.length) {
flag = true;
} else {
flag = false;
this.$messageBox(this.$t('tip.dataValidationFailed'));
this.tableToExcel(tipInfoList);
}
return flag;
},
async verifyInterlockDevice(map) {
let flag = true;
const tipInfoList = [];
const routeCodeList = [];
const cycleCodeList = [];
const resp1 = await getRouteNewList(this.$route.params.mapId, {pageSize:9999, pageNum:1});
if (resp1.data && resp1.data.list) {
resp1.data.list.forEach(item => {
routeCodeList.push(item.code);
});
}
const resp2 = await getAutoReentryList(this.$route.params.mapId, {pageSize:9999, pageNum:1});
if (resp2.data && resp2.data.list) {
resp2.data.list.forEach(item => {
cycleCodeList.push(item.code);
});
}
map.cycleButtonList.forEach(cycleButton => {
if (!cycleCodeList.includes(cycleButton.cycleCode)) {
flag = false;
tipInfoList.push('自动折返功能按钮' + cycleButton.name + '(' + cycleButton.code + ')' + '的关联自动折返数据不存在!');
}
});
map.automaticRouteButtonList.forEach(routeButton => {
if (!routeCodeList.includes(routeButton.automaticRouteCode)) {
flag = false;
tipInfoList.push('自动进路功能按钮' + routeButton.name + '(' + routeButton.code + ')' + '的关联进路数据不存在!');
}
});
if (!flag) {
this.$messageBox(this.$t('tip.dataValidationFailed'));
this.tableToExcel(tipInfoList);
}
return flag;
},
verifyStationPosition(map) {
let flag = true;
const tipInfoList = [];
map.stationStandList.forEach(stationStand => {
const section = this.$store.getters['map/getDeviceByCode'](stationStand.standTrackCode);
const list = [];
section.points.forEach(point => {
list.push(point.x);
});
if (stationStand.position.x > Math.max(...list) || stationStand.position.x < Math.min(...list)) {
flag = false;
tipInfoList.push('站台' + stationStand.name + '(' + stationStand.code + ')' + '位置偏移出关联站台轨,请检查关联站台轨是否正确!');
}
});
if (!flag) {
this.$messageBox(this.$t('tip.dataValidationFailed'));
this.tableToExcel(tipInfoList);
}
return flag;
},
verifySignalPosition(map) {
let flag = true;
const tipInfoList = [];
map.signalList.forEach(signal => {
const section = this.$store.getters['map/getDeviceByCode'](signal.sectionCode);
if (section) {
const offsetX = signal.positionPoint ? signal.positionPoint.x : 0;
const signalPositionX = signal.position.x - offsetX;
const max = Math.max(section.points[section.points.length - 1].x, section.points[0].x);
const min = Math.min(section.points[section.points.length - 1].x, section.points[0].x);
if (signalPositionX < min && signalPositionX > max) {
tipInfoList.push('信号机' + signal.name + '(' + signal.code + ')未在其关联的区段' + section.name + '(' + section.code + ')里');
}
// if (signal.right) {
// const rightSection = this.$store.getters['map/getDeviceByCode'](section.rightSectionCode);
// if (rightSection && rightSection.points[0].x != section.points[section.points.length - 1].x) {
// const max = Math.max(section.points[section.points.length - 1].x, section.points[0].x);
// const min = Math.min(section.points[section.points.length - 1].x, section.points[0].x);
// if (signalPositionX < min && signalPositionX > max) {
// tipInfoList.push('信号机' + signal.name + '(' + signal.code + ')未在其关联的区段' + section.name + '(' + section.code + ')里');
// }
// } else {
// if (signalPositionX > section.points[section.points.length - 1].x && signalPositionX < section.points[0].x) {
// tipInfoList.push('信号机' + signal.name + '(' + signal.code + ')未在其关联的区段' + section.name + '(' + section.code + ')里');
// }
// }
// } else {
// const leftSection = this.$store.getters['map/getDeviceByCode'](section.leftSectionCode);
// if (leftSection && leftSection.points[leftSection.points.length - 1].x != section.points[0].x) {
// const max = Math.max(section.points[section.points.length - 1].x, section.points[0].x);
// const min = Math.min(section.points[section.points.length - 1].x, section.points[0].x);
// if (signalPositionX < min && signalPositionX > max) {
// tipInfoList.push('信号机' + signal.name + '(' + signal.code + ')未在其关联的区段' + section.name + '(' + section.code + ')里');
// }
// } else {
// if (signalPositionX < section.points[0].x && signalPositionX > section.points[section.points.length - 1].x) {
// tipInfoList.push('信号机' + signal.name + '(' + signal.code + ')未在其关联的区段' + section.name + '(' + section.code + ')里');
// }
// }
// }
} else {
tipInfoList.push('信号机' + signal.name + '(' + signal.code + ')所关联的区段不存在');
}
});
if (!tipInfoList.length) {
flag = true;
} else {
flag = false;
this.$messageBox(this.$t('tip.dataValidationFailed'));
this.tableToExcel(tipInfoList);
}
return flag;
},
checkPointsCoincide(point1, point2) { // 校验两点是否重合
if (point1 && point2) {
return point1.x === point2.x && point1.y === point2.y;
}
return false;
},
checkSectionPointsHasCoincide(points1, points2) { // 校验两区段的左右点是否有重合
return points1.length && points2.length && (this.checkPointsCoincide(points1[0], points2[0]) || this.checkPointsCoincide(points1[0], points2[points2.length - 1]) || this.checkPointsCoincide(points1[points1.length - 1], points2[points2.length - 1]) || this.checkPointsCoincide(points1[points1.length - 1], points2[0]));
},
checkCorrelation(section1, section2) { // 校验后者是否与前者有关联关系
return section1.leftSectionCode === section2.code || section1.rightSectionCode === section2.code;
},
saveMapEvent() { // 保存地图
const map = this.$store.state.map.map;
// map.signalList.forEach(item => {
// item.namePosition = { x: 0, y: 0 };
// item.lampPositionType = '02';
// });
if (this.$refs.jlmapVisual && map && parseInt(this.$route.params.mapId)) {
if (this.verifySectionPoint(map)) {
this.mapSaveing = true;
this.$store.dispatch('map/saveMapDeviceDefaultRelations').then(() => { // 草稿地图关系处理
saveMap(Object.assign(map, { mapId: this.$route.params.mapId })).then(response => {
this.$message.success(this.$t('tip.saveSuccessfully'));
this.mapSaveing = false;
this.initAutoSaveTask();
}).catch(error => {
console.log(error);
this.$messageBox(this.$t('tip.saveFailed'));
this.mapSaveing = false;
if (error.code === 40004 || error.code === 40005 || error.code === 40003) {
this.clearAutoSave();
} else {
this.initAutoSaveTask();
}
});
}).catch(error => {
console.log(error, '错误提示');
this.mapSaveing = false;
this.$message(this.$t('tip.saveFailed'));
});
}
}
},
async verifyMapEvent() {
if (this.$refs.jlmapVisual) {
const map = this.$store.state.map.map;
if (map && this.$route.params.mapId) {
const checkInterlockDevice = await this.verifyInterlockDevice(map);
if (this.verifySectionRelation(map) && this.verifySignalPosition(map) && checkInterlockDevice && this.verifyStationPosition(map)) {
verifyMap(this.$route.params.mapId).then(res => {
if (res.data.length) {
this.tableToExcel(res.data);
this.$messageBox(this.$t('tip.dataValidationFailed'));
} else {
this.$message.success(this.$t('tip.dataValidationSuccess'));
}
}).catch(() => {
this.$message.error(this.$t('tip.requestFailed'));
});
}
}
}
},
tableToExcel(data) {
const filterVal = ['index'];
const arr = [];
data.forEach(item => {
arr.push({ index: item });
});
const dataList = this.formatJson(filterVal, arr);
import('@/utils/Export2Excel').then(excel => {
excel.export_json_to_excel([this.$t('tip.dataQuestion')], dataList, this.$t('tip.dataList'));
});
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]));
},
setDelayUnlockStatus(data, status) {
if (data && data.delayShowList) {
data.delayShowList.forEach(elem => {
elem.status = status;
});
}
},
backRoute() {
this.$router.push({ path: `/design/usermap/home` });
},
// // 增加数据数据 给vuex map对象中
addOrUpdateMapModel(obj) {
this.$store.dispatch('map/updateMapDevices', obj);
},
updateMapModel(models) {
this.$store.dispatch('map/updateMapDevices', models);
},
// 撤销
revocation() {
this.$store.dispatch('map/setRevocation');
},
// 恢复
recover() {
this.$store.dispatch('map/setRecover');
},
// 设置显示中心
setCenter(code) {
this.$refs.jlmapVisual.setCenter(code);
const device = this.$store.getters['map/getDeviceByCode'](code);
this.deviceHighLight(this.oldDevice, false);
this.deviceHighLight(device, true);
this.oldDevice = device;
},
createMap() {
this.$refs.mapCreate.show();
},
importf() { // 导入地图jsons数据
const loading = this.$loading({
lock: true,
text: '正在导入中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
setTimeout(() => {
const obj = this.$refs.files;
if (!obj.files) return;
const f = obj.files[0];
const reader = new FileReader();
const that = this;
reader.readAsText(f, 'utf-8');
reader.onload = function(e) {
const data = e.target.result;
postBuildMapImport(JSON.parse(data)).then(res => {
loading.close();
that.$message.success('导入成功!');
that.refresh();
loading.close();
}).catch(error => {
loading.close();
that.$message.error('导入失败' + error.message);
});
obj.value = '';
};
});
},
// 高亮设备
deviceHighLight(device, flag) {
if (device && device.instance && typeof device.instance.drawSelected === 'function' ) {
if (device._type === 'Section' && device.type === '04') {
device.relevanceSectionList.forEach(item => {
const sectionModel = this.$store.getters['map/getDeviceByCode'](item);
sectionModel && sectionModel.instance.drawSelected(flag);
});
} else if (device._type === 'Section' && device.type === '01' && device.logicSectionCodeList && device.logicSectionCodeList.length) {
device.logicSectionCodeList.forEach(item => {
const sectionModel = this.$store.getters['map/getDeviceByCode'](item);
sectionModel && sectionModel.instance.drawSelected(flag);
});
} else {
device.instance.drawSelected(flag);
}
}
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss";
.mask{
opacity: 0;
background: #000;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9;
}
.operation_box{
position: absolute;
right: 20px;
top: 15px;
z-index: 9;
}
.back_box{
left: 150px;
display: inline-block;
width: 180px;
}
.map-draft{
/deep/{
.v-modal{
opacity: 0;
}
}
}
.box{
height: 100%;
overflow: hidden;
}
.mapPaint{
height: 100%;
overflow: hidden;
position: relative;
}
.map-view {
float: left;
width: calc(100% - 520px);
position: relative;
}
.map-draft {
float: right;
width: 520px;
height: 100%;
// /deep/ .el-scrollbar__view {
// width: 510px !important;
// height: calc(100% - 40px);
// }
}
.physical-view {
line-height: 25px;
height: 60px;
padding-left: 12px;
.el-checkbox {
width: 70px;
margin: 0;
margin-right: 12px;
}
}
.uploadDemo {
position: relative;
overflow: hidden;
float: right;
padding: 3px 0;
margin-right: 3px;
cursor: pointer;
input {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: 0;
cursor: pointer;
}
}
</style>