This commit is contained in:
lVAL 2021-01-13 17:45:49 +08:00
commit 9f4155b70d
8 changed files with 238 additions and 100 deletions

View File

@ -141,6 +141,24 @@ class SkinCode extends defaultStyle {
},
trainPosition:{
display: false // 列车实时位置显示
},
cross:{ // 岔心
centerSquare:{
defaultColor:'#000'
},
crossSection:{
fillColor:'#ff0',
strokeColor:'#fff',
width:1
},
text:{
fontSize: 8, // 字体大小
fontWeight: 'normal', // 字体粗细
fontColor: '#FFFFFF', // 字体颜色
textAlign: 'center', // 水平对齐方式
textPosition: 'inside', // 文字位置
textVerticalAlign: 'middle' // 文字垂直对齐方式
}
}
};

View File

@ -1,8 +1,11 @@
import Group from 'zrender/src/container/Group';
import Polyline from 'zrender/src/graphic/shape/Polyline';
import Isogon from 'zrender/src/graphic/shape/Isogon';
import Text from 'zrender/src/graphic/Text';
import BezierCurve from 'zrender/src/graphic/shape/BezierCurve';
import JTriangle from '../../utils/JTriangle';
import {segmentsIntr} from '@/utils/index';
import store from '@/store/index';
/** 创建区段线集合*/
export default class ELines extends Group {
@ -22,10 +25,126 @@ export default class ELines extends Group {
this.createLine();
}
if (model.type == '05') {
this.createCross();
}
}
createCross() {
const model = this.model.modelData;
const style = this.model.style;
const relateSectionList = model.relateSectionList;
const sectionA = store.getters['map/getDeviceByCode'](relateSectionList[0]);
const sectionB = store.getters['map/getDeviceByCode'](relateSectionList[1]);
const endPointA = sectionA.points[sectionA.points.length - 1];
const startPointA = sectionA.points[0];
const endPointB = sectionB.points[sectionB.points.length - 1];
const startPointB = sectionB.points[0];
const result = segmentsIntr(startPointA, endPointA, startPointB, endPointB);
// this.cross = new Polyline({
// zlevel: this.zlevel,
// z: this.z + 5,
// shape: {
// points: points
// },
// style: {
// // lineWidth: this.style.Section.cross.crossSection.width,
// fill:this.style.Section.cross.crossSection.fillColor
// // stroke: this.style.Section.cross.crossSection.strokeColor
// }
// });
const offset = style.Section.line.width / 2;
const triangleA = new JTriangle(startPointA, endPointA);
const triangleB = new JTriangle(startPointB, endPointB);
let lineDirect = 1;
if (triangleA.getRotation() > 0) { lineDirect = -1; } else { lineDirect = 1; }
const new1Point1 = {x:startPointA.x - lineDirect * offset * triangleA.getSinRate(), y:startPointA.y - offset * triangleA.getCosRate()};
const new1Point2 = {x:startPointA.x + lineDirect * offset * triangleA.getSinRate(), y:startPointA.y + offset * triangleA.getCosRate()};
const new2Point1 = {x:endPointA.x - lineDirect * offset * triangleA.getSinRate(), y:endPointA.y - offset * triangleA.getCosRate()};
const new2Point2 = {x:endPointA.x + lineDirect * offset * triangleA.getSinRate(), y:endPointA.y + offset * triangleA.getCosRate()};
if (triangleB.getRotation() > 0) { lineDirect = -1; } else { lineDirect = 1; }
const new3Point1 = {x:startPointB.x + lineDirect * offset * triangleB.getSinRate(), y:startPointB.y + offset * triangleB.getCosRate()};
const new3Point2 = {x:startPointB.x - lineDirect * offset * triangleB.getSinRate(), y:startPointB.y - offset * triangleB.getCosRate()};
const new4Point1 = {x:endPointB.x + lineDirect * offset * triangleB.getSinRate(), y:endPointB.y + offset * triangleB.getCosRate()};
const new4Point2 = {x:endPointB.x - lineDirect * offset * triangleB.getSinRate(), y:endPointB.y - offset * triangleB.getCosRate()};
// getCosRate
// getSinRate
const point1 = segmentsIntr(new1Point1, new2Point1, new3Point2, new4Point2);
const point2 = segmentsIntr(new1Point1, new2Point1, new3Point1, new4Point1);
const point3 = segmentsIntr(new1Point2, new2Point2, new3Point1, new4Point1);
const point4 = segmentsIntr(new1Point2, new2Point2, new3Point2, new4Point2);
const centerSquarePoints = [
// [new3Point1.x, new3Point1.y],
// [new3Point2.x, new3Point2.y],
// [new4Point2.x, new4Point2.y],
// [new4Point1.x, new4Point1.y]
[point1.x, point1.y],
[point2.x, point2.y],
[point3.x, point3.y],
[point4.x, point4.y],
[point1.x, point1.y]
];
const crossSectionPoints = [
[new1Point1.x, new1Point1.y],
[new1Point2.x, new1Point2.y],
[point4.x, point4.y],
[new4Point2.x, new4Point2.y],
[new4Point1.x, new4Point1.y],
[point3.x, point3.y],
[new2Point2.x, new2Point2.y],
[new2Point1.x, new2Point1.y],
[point2.x, point2.y],
[new3Point1.x, new3Point1.y],
[new3Point2.x, new3Point2.y],
[point1.x, point1.y],
[new1Point1.x, new1Point1.y]
];
this.crossSection = new Polyline({
zlevel: this.zlevel,
z: this.z + 6,
shape: {
points: crossSectionPoints
},
style: {
lineWidth:0,
fill:style.Section.cross.crossSection.fillColor
}
});
this.centerSquare = new Polyline({
zlevel: this.zlevel,
z: this.z + 7,
shape: {
points: centerSquarePoints
},
style: {
lineWidth:0,
fill:style.Section.cross.centerSquare.defaultColor
}
});
this.crossText = new Text({
zlevel: this.zlevel,
z: this.z + 8,
style: {
x: result.x + model.namePosition.x,
y: result.y + model.namePosition.y,
fontWeight: style.Section.cross.text.fontWeight,
fontSize: style.Section.cross.text.fontSize,
fontFamily: style.Section.cross.text.fontFamily || style.fontFamily,
text: model.name,
textFill:style.Section.cross.text.fontColor,
textAlign: style.Section.cross.text.textAlign,
textPosition: style.Section.cross.text.textPosition,
textVerticalAlign: style.Section.cross.text.textVerticalAlign
}
});
this.add(this.crossSection);
this.add(this.centerSquare);
this.add(this.crossText);
}
createLine() {
const model = this.model.modelData;
const style = this.model.style;
@ -242,6 +361,8 @@ export default class ELines extends Group {
}
show() {
this.section && this.section.show();
this.crossSection && this.crossSection.show();
this.centerSquare && this.centerSquare.show();
}
animateStyle(loop, animates) {
@ -353,6 +474,8 @@ export default class ELines extends Group {
getBoundingRect() {
if (this.section) {
return this.section.getBoundingRect().clone();
} else if (this.crossSection) {
return this.crossSection.getBoundingRect().clone();
}
}

View File

@ -36,39 +36,51 @@ export default class Section extends Group {
create() {
// 区段type 01计轴区段02逻辑区段03道岔区段 04道岔计轴区段 05 岔心
// 站台所有的绘图元素
const elementTypeList = {
'name': ETextName, // 区段名称
'logicText': ETextName, // 逻辑区段名称
'standTrackText': ETextName, // 站台轨名称
'reentryTrackText': ETextName, // 折返轨名称
'transferTrackText': ETextName, // 转换轨名称
'destinationText': ETextName, // 目的码名称
'line': ELines, // 创建区段
'lineBorder': ELines, // 哈尔滨线路点击背景色
'sectionBlock': EblockLines, // 哈尔滨线路区段(封锁显示)
'stopRouteImg': EStopRouteImg, // 宁波三线路特有
'axle': EAxle, // 计轴 (西安二号线 )
'separator': ESeparator, // 分隔符
'speedLimit': ELimitLines, // 限速线
'speedLimitName': ELimitName, // 限速线名称
'shuttleBack': EBackArrowGroup // 折返箭头 (成都三号线显示)
};
// 遍历当前线路下的绘图元素
const model = this.model;
const style = this.style;
const currentTypeList = style.Section.elemnetType;
currentTypeList.forEach(element => {
const ClassName = elementTypeList[element];
const elementZ = style.Section[element] ? style.Section[element].z ? style.Section[element].z : 0 : 0;
this[element] = new ClassName({
if (this.model.type == '05') {
this.line = new ELines({
zlevel: this.zlevel,
z: this.z + elementZ,
style: style,
type: element,
modelData: model
z: this.z,
style: this.style,
// type: element,
modelData: this.model
});
this.add(this[element]);
});
this.add(this.line);
} else {
const elementTypeList = {
'name': ETextName, // 区段名称
'logicText': ETextName, // 逻辑区段名称
'standTrackText': ETextName, // 站台轨名称
'reentryTrackText': ETextName, // 折返轨名称
'transferTrackText': ETextName, // 转换轨名称
'destinationText': ETextName, // 目的码名称
'line': ELines, // 创建区段
'lineBorder': ELines, // 哈尔滨线路点击背景色
'sectionBlock': EblockLines, // 哈尔滨线路区段(封锁显示)
'stopRouteImg': EStopRouteImg, // 宁波三线路特有
'axle': EAxle, // 计轴 (西安二号线 )
'separator': ESeparator, // 分隔符
'speedLimit': ELimitLines, // 限速线
'speedLimitName': ELimitName, // 限速线名称
'shuttleBack': EBackArrowGroup // 折返箭头 (成都三号线显示)
};
// 遍历当前线路下的绘图元素
const model = this.model;
const style = this.style;
const currentTypeList = style.Section.elemnetType;
currentTypeList.forEach(element => {
const ClassName = elementTypeList[element];
const elementZ = style.Section[element] ? style.Section[element].z ? style.Section[element].z : 0 : 0;
this[element] = new ClassName({
zlevel: this.zlevel,
z: this.z + elementZ,
style: style,
type: element,
modelData: model
});
this.add(this[element]);
});
}
}
/** 设置区段恢复默认状态*/

View File

@ -160,6 +160,31 @@ export function deepAssign(obj, item) {
return Object.assign(obj, target);
}
// 求解 两线段的交点
export function segmentsIntr(a, b, c, d) {
// 三角形abc 面积的2倍
var area_abc = (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
// 三角形abd 面积的2倍
var area_abd = (a.x - d.x) * (b.y - d.y) - (a.y - d.y) * (b.x - d.x);
// 面积符号相同则两点在线段同侧,不相交 (对点在线段上的情况,本例当作不相交处理);
if ( area_abc * area_abd >= 0 ) {
return false;
}
// 三角形cda 面积的2倍
var area_cda = (c.x - a.x) * (d.y - a.y) - (c.y - a.y) * (d.x - a.x);
// 三角形cdb 面积的2倍
// 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出.
var area_cdb = area_cda + area_abc - area_abd;
if ( area_cda * area_cdb >= 0 ) {
return false;
}
// 计算交点坐标
var t = area_cda / ( area_abd - area_abc );
var dx = t * (b.x - a.x);
var dy = t * (b.y - a.y);
return { x: a.x + dx, y: a.y + dy };
}
// export function deepAssign(obj, item) {
// function * colneData(item) {
// for (const keys in item) {

View File

@ -159,8 +159,7 @@ export default {
this.questionList = res.data;
if (this.isTest) {
this.questionList.forEach((question, index)=>{
// answerOptionId:[]
this.hasAnswerList[index] = {questionId:question.id, answerContents:[]};
this.hasAnswerList[index] = {questionId:question.id, answerOptionId:[]};
});
}
if (this.mode == 'practice') {
@ -176,14 +175,6 @@ export default {
this.wrongQuestionNum = 0;
this.loading = false;
}
}).catch(error=>{
if (error.code == '10007') {
this.$messageBox('获取试卷失败:试题不存在');
} else if (error.code == '10011') {
this.$messageBox('获取试卷失败:缺少出题规则');
} else {
this.$messageBox('获取试卷失败,请稍后再试');
}
});
this.dialogVisible = true;
},
@ -258,18 +249,13 @@ export default {
},
checkCurrentData(currentQuestionNum) {
if (this.hasAnswerList[currentQuestionNum]) {
const answerObj = this.hasAnswerList[currentQuestionNum].answerContents;
// answerOptionId;
const answerObj = this.hasAnswerList[currentQuestionNum].answerOptionId;
if (answerObj.length > 0) {
const question = this.questionList[currentQuestionNum];
if (question.type == 'judge' || question.type == 'select') {
this.currentRadioAnswer = answerObj[0].optionId;
this.currentRadioAnswer = answerObj[0];
} else {
const data = [];
answerObj.forEach(each=>{
data.push(each.optionId);
});
this.currentSelectAnswer = data;
this.currentSelectAnswer = answerObj;
}
} else {
this.currentSelectAnswer = [];
@ -284,7 +270,7 @@ export default {
const submitData = Object.values(this.hasAnswerList);
let submitWriteLength = 0;
submitData.forEach(each=>{
if (each.answerContents.length > 0) {
if (each.answerOptionId.length > 0) {
submitWriteLength++;
}
});
@ -327,7 +313,6 @@ export default {
}
}).catch(()=>{
this.loading = false;
this.$message.error('提交失败,请稍后再试');
});
},
@ -393,23 +378,13 @@ export default {
},
changeAnswer(data) {
if (this.isTest) {
let answerContents = [];
let answerOptionId = [];
if (data instanceof Array) {
data.forEach(each=>{
const answerList = this.questionList[this.currentQuestionNum].optionList;
const answerContent = answerList.find(answer=>{ return answer.id == each; });
if (answerContent) {
answerContents.push({optionId:each, answerContent:answerContent.content});
}
});
answerOptionId = data;
} else {
const answerList = this.questionList[this.currentQuestionNum].optionList;
const answerContent = answerList.find(answer=>{ return answer.id == data; });
if (answerContent) {
answerContents = [{optionId:data, answerContent:answerContent.content}];
}
answerOptionId = [data];
}
this.hasAnswerList[this.currentQuestionNum].answerContents = answerContents;
this.hasAnswerList[this.currentQuestionNum].answerOptionId = answerOptionId;
document.querySelector('#eachQuestionNum' + this.currentQuestionNum).classList.add('hasSelect');
}
}

View File

@ -11,6 +11,7 @@
import { mapGetters } from 'vuex';
import { getUID } from '@/jmapNew/utils/Uid';
import CreateOperate from '../components/createOperate';
import {segmentsIntr} from '@/utils/index';
export default {
name:'CrossDraft',
components: {
@ -111,32 +112,7 @@ export default {
const startPointA = sectionA.points[0];
const endPointB = sectionB.points[sectionB.points.length - 1];
const startPointB = sectionB.points[0];
return this.segmentsIntr(startPointA, endPointA, startPointB, endPointB);
},
segmentsIntr(a, b, c, d) {
// abc 2
var area_abc = (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
// abd 2
var area_abd = (a.x - d.x) * (b.y - d.y) - (a.y - d.y) * (b.x - d.x);
// 线, (线,);
if ( area_abc * area_abd >= 0 ) {
return false;
}
// cda 2
var area_cda = (c.x - a.x) * (d.y - a.y) - (c.y - a.y) * (d.x - a.x);
// cdb 2
// : .,.
var area_cdb = area_cda + area_abc - area_abd;
if ( area_cda * area_cdb >= 0 ) {
return false;
}
return true;
// //
// var t = area_cda / ( area_abd - area_abc );
// var dx = t * (b.x - a.x);
// var dy = t * (b.y - a.y);
// return { x: a.x + dx, y: a.y + dy };
return segmentsIntr(startPointA, endPointA, startPointB, endPointB);
},
updateMapDraw(standCode) {
@ -146,6 +122,7 @@ export default {
type:'05', //
namePosition:{x:50, y:0},
name:this.addModel.name,
points: [{ x: 0, y: 0 }, { x: 0, y: 0 }],
relateSectionList:this.addModel.relateSectionList,
stationCode:standCode
};

View File

@ -47,7 +47,7 @@
/>
</el-tab-pane>
<el-tab-pane class="view-control" :label="$t('map.cross')" name="six" :lazy="lazy">
<cross-section ref="crossSection" :field="field" @hover="hover" />
<cross-section ref="crossSection" :field="field" @hover="hover" @updateMapModel="updateMapModel" />
</el-tab-pane>
<tip-info ref="tipInfo" :tip-info-list="tipInfoList" />
</el-tabs>
@ -143,12 +143,12 @@ export default {
{ prop: 'namePosition.y', firstLevel: 'namePosition', secondLevel: 'y', label: 'y:', type: 'number', labelWidth: '25px' }
] },
{ prop: 'type', label: this.$t('map.sectionType'), type: 'select', optionLabel: 'name', optionValue: 'code', options: this.SectionTypeList, disabled: true }, //
{ prop: 'roadType', label: '线路类型:', type: 'select', optionLabel: 'name', optionValue: 'code', options: this.sectionRoadTypeList, clearable: true, isHidden: !this.isSwitchSectionType, deviceChange: this.roadTypeChange },
{ prop: 'roadType', label: '线路类型:', type: 'select', optionLabel: 'name', optionValue: 'code', options: this.sectionRoadTypeList, clearable: true, isHidden: !this.isSwitchSectionType || !this.isCrossSectionType, deviceChange: this.roadTypeChange },
{ prop: 'leftSectionCode', label: this.$t('map.leftAssociatedSection'), type: 'selectHover', optionLabel: 'name&&code', optionValue: 'code', clearable: true, options: this.switchAndPhySicalSectionList, hover: this.hover, buttonType: 'leftSection', buttonShowType: this.isLeftSectionButtonShow, isHidden: !this.hasAssociatedSection }, //
{ prop: 'rightSectionCode', label: this.$t('map.rightAssociatedSection'), type: 'selectHover', optionLabel: 'name&&code', optionValue: 'code', clearable: true, options: this.switchAndPhySicalSectionList, hover: this.hover, buttonType: 'rightSection', buttonShowType: this.isRightSectionButtonShow, isHidden: !this.hasAssociatedSection }, //
{ prop: 'parentCode', label: this.$t('map.associatedSection'), type: 'select', mode: true, optionLabel: 'name&&code', optionValue: 'code', disabled: true, options: this.sectionList, isHidden: !this.isParentCode }, // /code
{ prop: 'sepTypeLeft', label: this.$t('map.sepTypeLeft'), type: 'select', optionLabel: 'name', optionValue: 'code', options: this.SectionSepTypeList, isHidden: !this.isSwitchSectionType },
{ prop: 'sepTypeRight', label: this.$t('map.sepTypeRight'), type: 'select', optionLabel: 'name', optionValue: 'code', options: this.SectionSepTypeList, isHidden: !this.isSwitchSectionType },
{ prop: 'sepTypeLeft', label: this.$t('map.sepTypeLeft'), type: 'select', optionLabel: 'name', optionValue: 'code', options: this.SectionSepTypeList, isHidden: !this.isSwitchSectionType || !this.isCrossSectionType },
{ prop: 'sepTypeRight', label: this.$t('map.sepTypeRight'), type: 'select', optionLabel: 'name', optionValue: 'code', options: this.SectionSepTypeList, isHidden: !this.isSwitchSectionType || !this.isCrossSectionType },
{ prop: 'points', label: this.$t('map.segmentCoordinates'), type: 'points', width: '100px', isHidden: !this.isPointsShow, addPoint: this.addPoint, delPoint: this.delPoint, lastDisabled: true },
{ prop: 'logicSectionStartOffset', label: this.$t('map.logicalSectionStartOffset'), type: 'number', min: 0, width: '150px', isHidden: !this.isStationCodeDisabled, disabled: true }, //
{ prop: 'logicSectionEndOffset', label: this.$t('map.logicalSectionEndOffset'), type: 'number', min: 0, width: '150px', isHidden: !this.isStationCodeDisabled, disabled: true }, //
@ -186,7 +186,7 @@ export default {
{ value: true, label: this.$t('map.fromSmallToLarge') },
{ value: false, label: this.$t('map.fromLargeToSmall') }
] }, // 1
{ prop: 'curve', label: this.$t('map.isCurve'), type: 'checkbox', isHidden: !this.isSwitchSectionType },
{ prop: 'curve', label: this.$t('map.isCurve'), type: 'checkbox', isHidden: !this.isSwitchSectionType || !this.isCrossSectionType },
{ prop: 'relevanceSectionList', label: this.$t('map.associateSwitchSection'), type: 'multiSelect', optionLabel: 'name&&code', optionValue: 'code', options: this.switchSectionList, isHidden: this.isSwitchSectionType, disabled: true },
{ prop: 'leftAxlePosition', label: '左侧计轴:', type: 'select', optionLabel: 'label', optionValue: 'value', options: this.axlePositionList, isHidden: !this.hasAssociatedSection },
{ prop: 'leftAxleOffset', label: '左侧计轴偏移:', type: 'coordinate', width: '150px', isHidden: !this.leftAxlePositionShow, children: [
@ -205,11 +205,11 @@ export default {
item: [
{ prop: 'stationCode', label: this.$t('map.equipmentStation') + ':', type: 'select', mode: true, optionLabel: 'name&&code', optionValue: 'code', disabled: this.isStationCodeDisabled, options: this.centralizedStationList, isHidden: this.isStationCodeDisabled },
{ prop: 'belongStation', label: '所属车站:', type: 'select', mode: true, optionLabel: 'name&&code', optionValue: 'code', options: this.stationList, isHidden: !this.editModel.standTrack && !this.editModel.reentryTrack && !this.editModel.transferTrack },
{ prop: 'lengthFact', label: this.$t('map.actualLength') + ':', type: 'number', min: 0, placeholder: this.$t('map.meter'), isHidden: !this.isSwitchSectionType },
{ prop: 'lengthFact', label: this.$t('map.actualLength') + ':', type: 'number', min: 0, placeholder: this.$t('map.meter'), isHidden: !this.isSwitchSectionType || !this.isCrossSectionType },
{ prop: 'leftStopPointOffset', label: this.$t('map.leftStopPointOffset'), type: 'number', min: 0, max: this.maxLengthFact, isHidden: !this.isStopPointOffset }, //
{ prop: 'rightStopPointOffset', label: this.$t('map.rightStopPointOffset'), type: 'number', min: 0, max: this.maxLengthFact, isHidden: !this.isStopPointOffset }, //
{ prop: 'region', label: this.$t('map.sectionColon'), type: 'select', optionLabel: 'label', optionValue: 'value', options: this.regionList, isHidden: !this.sectionColonShow },
{ prop: 'trainWindowCode', label: '关联车次窗', type: 'input', disabled: true, isHidden: !this.isSwitchSectionShow }
{ prop: 'trainWindowCode', label: '关联车次窗', type: 'input', disabled: true, isHidden: !this.isSwitchSectionShow || !this.isCrossSectionType }
// { prop: 'kmRangeLeft', label: this.$t('map.leftKilometerMark'), type: 'number', min: 0, placeholder: this.$t('map.meter') },
// { prop: 'kmRangeRight', label: this.$t('map.rightKilometerMark'), type: 'number', min: 0, placeholder: this.$t('map.meter') }
]
@ -315,6 +315,9 @@ export default {
isStationCodeDisabled() {
return this.editModel.type == '02';
},
isCrossSectionType() {
return this.editModel.type !== '05';
},
isSwitchSectionType() {
return this.editModel.type !== '04';
},
@ -325,7 +328,7 @@ export default {
return this.editModel.type != '03' && !this.editModel.logicSectionCodeList.length;
},
isPointsShow() {
return this.editModel.type !== '04' && this.editModel.points.length > 0;
return this.editModel.type !== '04' && this.editModel.type !== '05' && this.editModel.points.length > 0;
},
isRelevanceSwitchShow() {
return this.editModel.type == '04' || this.editModel.type == '03';
@ -753,6 +756,9 @@ export default {
clear() {
this.editModel = getModel('Section');
this.$refs.dataform && this.$refs.dataform.resetFields(); //
},
updateMapModel(models) {
this.$emit('updateMapModel', models);
}
}
};

View File

@ -400,6 +400,8 @@ export default {
models.push(sectionModel);
});
this.$emit('updateMapModel', models);
this.field = '';
this.$emit('deviceSelect', '');
this.addModel = {
modelList: [],
positionY: 0