This commit is contained in:
zyy 2020-10-22 13:03:40 +08:00
commit 415486c815
51 changed files with 3545 additions and 2477 deletions

View File

@ -363,3 +363,11 @@ export function getAllConversition(group) {
method: 'get'
});
}
/** 语音播完的接口 */
export function overConversationMessage(group, conversationMessageId) {
return request({
url: `/api/v1/competitionPractical/${group}/audio/over/${conversationMessageId}`,
method: 'put'
});
}

View File

@ -183,3 +183,11 @@ export function setSandboxConfig(id, data) {
data: data
});
}
/** 添加/修改联锁工作站配置 */
export function setIlwConfig(id, data) {
return request({
url: `/api/device/${id}/config/ilw`,
method: 'put',
data: data
});
}

View File

@ -1,5 +1,26 @@
import request from '@/utils/request';
/**
* 获取运行图配置
*/
export function getRpConfig() {
return request({
url: `/api/rpTools/config`,
method: 'get'
})
}
/**
* 修改运行图配置
*/
export function modifyRpConfig(data) {
return request({
url: `/api/rpTools/config`,
method: 'put',
data
})
}
/**
* 获取运行图数据
*/
@ -41,6 +62,71 @@ export function delRpTrip(tripNo) {
})
}
/**
* 平移服务
*/
export function translateRpService(serviceNo, data) {
return request({
url: `/api/rpTools/${serviceNo}/service`,
method: 'put',
data
})
}
/**
* 删除服务
*/
export function delRpService(serviceNo) {
return request({
url: `/api/rpTools/${serviceNo}/service`,
method: 'delete'
})
}
/**
* 添加区域
*/
export function createRpArea(data) {
return request({
url: `/api/rpTools/area`,
method: 'post',
data
})
}
/**
* 修改区域
*/
export function modifyRpArea(areaNo, data) {
return request({
url: `/api/rpTools/${areaNo}/area`,
method: 'put',
data
})
}
/**
* 修改区域文字
*/
export function modifyAreaNote(areaNo, data) {
return request({
url: `/api/rpTools/${areaNo}/text`,
method: 'put',
data
})
}
/**
* 删除区域
*/
export function delRpArea(areaNo) {
return request({
url: `/api/rpTools/${areaNo}/area`,
method: 'delete'
})
}
/**
* 修改运行时间
*/
@ -52,7 +138,6 @@ export function justTripNoRunning(tripNo, data) {
})
}
/**
* 修改停站时间
*/
@ -65,14 +150,12 @@ export function justTripNoStop(tripNo, data) {
}
/**
* 平移车次
* 修改折返时间
*/
export function translateTripNo(tripNo, data) {
export function justTripTurnBack(tripNo, data) {
return request({
url: `/api/rpTools/${tripNo}/trip`,
url: `/api/rpTools/${tripNo}/turnBack`,
method: 'put',
data
})
}

View File

@ -84,5 +84,6 @@ export default {
sceneManage:'Scene manage',
companyManage: 'Company manage',
authorApply: 'Grant application',
AuthorList: 'Authorization code list'
AuthorList: 'Authorization code list',
questionsRuleManage: 'Question rule manage'
};

View File

@ -89,5 +89,6 @@ export default {
sceneManage:'场景列表',
companyManage: '单位管理',
authorApply: '授权申请',
AuthorList: '授权列表'
AuthorList: '授权列表',
questionsRuleManage: '出题规则管理'
};

View File

@ -278,6 +278,7 @@ export default class Switch extends Group {
this.shapeModelB.show();
this.shapeModelB.setColor(this.style.Section.line.spareColor);
this.shapeModelC.show();
this.shapeModelC.setColor(this.style.backgroundColor);
}
if (this.style.Switch.core.graphShow) { // 佛山线路显示
this.shapeModelB.show();
@ -324,8 +325,8 @@ export default class Switch extends Group {
.when(1000, { stroke: this.style.backgroundColor })
.start();
}
setSwitchFault(split) {
if (this.style.Switch.jointImg.faultStatus && split) { // 宁波线失表状态
setSwitchFault(split, normalPosition, reversePosition) {
if (this.style.Switch.jointImg.faultStatus && split && !reversePosition && !normalPosition ) { // 宁波线失表状态
this.setForkAction(); // 道岔挤岔
} else {
if (this.model.switchFaultCode && split) {
@ -511,6 +512,7 @@ export default class Switch extends Group {
setState(model) {
if (!this.isShowShape) return;
this.recover();
this.setSwitchFault(model.split, model.normalPosition, model.reversePosition);
if (model.normalPosition) {
this.setLocationAction(model); /** 定位*/
} else if (model.reversePosition) {
@ -519,7 +521,6 @@ export default class Switch extends Group {
this.setLossAction(); // 失去
}
model.isCiConfirm && this.setCiConfirm(); // 道岔使能显示
this.setSwitchFault(model.split);
model.singleLock && this.setMonolock(); // 道岔单锁
model.blockade && this.block(); // 道岔封锁

View File

@ -0,0 +1,268 @@
import { createSeriesModel, createMarkLineModels, createMartPoint } from './utils';
import { toTimeStamp } from '@/utils/date';
export default {
/** 边缘高度*/
EdgeHeight: 600,
/** 间隔高度*/
CoordMultiple: 1,
/** 偏移时间*/
TranslationTime: 0,
/** 将后台数据解析成图形*/
parseDataToGraph(chart, planData, stations, kmRangeCoordinateMap) {
const graphs = [];
if (planData &&
planData.areaList &&
planData.areaList.length) {
planData.areaList.forEach(area => {
const startTime = toTimeStamp(area.startTime);
const endTime = toTimeStamp(area.endTime);
const fartherKm = this.getCoordinateYByObj(stations, kmRangeCoordinateMap, {stationCode: area.fartherStationCode});
const closerKm = this.getCoordinateYByObj(stations, kmRangeCoordinateMap, {stationCode: area.closerStationCode});
const point1 = [ startTime, fartherKm];
const point2 = [ endTime, closerKm]
const position = chart.convertToPixel('grid', point1);
const position2 = chart.convertToPixel('grid', point2)
const width = Math.abs(position[0] - position2[0]);
const height = Math.abs(position[1] - position2[1]);
graphs.push({
type: 'rect',
subType: 'area',
areaNo: area.areaNo,
position,
point1,
point2,
model: area,
shape: {
x: 0,
y: 0,
width,
height
},
style: {
fill: 'rgb(255,0,0, 0.3)',
stroke: 'rgb(255, 0, 0, 0.8)'
},
z: 100
})
})
}
return graphs;
},
/** 将后台数据解析成折线*/
parseDataToSeries(chart, planData, stations, kmRangeCoordinateMap) {
const models = [];
if (planData &&
planData.serviceList &&
planData.serviceList.length) {
planData.serviceList.forEach((service,i) => {
if (service.tripList &&
service.tripList.length) {
service.tripList.forEach((trip,j) => {
const opt = {
name: `plan-${service.serviceNo}-${trip.tripNo}-${trip.direction}`,
type: 'line',
symbolSize: 1,
showAllSymbol: true,
markPoint: { data: [] },
data: []
};
var lastPoint = null;
var nextPoint = null;
var pointData = {
name: `${service.serviceNo}-${trip.tripNo}`,
color: '#000',
direction: trip.direction,
coord: [trip.stationTimeList[0].departureTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, trip.stationTimeList[0], trip.direction, false)],
};
opt.markPoint.data.push(createMartPoint(pointData));
trip.stationTimeList.forEach(elem => {
const name = `${trip.direction}${trip.tripNo}`;
if (elem.arrivalTime) {
opt.data.push([elem.arrivalTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, elem, elem.direction, false), {
stationCode: elem.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
name
}]);
}
if (elem.departureTime) {
opt.data.push([elem.departureTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, elem, elem.direction, false), {
stationCode: elem.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
name
}]);
}
});
const model = createSeriesModel(opt,
{ color: '#000', width: 1 },
{ color: '#000', fill: '#000'}
);
models.push(model);
if (service.tripList[j + 1] &&
service.tripList[j + 1].stationTimeList) {
const opt = {
name: `reentry-${service.serviceNo}-${trip.tripNo}-${trip.direction}`,
type: 'line',
symbolSize: 1,
showAllSymbol: false,
markPoint: { data: [] },
data: []
};
lastPoint = trip.stationTimeList[trip.stationTimeList.length-1];
nextPoint = service.tripList[j + 1].stationTimeList[0];
const name = `${trip.direction}${trip.tripNo}`;
opt.data.push([lastPoint.arrivalTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, lastPoint, trip.direction, false), {
stationCode: lastPoint.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
name
}]);
opt.data.push([lastPoint.arrivalTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, lastPoint, trip.direction, true), {
stationCode: lastPoint.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
name
}]);
opt.data.push([nextPoint.departureTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, lastPoint, trip.direction, true), {
stationCode: lastPoint.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
name
}]);
opt.data.push([nextPoint.departureTime, this.getCoordinateYByObj(stations, kmRangeCoordinateMap, lastPoint, trip.direction, false), {
stationCode: lastPoint.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
name
}]);
const model = createSeriesModel(opt,
{ color: '#000', width: 1 },
{ color: '#000', fill: '#000'}
);
models.push(model);
}
});
}
})
}
return models;
},
/** 更新数据并解析成折线*/
updateDataToModels(chart, planData, stations, kmRangeCoordinateMap, series) {
if (planData && planData.length) {
}
return series;
},
/** 初始化Y轴*/
initializeYaxis(stations) {
return createMarkLineModels(stations, (elem) => {
return this.EdgeHeight + elem.kmRange * this.CoordMultiple;
});
},
/** 将后台数据转换为试图序列模型*/
convertStationsToMap(stations) {
var map = {};
if (stations && stations.length) {
stations.forEach((elem) => {
map[`${elem.kmRange}`] = this.EdgeHeight + elem.kmRange * this.CoordMultiple;
});
}
return map;
},
/** 计算y轴最小值*/
computedYaxisMinValue(stations) {
return stations[0].kmRange * this.CoordMultiple;
},
/** 计算y轴最大值*/
computedYaxisMaxValue(stations) {
return stations[stations.length - 1].kmRange * this.CoordMultiple + this.EdgeHeight * 2;
},
/** 格式化y轴数据*/
computedFormatYAxis(stations, params) {
var yText = '0m';
stations.forEach(elem => {
if (elem.kmRange < parseInt(params.value) / this.CoordMultiple - this.EdgeHeight) {
yText = Math.floor(elem.kmRange) + 'm';
}
});
return yText;
},
/** 根据方向计算y折返偏移量*/
getYvalueByDirectionCode(defaultVlue, direction) {
if (direction === '1') {
defaultVlue -= this.EdgeHeight / 2;
} else if (direction === '2') {
defaultVlue += this.EdgeHeight / 2;
}
return defaultVlue;
},
/** 根据elem计算y值*/
getCoordinateYByObj(stations, kmRangeCoordinateMap, obj, direction, isSpecial) {
var defaultVlue = 0;
var station = stations.find(it => { return it.code == obj.stationCode; });
if (station) {
defaultVlue = kmRangeCoordinateMap[`${station.kmRange}`];
if (isSpecial) {
defaultVlue = this.getYvalueByDirectionCode(defaultVlue, direction);
}
}
return defaultVlue;
},
/** 通过y坐标获取站信息 */
getStationByCoordinate(stations, y) {
for(var i = stations.length-1; i >= 0; i--) {
const station = stations[i];
const edge = this.EdgeHeight
const preKm = i == 0? edge*2: Math.abs(station.kmRange-stations[i-1].kmRange)/2;
const nxtKm = i == stations.length-1? edge: Math.abs(station.kmRange-stations[i+1].kmRange)/2;
const min = edge + station.kmRange - preKm;
const max = edge + station.kmRange + nxtKm;
if (y >= min && y <= max) {
return station;
}
}
return null;
}
};

View File

@ -1,4 +1,5 @@
import { createMartPoint, createSeriesModel, createMarkLineModels, hexColor, prefixTime, convertSheetToList } from '@/utils/runPlan';
import { toTimeStamp } from '@/utils/date';
export default {
/** 边缘高度*/
@ -10,20 +11,65 @@ export default {
/** 偏移时间*/
TranslationTime: 0,
/** 将后台数据解析成图表*/
convertDataToModels(tripList, stations, kmRangeCoordMap, lineStyle) {
/** 将后台数据解析成图形*/
parseDataToGraph(chart, planData, stations, kmRangeCoordMap) {
const graphs = [];
if (planData &&
planData.areaList &&
planData.areaList.length) {
planData.areaList.forEach(el => {
const startTime = toTimeStamp(el.startTime);
const endTime = toTimeStamp(el.endTime);
const fartherKm = this.getCoordYByObj(stations, kmRangeCoordMap, {stationCode: el.fartherStationCode});
const closerKm = this.getCoordYByObj(stations, kmRangeCoordMap, {stationCode: el.closerStationCode});
const point1 = [ startTime, fartherKm];
const point2 = [ endTime, closerKm]
const position = chart.convertToPixel('grid', point1);
const position2 = chart.convertToPixel('grid', point2)
const width = Math.abs(position[0] - position2[0]);
const height = Math.abs(position[1] - position2[1]);
graphs.push({
type: 'rect',
subType: 'area',
areaNo: el.areaNo,
position,
point1,
point2,
model: el,
shape: {
x: 0,
y: 0,
width,
height
},
style: {
fill: 'rgb(255,0,0, 0.3)',
stroke: 'rgb(255, 0, 0, 0.8)'
},
z: 100
})
})
}
return graphs;
},
/** 将后台数据解析成折线*/
parseDataToSeries(chart, planData, stations, kmRangeCoordMap) {
var models = [];
/** 按车次遍历数据*/
if (tripList && tripList.length) {
tripList.forEach(trip => {
if (planData && planData.length) {
planData.forEach(trip => {
const opt = {
name: `run-${trip.tripNo}`,
name: `plan-${trip.tripNo}`,
type: 'line',
symbolSize: 1,
showAllSymbol: true,
lineStyle: {
color: '#000',
width: 1,
width: 1,
},
itemStyle: {
color: '#000',
@ -36,11 +82,11 @@ export default {
/** 计算停站点坐标集合*/
trip.stationTimeList.forEach((elem,idx) => {
if (elem.arrivalTime) {
opt.data.push([elem.arrivalTime, this.getCoordYByElem(stations, kmRangeCoordMap, elem), elem.stationCode, trip.tripNo]);
opt.data.push([elem.arrivalTime, this.getCoordYByObj(stations, kmRangeCoordMap, elem), elem.stationCode, trip.tripNo]);
}
if (elem.departureTime) {
opt.data.push([elem.departureTime, this.getCoordYByElem(stations, kmRangeCoordMap, elem), elem.stationCode, trip.tripNo]);
opt.data.push([elem.departureTime, this.getCoordYByObj(stations, kmRangeCoordMap, elem), elem.stationCode, trip.tripNo]);
}
});
@ -51,9 +97,9 @@ export default {
return models;
},
/** 更新数据并解析成图表*/
updateDataToModels(tripList, stations, kmRangeCoordMap, runPlanData, series, lineStyle) {
if (tripList && tripList.length) {
/** 更新数据并解析成折线*/
updateDataToModels(chart, planData, stations, kmRangeCoordMap, runPlanData, series) {
if (planData && planData.length) {
}
return series;
},
@ -108,7 +154,7 @@ export default {
},
/** 根据elem计算y值*/
getCoordYByElem(stations, kmRangeCoordMap, elem, directionCode, isSpecial) {
getCoordYByObj(stations, kmRangeCoordMap, elem, directionCode, isSpecial) {
var defaultVlue = 0;
var station = stations.find(it => { return it.code == elem.stationCode; });
if (station) {
@ -119,5 +165,24 @@ export default {
}
return defaultVlue;
}
},
/** 通过y坐标获取站信息*/
getStationByCoordinate(stations, y) {
for(var i = stations.length-1; i >= 0; i--) {
const station = stations[i];
const edge = this.EdgeHeight;
const rate = this.CoordMultiple;
const preKm = i == 0? edge*2: rate/2;
const nxtKm = i == stations.length-1? edge: rate/2;
const min = edge + i*rate - preKm;
const max = edge + i*rate + nxtKm;
if (y >= min && y <= max) {
return station;
}
}
return null;
}
};

View File

@ -1,4 +1,5 @@
import { createMartPointReverse, createSeriesModel, createMarkLineModels, hexColor, convertSheetToList, prefixTime } from '@/utils/runPlan';
import { createSeriesModel, createMarkLineModels, createRectArea, createMartPoint } from './utils';
import { toTimeStamp } from '@/utils/date';
export default {
/** 边缘高度*/
@ -10,63 +11,139 @@ export default {
/** 偏移时间*/
TranslationTime: 0,
/** 将后台数据解析成图表*/
convertDataToModels(tripList, stations, kmRangeCoordMap, lineStyle) {
var models = [];
/** 按车次遍历数据*/
if (tripList && tripList.length) {
tripList.forEach(trip => {
const opt = {
name: `run-${trip.tripNo}`,
type: 'line',
symbolSize: 1,
showAllSymbol: true,
lineStyle: {
color: '#000',
width: 1,
},
itemStyle: {
color: '#000',
fill: '#000'
},
markPoint: { data: [] },
data: []
};
/** 将后台数据解析成图形*/
parseDataToGraph(chart, planData, stations) {
const graphs = [];
if (planData &&
planData.areaList &&
planData.areaList.length) {
planData.areaList.forEach(area => {
const startTime = toTimeStamp(area.startTime);
const endTime = toTimeStamp(area.endTime);
// const length = trip.stationTimeList.length;
// if (trip.tripNo &&
// trip.stationTimeList.length) {
// opt.markPoint.data.push(createMartPointReverse({
// name: `${trip.tripNo}`,
// color: '#000' || lineStyle.color,
// coord: [
// trip.stationTimeList[0].arrivalTime,
// this.getCoordYByElem(stations, kmRangeCoordMap, trip.stationTimeList[0])
// ]
// }));
// }
const fartherKm = this.getCoordinateYByStationCode(stations, area.fartherStationCode);
const closerKm = this.getCoordinateYByStationCode(stations, area.closerStationCode);
const point1 = [ startTime, fartherKm];
const point2 = [ endTime, closerKm]
const position = chart.convertToPixel('grid', point1);
const position2 = chart.convertToPixel('grid', point2)
const width = Math.abs(position[0] - position2[0]);
const height = Math.abs(position[1] - position2[1]);
/** 计算停站点坐标集合*/
trip.stationTimeList.forEach((elem,idx) => {
if (elem.arrivalTime) {
opt.data.push([elem.arrivalTime, this.getCoordYByElem(stations, kmRangeCoordMap, elem), elem.stationCode, trip.tripNo]);
}
graphs.push(createRectArea({
areaNo: area.areaNo,
model: area,
position,
point1,
point2,
width,
height
}));
})
}
if (elem.departureTime) {
opt.data.push([elem.departureTime, this.getCoordYByElem(stations, kmRangeCoordMap, elem), elem.stationCode, trip.tripNo]);
}
});
return graphs;
},
models.push(opt);
});
/** 将后台数据解析成折线*/
parseDataToSeries(chart, planData, stations) {
const models = [];
if (planData &&
planData.serviceList &&
planData.serviceList.length) {
planData.serviceList.forEach((service,i) => {
if (service.tripList &&
service.tripList.length) {
const opt = {
name: `service${service.serviceNo}`,
type: 'line',
symbolSize: 1,
showAllSymbol: true,
markPoint: { data: [] },
data: []
};
service.tripList.forEach((trip,j) => {
var lastPoint = null;
var nextPoint = null;
var pointData = {
name: `${service.serviceNo}-${trip.tripNo}`,
color: '#000',
direction: trip.direction,
coord: [trip.stationTimeList[0].departureTime, this.getCoordinateYByStationCode(stations, trip.stationTimeList[0].stationCode)],
};
opt.markPoint.data.push(createMartPoint(pointData));
trip.stationTimeList.forEach(elem => {
if (elem.arrivalTime) {
opt.data.push([elem.arrivalTime, this.getCoordinateYByStationCode(stations, elem.stationCode), {
stationCode: elem.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
silent: false
}]);
}
if (elem.departureTime) {
opt.data.push([elem.departureTime, this.getCoordinateYByStationCode(stations, elem.stationCode), {
stationCode: elem.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
silent: false
}]);
}
});
if (service.tripList[j + 1] &&
service.tripList[j + 1].stationTimeList) {
lastPoint = trip.stationTimeList[trip.stationTimeList.length-1];
nextPoint = service.tripList[j + 1].stationTimeList[0];
opt.data.push({
value: [lastPoint.arrivalTime, this.getCoordinateYByStationCode(stations, lastPoint.stationCode, true, trip.direction), {
stationCode: lastPoint.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
silent: true
}],
symbol: 'none',
symbolSize: 1,
});
opt.data.push({
value: [nextPoint.departureTime, this.getCoordinateYByStationCode(stations, lastPoint.stationCode, true, trip.direction), {
stationCode: lastPoint.stationCode,
serviceNo: service.serviceNo,
tripNo: trip.tripNo,
direction: trip.direction,
silent: true
}],
symbol: 'none',
symbolSize: 1,
});
}
});
const model = createSeriesModel(opt,
{ color: '#000', width: 1 },
{ color: '#000', fill: '#000'}
);
models.push(model);
}
})
}
return models;
},
/** 更新数据并解析成图表*/
updateDataToModels(tripList, stations, kmRangeCoordMap, runPlanData, series, lineStyle) {
if (tripList && tripList.length) {
/** 更新数据并解析成折线*/
updateDataToModels(chart, planData, stations, series) {
if (planData && planData.length) {
}
return series;
},
@ -78,18 +155,6 @@ export default {
});
},
/** 将后台数据转换为试图序列模型*/
convertStationsToMap(stations) {
var map = {};
if (stations && stations.length) {
stations.forEach((elem) => {
map[`${elem.kmRange}`] = this.EdgeHeight + elem.kmRange * this.CoordMultiple;
});
}
return map;
},
/** 计算y轴最小值*/
computedYaxisMinValue(stations) {
return stations[0].kmRange * this.CoordMultiple;
@ -111,33 +176,47 @@ export default {
});
return yText;
},
},
/** 根据是否和上一个车次是否相交,计算下一个车次的折返的高度*/
computedReentryNumber(code) {
// return parseInt(code || 1) % 2 ? 1 : 2;
return 1;
},
/** 根据方向计算y折返偏移量*/
getOffsetYByDirection(value, direction) {
if (direction === '1') {
value -= this.EdgeHeight / 2;
} else if (direction === '2') {
value += this.EdgeHeight / 2;
}
/** 根据方向计算y折返偏移量*/
getYvalueByDirectionCode(defaultVlue, directionCode, num) {
if (directionCode === '1') {
defaultVlue += this.EdgeHeight / 2 * num;
} else if (directionCode === '2') {
defaultVlue -= this.EdgeHeight / 2 * num;
}
return value;
},
return defaultVlue;
},
/** 根据elem计算y值*/
getCoordYByElem(stations, kmRangeCoordMap, elem) {
var defaultVlue = 0;
var station = stations.find(it => { return it.code == elem.stationCode; });
/** 通过站信息获取y坐标*/
getCoordinateYByStationCode(stations, stationCode, isSpecial=false, direction='01') {
var value = 0;
var station = stations.find(it => { return it.code == stationCode; });
if (station) {
defaultVlue = kmRangeCoordMap[`${station.kmRange}`];
value = this.EdgeHeight + station.kmRange * this.CoordMultiple;
if (isSpecial) {
value = this.getOffsetYByDirection(value, direction);
}
}
return defaultVlue;
}
return value;
},
/** 通过y坐标获取站信息 */
getStationByCoordinate(stations, y) {
for(var i = stations.length-1; i >= 0; i--) {
const station = stations[i];
const edge = this.EdgeHeight
const preKm = i == 0? edge*2: Math.abs(station.kmRange-stations[i-1].kmRange)/2;
const nxtKm = i == stations.length-1? edge: Math.abs(station.kmRange-stations[i+1].kmRange)/2;
const min = edge + station.kmRange - preKm;
const max = edge + station.kmRange + nxtKm;
if (y >= min && y <= max) {
return station;
}
}
return null;
}
};

View File

@ -0,0 +1,232 @@
import store from '@/store/index_APP_TARGET';
import { timeFormat } from '@/utils/date';
/** 创建一个车次数据点*/
export function createMartPoint(opt) {
const rotate = opt.direction == '2' ? 45 : (opt.direction == '1' ? -45 : 0);
const position = opt.type ? 'insideBottomLeft' : 'insideTopLeft';
return {
coord: opt.coord,
name: opt.name,
label: {
normal: {
rotate: rotate,
formatter: '{b}',
backgroundColor: 'rgb(242,242,242,0.1)',
color: 'black',
position: position
}
}
};
}
/** 创建一个服务数据序列*/
export function createSeriesModel(opt, lineStyle={}, itemStyle={}) {
return {
z: opt.z || 2,
type: 'line',
name: opt.name,
data: opt.data,
sampling: 'average',
symbolSize: opt.symbolSize,
showAllSymbol: opt.showAllSymbol||'auto',
lineStyle: lineStyle,
itemStyle: itemStyle,
animation: false,
markPoint: {
symbol: 'roundRect',
symbolSize: 1,
data: opt.markPoint.data
}
};
}
/**
* 创建一个区域
*/
export function createRectArea(opt, style={}) {
return {
type: 'rect',
subType: 'area',
areaNo: opt.model.areaNo,
position: opt.position,
point1: opt.point1,
point2: opt.point2,
model: opt.model,
shape: {
x: 0,
y: 0,
width: opt.width,
height: opt.height
},
style: {
fill: 'rgb(255,0,0, 0.3)',
stroke: 'rgb(255, 0, 0, 0.8)',
text: opt.model.text,
textFill: 'rgb(0, 0, 0)',
fontSize: 18,
fontWeight: 500,
textVerticalAlign: 'middle',
textAlign: 'center',
...style
},
z: 100
}
}
/** 创建标记横线*/
export function createMarkLineModels(stations, computedYaxis) {
const markLineModel = {};
if (stations && stations.length) {
markLineModel.type = 'line';
markLineModel.name = 'markline';
markLineModel.silent = true;
markLineModel.animation = false;
markLineModel.markLine = {};
markLineModel.markLine.silent = true;
markLineModel.markLine.data = [];
markLineModel.markLine.lineStyle = { color: '#B0C4DE', width: 0.5 };
markLineModel.markLine.symbol = 'none';
markLineModel.elements = []
stations.forEach((elem, index) => {
markLineModel.markLine.data.push(
{
label: {
show: true,
position: 'start',
formatter: elem.name,
color: 'black'
},
lineStyle: {
type: 'solid',
width: 0.5,
opacity: 0.5
},
yAxis: computedYaxis(elem, index)
}
);
});
}
return markLineModel;
}
/** 对list数据进行排序, 相同元素保持原有顺序*/
export function sortListByCb(list, callback) {
list.map((elem, index) => { elem[`oldIndex`] = index; });
list.sort((a, b) => {
return callback(a, b) || a.oldIndex - b.oldIndex;
});
return list;
}
/** 将数字转换成asc码*/
export function numToAsc(num) {
const nmA = 'A'.charCodeAt(0);
const nmZ = 'Z'.charCodeAt(0);
const len = nmZ - nmA + 1;
let str = '';
while (num >= 0) {
str = String.fromCharCode(num % len + nmA) + str;
num = Math.floor(num / len) - 1;
}
return str;
}
/** 将asc码转换成数字*/
export function ascToNum(asc) {
const base = 'A'.charCodeAt() - 1;
let idx = asc.length - 1;
let num = 0;
let mulFactor = 1;
while (idx >= 0) {
num += (asc[idx].charCodeAt() - base) * mulFactor;
mulFactor *= 26;
idx -= 1;
}
return num;
}
/** 根据索引获取单元格的数据*/
export function getCellValue(Sheet, index) {
let value;
const cell = Sheet[index];
if (cell) {
value = cell.w || cell.v;
}
return value;
}
/** 转换sheet数据为json数据*/
export function convertSheetToList(Sheet, isReverse) {
const dataList = [];
if (Sheet) {
const refarea = Sheet['!ref'];
const regular = /([a-zA-Z]+)([0-9]+):([a-zA-Z]+)([0-9]+)/i;
if (refarea == null) return []; // "A1:M698"
if (regular.test(refarea)) {
/** 正则转换解析行列数据*/
const CoordList = regular.exec(refarea);
/** 转换数据为二维数组*/
const colBeg = ascToNum(CoordList[1]);
const colEnd = ascToNum(CoordList[3]);
const rowBeg = Number(CoordList[2]);
const rowEnd = Number(CoordList[4]);
if (isReverse) {
for (let i = colBeg - 1; i < colEnd; i++) {
dataList.push([]);
for (let j = rowBeg; j <= rowEnd; j++) {
dataList[dataList.length - 1].push(getCellValue(Sheet, numToAsc(i) + j));
}
}
} else {
for (let i = rowBeg; i <= rowEnd; i++) {
dataList.push([]);
for (let j = colBeg - 1; j < colEnd; j++) {
dataList[dataList.length - 1].push(getCellValue(Sheet, numToAsc(j) + i));
}
}
}
}
}
return dataList;
}
/** 通过time将时间格式化*/
export function formatTime(time) {
if (Number.isInteger(time)) {
return timeFormat(time);
} else {
return '';
}
}
/** 通过code将名称格式化*/
export function formatName(code) {
let name = '';
const device = store.getters['map/getDeviceByCode'](code);
if (device) {
name = device.name;
}
return name;
}
/** 将时间格式化前补零*/
export function prefixTime(time) {
let str = `${time}` || '';
if (str) {
const list = str.split(':');
str = list.map(elem => {
return `00000${elem}`.substr(-2);
}).join(':');
}
return str;
}

View File

@ -151,6 +151,7 @@ const RefereeList = () => import('@/views/jsxt/refereeList/index');
const RefereeDisplay = () => import('@/views/jsxt/refereeList/display');
const Approval = () => import('@/views/approval/index');
const CompanyManage = () => import('@/views/system/companyManage/index');
const QuestionsRuleManage = () => import('@/views/system/questionsRuleManage/index');
import { GenerateRouteProjectList } from '@/scripts/ProjectConfig';
// import { getSessionStorage } from '@/utils/auth';
@ -814,6 +815,14 @@ export const asyncRouter = [
i18n: 'router.companyManage'
}
},
{ // 出题规则管理
path: 'questionsRuleManage',
hidden: true,
component: QuestionsRuleManage,
meta: {
i18n: 'router.questionsRuleManage'
}
},
{
// 缓存管理
path: 'cache',

View File

@ -185,7 +185,10 @@ export default {
QuestionTypeList: [
{ label: '选择题', value: 'select' },
{ label: '判断题', value: 'judge' }
{ label: '判断题', value: 'judge' },
{ label: '多选题', value: 'multi'},
{ label: '填空题', value: 'fill'},
{ label: '问答题', value: 'answer'}
],
// 新版的产品类型枚举
prdType:[
@ -238,7 +241,8 @@ export default {
{label: 'PLC网关', value: 'PLC_GATEWAY'},
{label: '端头控制盒', value: 'PSL'},
{label: 'PSC控制柜', value: 'PSC'},
{label: '虚拟电子沙盘', value: 'SANDBOX'}
{label: '虚拟电子沙盘', value: 'SANDBOX'},
{label: '联锁工作站', value: 'ILW'}
]
}
};

View File

@ -128,10 +128,7 @@ export const DeviceMenu = {
SetDriver: '106',
Script: '107',
IscsSystem: '108',
IscsInterface: '109',
planJustRunning: '200',
planJustDeparture: '201'
IscsInterface: '109'
};
/**

View File

@ -36,7 +36,9 @@ export const deviceFaultType = {
{label: '主灯丝熔断故障', value: 'MAIN_FILAMENT_BROKEN'}
],
Switch: [
{label: '失表', value: 'SPLIT'}
{label: '失表', value: 'SPLIT'},
{label: '定位失表', value: 'NORMAL_SPLIT'},
{label: '反位失表', value: 'REVERSE_SPLIT'}
],
StationStand: [
{label: '屏蔽门故障打开', value: 'FAULT_PSD_OPEN'}

View File

@ -65,7 +65,7 @@ class MenuContextHandler {
let menu = [];
const control = this.getStationControl(selected);
// (!store.state.scriptRecord.bgSet || store.state.scriptRecord.isScriptCommand)
if (control) {
if (control && !store.state.scriptRecord.audioPlay) {
if (this.getPrdType() != '' && this.getPrdType() != null) {
const type = State2SimulationMap[this.getPrdType()];
const status = State2ControlMap[control.controlMode]; // 判断当前模式

View File

@ -17,6 +17,7 @@ import ibp from './modules/ibp';
import order from './modules/order';
import iscs from './modules/iscs';
import rpTools from './modules/rpTools';
import race from './modules/race';
import getters from './getters';
@ -39,8 +40,9 @@ const store = new Vuex.Store({
scriptRecord,
ibp,
order,
iscs,
rpTools
iscs,
rpTools,
race
},
getters
});

View File

@ -16,6 +16,7 @@ import scriptRecord from './modules/scriptRecord';
import ibp from './modules/ibp';
import order from './modules/order';
import iscs from './modules/iscs';
import race from './modules/race';
import getters from './getters';
@ -38,7 +39,8 @@ const store = new Vuex.Store({
scriptRecord,
ibp,
order,
iscs
iscs,
race
},
getters
});

40
src/store/modules/race.js Normal file
View File

@ -0,0 +1,40 @@
/**
* 竞赛状态数据
*/
const race = {
namespaced: true,
state: {
preTheoryData: [] // 导入的理论预保存数据,
},
getters: {
preTheoryData: (state)=>{
return state.preTheoryData;
}
},
mutations: {
setPreTheoryData: (state, preTheoryData) => {
state.orderList = preTheoryData;
}
},
actions: {
/**
* 设置导入的理论预保存数据
*/
setPreTheoryData: ({ commit }, preTheoryData) => {
commit('setPreTheoryData', preTheoryData);
}
// getRouteDataListByCode: ({ state, commit }, code) => { // 获取进路数据
// return new Promise((resolve) => {
// const list = [];
// const routeList = Object.values(state.routeData);
// routeList.forEach(route => {
// if (route.startSignalCode == code) {
// list.push(route);
// }
// });
// resolve(list);
// });
// },
}
};
export default race;

View File

@ -3,7 +3,7 @@ const runPlan = {
state: {
stations: [], // 车站列表
planData: {}, // 运行图原始数据
planData: [], // 运行图原始数据
editData: {}, // 运行图编辑数据
planSizeCount: 0, // 运行图canvas 大小变更标识
planLoadedCount: 0, // 运行图数据更新
@ -16,7 +16,10 @@ const runPlan = {
getters: {
stations: (state) => {
return state.stations || [];
}
},
planData: (state) => {
return state.planData || [];
}
},
mutations: {
setWidth: (state, width) => {
@ -48,7 +51,11 @@ const runPlan = {
}
},
actions: {
/** 设置运行图大小*/
/** 更新数据*/
updateRunPlanData: ({ commit }, data) => {
commit('updateRunPlanData', data);
},
/** 设置运行图大小*/
resize({ commit }, opt) {
if (opt.width) {
commit('setWidth', opt.width);
@ -57,32 +64,6 @@ const runPlan = {
commit('setHeight', opt.height);
}
},
/** 设置stations数据 */
setStations: ({ commit }, mapModel) => {
return new Promise((resolve) => {
commit('setStations', mapModel);
resolve(mapModel);
});
},
/** 设置运行图数据 */
setPlanData: ({ commit }, data) => {
commit('setPlanData', data);
},
/** 选择车次*/
setSelected: ({ commit }, selected) => {
commit('setSelected', selected);
},
/** 更新数据*/
updateRunPlanData: ({ commit }, data) => {
commit('updateRunPlanData', data);
},
/** 清空数据*/
clear: ({ commit }) => {
return new Promise((resolve) => {
commit('clear');
resolve();
});
},
/** 刷新页面*/
refresh: ({commit}) => {
commit('refresh');

View File

@ -14,7 +14,8 @@ const scriptRecord = {
updateRoleId:'', // 剧本更新角色id
updateCoversitionStatus:0, // 剧本仿真更新会话信息
userRole:null, // 剧本更新的角色
operationalItemVOs:{} // 剧本场景的运营统计数据缓存
operationalItemVOs:{}, // 剧本场景的运营统计数据缓存
audioPlay:false // 语音是否自动播放
},
getters: {
mapLocation: (state)=>{
@ -76,6 +77,9 @@ const scriptRecord = {
},
updateOperationalItemVOs:(state, operationalItemVOs) => {
state.operationalItemVOs = operationalItemVOs;
},
setAudioPlay:(state, audioPlay) => {
state.audioPlay = audioPlay;
}
},
actions: {
@ -108,6 +112,9 @@ const scriptRecord = {
},
updateOperationalItemVOs:({ commit }, operationalItemVOs) => {
commit('updateOperationalItemVOs', operationalItemVOs);
},
updateAudioPlay:({ commit }, audioPlay) => {
commit('setAudioPlay', audioPlay);
}
}
};

View File

@ -2,8 +2,8 @@ export function getBaseUrl() {
let BASE_API;
if (process.env.NODE_ENV === 'development') {
// BASE_API = 'https://joylink.club/jlcloud';
BASE_API = 'https://test.joylink.club/jlcloud';
// BASE_API = 'http://192.168.3.5:9000'; // 袁琪
// BASE_API = 'https://test.joylink.club/jlcloud';
BASE_API = 'http://192.168.3.5:9000'; // 袁琪
// BASE_API = 'http://192.168.3.169:9000'; // 旭强
// BASE_API = 'http://192.168.3.175:9000'; // 张赛
// BASE_API = 'http://192.168.3.82:9000'; // 杜康

View File

@ -38,7 +38,7 @@ export default {
doInput() {
const node = this.node;
node.model[node.prop] = this.content;
this.$emit('update', node.model);
// this.$emit('update');
this.doClose();
}
}

View File

@ -26,6 +26,7 @@ export default {
queryForm: {
reset: true,
labelWidth: '80px',
leftSpan: 17,
queryObject: {
type: {
type: 'select',
@ -63,7 +64,7 @@ export default {
title: '答 案',
prop: 'answer',
type: 'tagMore',
width: '100',
width: '200',
columnValue: (row) => { return this.answerTags(row); },
tagType: (row) => {
return '';
@ -77,7 +78,7 @@ export default {
{
type: 'button',
title: '操 作',
width: '420',
width: '320',
buttons: [
{
name: '编辑',
@ -98,7 +99,8 @@ export default {
],
actions: [
{ text: '添 加', handler: this.doCreate },
{ text: '导 入', fileType: 'file', handler: this.importQuestionBank }
{ text: '导 入', fileType: 'file', handler: this.importQuestionBank },
{ text: '出题规则管理', handler: this.questionsRuleManage}
]
}
};
@ -149,6 +151,17 @@ export default {
answer.push(el.content);
}
break;
case 'multi':
if (el.correct) {
answer.push(this.$asc2chart(i + 65));
}
break;
case 'fill':
answer.push(el.content);
break;
case 'answer':
answer.push(el.content);
break;
}
});
return answer;
@ -161,7 +174,9 @@ export default {
const questionTypeMap = {
'单选': 'select',
'多选': 'multi',
'判断': 'judge'
'判断': 'judge',
'填空': 'fill',
'问答': 'answer'
};
if (file) {
setTimeout(() => {
@ -216,19 +231,34 @@ export default {
topic: dataList[topicIndex][index],
optionList: []
};
param.optionList.push({ content:dataList[option1Index][index] || '正确', correct: dataList[answerIndex][index].includes('A') || dataList[answerIndex][index] == '√' });
param.optionList.push({ content:dataList[option2Index][index] || '错误', correct: dataList[answerIndex][index].includes('B') || dataList[answerIndex][index] == '×' });
if (dataList[option3Index][index]) {
param.optionList.push({content:dataList[option3Index][index], correct: dataList[answerIndex][index].includes('C')});
}
if (dataList[option4Index][index]) {
param.optionList.push({content:dataList[option4Index][index], correct: dataList[answerIndex][index].includes('D')});
if (param.type === 'fill') {
const answer = dataList[answerIndex][index];
const answerList = answer.split('&&');
answerList && answerList.forEach(item => {
param.optionList.push({content: item, correct: true});
});
} else if (param.type === 'answer') {
param.optionList.push({content: dataList[answerIndex][index]});
} else {
param.optionList.push({ content:dataList[option1Index][index] || '正确', correct: dataList[answerIndex][index].includes('A') || dataList[answerIndex][index] == '√' });
param.optionList.push({ content:dataList[option2Index][index] || '错误', correct: dataList[answerIndex][index].includes('B') || dataList[answerIndex][index] == '×' });
if (dataList[option3Index][index]) {
param.optionList.push({content:dataList[option3Index][index], correct: dataList[answerIndex][index].includes('C')});
}
if (dataList[option4Index][index]) {
param.optionList.push({content:dataList[option4Index][index], correct: dataList[answerIndex][index].includes('D')});
}
}
questionList.push(param);
}
});
}
}
// this.$store.dispatch('race/setPreTheoryData', questionList).then(({ valid }) => {
//
// }).catch(() => {
// this.$message.error('');
// });
importQuestionBand(questionList, 'DRTS').then(resp => {
this.$message.success('导入题库成功!');
}).catch(()=>{
@ -250,6 +280,9 @@ export default {
if (!obj.files) return;
const f = obj.files[0];
this.handleImport(f);
},
questionsRuleManage() {
this.$router.push({ path: `/system/questionsRuleManage`});
}
}
};

View File

@ -11,18 +11,37 @@
<el-radio :label="1"> × </el-radio>
</el-radio-group>
</template>
<template v-if="type=='multi'">
<el-checkbox-group v-model="activeList" @change="onChange">
<el-checkbox v-for="(el,i) in optionList" :key="i" :label="i"> 选项-{{ $asc2chart(65+i) }} </el-checkbox>
</el-checkbox-group>
</template>
<template v-if="type==='fill'">
<div v-for="(el, i) in answerList" :key="i" style="margin-bottom: 5px;">
<div>{{ `${i + 1}` }}</div>
<item-rich v-model="el.value" :remove="i>0" @modify="doModify(el)" @remove="doRemove(i)" />
</div>
<el-button class="item__button" type="primary" size="mini" icon="el-icon-plus" @click="doAppend" />
</template>
<template v-if="type==='answer'">
<el-input
v-model="answer"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入答案"
@change="onChange"
/>
</template>
</div>
</template>
<script>
import ItemRich from './item-rich';
export default {
components: {
ItemRich
},
props: {
value: {
type: Number,
default: 0
},
optionList: {
type: Array,
required: true
@ -34,18 +53,52 @@ export default {
},
data() {
return {
active: 0
active: 0,
activeList: [],
answer: '',
answerList: [{value: ''}]
};
},
watch: {
value(val) {
this.active = val;
optionList(val) {
if (this.type === 'judge' || this.type === 'select') {
this.active = this.optionList.findIndex(ele => ele.correct);
} else if (this.type === 'multi') {
this.activeList = [];
this.optionList.forEach((el, i) => {
if (el.correct) {
this.activeList.push(i);
}
});
} else if (this.type === 'fill') {
this.answerList = [];
this.optionList.forEach(el => {
this.answerList.push({value: el.content});
});
} else if (this.type === 'answer') {
this.answer = (this.optionList[0] || {content: ''}).content;
}
}
// answerList: {
// handler(val) {
// this.onChange(val);
// },
// deep: true
// }
},
methods: {
onChange(e) {
this.$emit('input', e);
this.$emit('change', e);
},
doAppend() {
this.answerList.push({value: ''});
},
doModify(el) {
this.$emit('modify', {model: el, prop: 'value'});
console.log('-----------', this.answerList);
},
doRemove(index) {
this.answerList.splice(index, 1);
}
}
};

View File

@ -1,6 +1,6 @@
<template>
<div class="option">
<template v-if="type=='select'">
<template v-if="type=='select' || type=='multi'">
<div v-for="(el,i) in optionList" :key="i" class="option__item">
<div> 选项-{{ $asc2chart(65+i) }} </div>
<item-rich v-model="el.content" :remove="remove" @modify="doModify(el)" @remove="doRemove(i)" />

View File

@ -0,0 +1,136 @@
<template>
<div>
<query-list-page ref="user" :pager-config="pagerConfig" :query-form="queryForm" :query-list="queryList" />
</div>
</template>
<script>
import { UrlConfig } from '@/scripts/ConstDic';
import { listQuestionPage, deleteQuestion } from '@/api/questionBank.js';
import { convertSheetToList } from '@/utils/runPlan';
import XLSX from 'xlsx';
import { importQuestionBand } from '@/api/race';
export default {
data() {
return {
pagerConfig: {
pageSize: 'pageSize',
pageIndex: 'pageNum'
},
queryForm: {
reset: true,
labelWidth: '80px',
leftSpan: 18,
queryObject: {
}
},
queryList: {
query: this.handlePreDataPaging,
selectCheckShow: false,
indexShow: true,
columns: [
{
title: '题 目',
prop: 'topic'
},
{
title: '类 型',
prop: 'type',
type: 'tag',
width: '120',
columnValue: (row) => { return this.$ConstSelect.translate(row.type, 'QuestionTypeList'); },
tagType: (row) => {
return '';
}
},
{
title: '答 案',
prop: 'answer',
type: 'tagMore',
width: '200',
columnValue: (row) => { return this.answerTags(row); },
tagType: (row) => {
return '';
}
},
{
type: 'button',
title: '操 作',
width: '320',
buttons: [
{
name: '编辑',
handleClick: this.edit
},
{
name: '删 除',
handleClick: this.doDelete,
type: 'danger'
}
]
}
]
}
};
},
computed: {
userId() {
return this.$store.state.user.id;
}
},
methods: {
edit(index, row) {
this.$router.push({path: `${UrlConfig.bank.questionUpdate}/${row.id}`});
},
handlePreDataPaging(param) {
},
doDelete(index, row) {
this.$confirm('删除试题,是否继续?', '提 示', {
confirmButtonText: '确 定',
cancelButtonText: '取 消',
type: 'warning'
}).then(() => {
deleteQuestion(row.id).then(resp => {
this.reloadTable();
}).catch(error => {
this.$message.error(`删除试题失败: ${error.message}`);
});
}).catch( () => { });
},
answerTags(row) {
const answer = [];
row.optionList.forEach((el, i) => {
switch (row.type) {
case 'select':
if (el.correct) {
answer.push(this.$asc2chart(i + 65));
}
break;
case 'judge':
if (el.correct) {
answer.push(el.content);
}
break;
case 'multi':
if (el.correct) {
answer.push(this.$asc2chart(i + 65));
}
break;
case 'fill':
answer.push(el.content);
break;
case 'answer':
answer.push(el.content);
break;
}
});
return answer;
},
reloadTable() {
this.queryList.reload();
}
}
};
</script>

View File

@ -10,11 +10,11 @@
<item-rich v-model="option.topic" @modify="onModify({model: option, prop: 'topic'})" />
</el-form-item>
<template v-if="isCreate">
<el-form-item v-if="option.type != 'judge'" label="选 项" prop="optionList">
<el-form-item v-if="option.type === 'select' || option.type === 'multi'" label="选 项" prop="optionList">
<item-options :option-list="optionList" :type="option.type" :add="isSelect" :remove="remove" @remove="onRemove" @modify="onModify" @append="onAppend" />
</el-form-item>
<el-form-item label="答 案" prop="answer">
<item-answer v-model="option.answer" :option-list="optionList" :type="option.type" @change="onAnswerChnage" />
<item-answer :option-list="optionList" :type="option.type" @change="onAnswerChnage" @modify="onModify" />
</el-form-item>
</template>
</el-form>
@ -73,6 +73,14 @@ export default {
{ content: '√', correct: true },
{ content: '×', correct: false }
];
},
multi: function() {
return [
{ content: '', correct: false},
{ content: '', correct: false },
{ content: '', correct: false },
{ content: '', correct: false }
];
}
};
},
@ -113,7 +121,18 @@ export default {
}
},
onAnswerChnage(answer) {
this.option.optionList.forEach((el, i) => { el.correct = i == answer; });
if (this.option.type === 'judge' || this.option.type === 'select') {
this.option.optionList.forEach((el, i) => { el.correct = i == answer; });
} else if (this.option.type === 'multi') {
this.option.optionList.forEach((el, i) => { el.correct = answer.includes(i); });
} else if (this.option.type === 'fill') {
this.option.optionList = [];
answer.forEach(item => {
this.option.optionList.push({ content: item.value, correct: true });
});
} else if (this.option.type === 'answer') {
this.option.optionList = [{content: answer, correct:true}];
}
},
onModify(node) {
this.$emit('modify', node);

View File

@ -52,7 +52,7 @@ export default {
loadInitData() {
getQuestionInfo(this.questionId).then(resp => {
this.formModel = resp.data;
this.formModel.answer = this.formModel.optionList.findIndex(ele => ele.correct);
// this.formModel.answer = this.formModel.optionList.findIndex(ele => ele.correct);
});
},
doBack() {

View File

@ -259,7 +259,7 @@ export default {
},
bgImg() {
const bgImgAll = process.env.VUE_APP_PRO === 'local' || this.$route.query.project == 'heb' ? '' : bgImg;
const synchronousLogin = ['VR_IBP', 'LSW', 'CCTV', 'ISCS_LW', 'ISCS_CW', 'VR_PSD', 'SANDBOX'];
const synchronousLogin = ['VR_IBP', 'LSW', 'CCTV', 'ISCS_LW', 'ISCS_CW', 'VR_PSD', 'SANDBOX', 'ILW'];
const imgMap = {
ISCS_LW: bgIscsImg,
ISCS_CW: bgIscsImg,
@ -267,12 +267,13 @@ export default {
CCTV: bgCctvImg,
VR_PSD: bgPsdImg,
LSW: bgLswImg,
SANDBOX: bgLswImg
SANDBOX: bgLswImg,
ILW: bgLswImg
};
return synchronousLogin.includes(this.$route.query.type) ? imgMap[this.$route.query.type] : bgImgAll;
},
syncLogin() {
const synchronousLogin = ['VR_IBP', 'LSW', 'CCTV', 'ISCS_LW', 'ISCS_CW', 'VR_PSD', 'SANDBOX'];
const synchronousLogin = ['VR_IBP', 'LSW', 'CCTV', 'ISCS_LW', 'ISCS_CW', 'VR_PSD', 'SANDBOX', 'ILW'];
return this.$route.query.type ? synchronousLogin.includes(this.$route.query.type) : false;
},
loadingText() {
@ -282,7 +283,8 @@ export default {
VR_IBP: '检测现地工作站登陆中',
CCTV: '检测教员机登录中',
VR_PSD: '检测教员机登录中',
LSW: '检测教员机登录中'
LSW: '检测教员机登录中',
ILW: '检测教员机登录中'
};
return this.$route.query.type ? textMap[this.$route.query.type] : '';
}
@ -542,6 +544,16 @@ export default {
type: this.$route.query.type
};
this.$router.push({ path: `/jlmap3d/sandbox`, query: sandboxQuery });
} else if (this.$route.query.type === 'ILW') {
const ilwQuery = {
mapid: query.mapId,
group: query.group,
project: getSessionStorage('project'),
token: getToken(),
projectDevice: this.$route.query.projectDevice,
type: this.$route.query.type
};
this.$router.push({ path: `/jointTrainingNew`, query: query });
} else {
this.$router.push({ path: `/jointTrainingNew`, query: query });
}

View File

@ -1,16 +1,16 @@
<template>
<div class="chatBox" :class="{'active': drawer}" :style="{'bottom':bottom+'px'}">
<div class="menuTrainListBtn" @click="clickBtn">
<template v-if="userRole == 'DISPATCHER'">
<div v-if="userRole == 'DISPATCHER'" id="teleName">
<p style="margin: 0;"></p>
<p style="margin: 0;"></p>
<p style="margin: 0;"></p>
<p style="margin: 0;"></p>
</template>
<template v-if="userRole != 'AUDIENCE' && userRole != 'DISPATCHER'">
</div>
<div v-if="userRole != 'AUDIENCE' && userRole != 'DISPATCHER'" id="teleName">
<p style="margin: 0;"></p>
<p style="margin: 0;"></p>
</template>
</div>
<template v-if="userRole == 'AUDIENCE'">
<p style="margin: 0;"></p>
<p style="margin: 0;"></p>
@ -86,10 +86,10 @@
</el-button>
</div>
<div v-else>
<el-button v-if="isButtonShow && !commonConversation" size="mini" type="danger" class="chat-box-footer-create chat-box-footer-quit" :loading="quitLoading" @click="quitConversition()">
<el-button v-if="isButtonShow && !commonConversation" size="mini" type="danger" class="chat-box-footer-create chat-box-footer-quit" :disabled="audioPlay" :loading="quitLoading" @click="quitConversition()">
<i class="el-icon-phone" />
</el-button>
<el-button v-if="isButtonShow && !commonConversation" class="chat-box-footer-create chat-box-footer-send" :class="{'active': recordSending}" size="mini" type="primary" @click="startRecording()">
<el-button v-if="isButtonShow && !commonConversation" class="chat-box-footer-create chat-box-footer-send" :class="{'active': recordSending}" :disabled="audioPlay" size="mini" type="primary" @click="startRecording()">
<el-progress id="record_progress_bar" type="circle" :show-text="false" :percentage="100/60*seconds" :width="40" :stroke-width="2" status="success" />
<i v-if="recordSending" class="el-icon-close close_icon" @click.stop="cancleRecording()" />
<span class="iconfont icon-yuyin">&#xe62b;</span>
@ -200,7 +200,8 @@ export default {
messageList: [], //
commonMessageList: [],
conversitionStateMap:{},
myMemberId: ''
myMemberId: '',
audioPlay:false
};
},
computed:{
@ -286,6 +287,9 @@ export default {
item.children[val.creatorId].isInviting = true;
const offsetTop = document.getElementById('proper_content_box' + val.creatorId).parentNode.offsetTop;
document.querySelector('.chat-box-content').scrollTop = (offsetTop - 40) > 0 ? (offsetTop - 80) : 0;
if (!document.querySelector('#teleName').classList.contains('flash')) {
document.querySelector('#teleName').classList.add('flash');
}
}
});
},
@ -456,8 +460,14 @@ export default {
}
});
}
},
'$store.state.scriptRecord.audioPlay':function(val) {
this.audioPlay = val;
}
},
beforeDestroy() {
this.$store.dispatch('scriptRecord/updateAudioPlay', false);
},
mounted() {
this.firstClick = true;
this.$nextTick(() => {
@ -489,6 +499,7 @@ export default {
acceptUser() {
acceptConversitionInvite(this.group, this.conversitionId).then(res=>{
this.connectSuccess = true;
document.querySelector('#teleName').classList.remove('flash');
this.treeData.forEach(data => {
if (data.children) {
const member = data.children[res.data.creatorId];
@ -930,6 +941,7 @@ export default {
this.commonMessageList = [];
this.conversitionStateMap = {};
this.messageList = this.commonMessageList;
this.connectSuccess = false;
this.treeData.forEach(item => {
if (item.children) {
const memberList = Object.values(item.children);
@ -1039,7 +1051,7 @@ export default {
align-items: center;
text-align: center;
justify-content: center;
padding: 7px 4px;
padding: 7px 4px;
.el-icon-more{
font-size: 20px;
margin-top: 9px;
@ -1210,6 +1222,13 @@ export default {
.proper_content_box_text{
position: absolute;
}
.flash{
opacity: 1;
animation: isInviting infinite 1s;
-moz-animation: isInviting infinite 1s; /* Firefox */
-webkit-animation: isInviting infinite 1s; /* Safari 和 Chrome */
-o-animation: isInviting infinite 1s; /* Opera */
}
</style>
<style lang="scss">
.isInviting::before{

View File

@ -22,6 +22,7 @@
</template>
<script>
import yuyin from '@/assets/yuyin.png';
import {overConversationMessage} from '@/api/chat';
export default {
props:{
messageList:{
@ -83,18 +84,21 @@ export default {
this.$emit('changeMessageList', conversationInfo);
if (this.conversitionId == val.id) {
if (member && member.userId != this.$store.state.user.id) {
this.currentAudioList.push(this.baseUrl + '/audio/' + conversationInfo.message.audioPath);
this.currentAudioList.push({audioUrl:this.baseUrl + '/audio/' + conversationInfo.message.audioPath, id:val.message.id});
if (!this.isPlay) {
this.isPlay = true;
this.$store.dispatch('scriptRecord/updateAudioPlay', true);
this.playAllAudio();
//
}
}
this.scrollTop();
} else if (this.userRole === 'AUDIENCE' || this.commonConversation) {
if (member && member.userId != this.$store.state.user.id) {
this.currentAudioList.push(this.baseUrl + '/audio/' + conversationInfo.message.audioPath);
this.currentAudioList.push({audioUrl:this.baseUrl + '/audio/' + conversationInfo.message.audioPath, id:val.message.id});
if (!this.isPlay) {
this.isPlay = true;
this.$store.dispatch('scriptRecord/updateAudioPlay', true);
this.playAllAudio();
}
}
@ -114,18 +118,21 @@ export default {
playAllAudio() {
this.playEachAudio(this.currentAudioList[this.currentAudioIndex]);
},
playEachAudio(audioUrl) {
playEachAudio(audioObject) {
this.$nextTick(function() {
document.querySelector('#audioPlay').src = audioUrl;
document.querySelector('#audioPlay').src = audioObject.audioUrl;
document.querySelector('#audioPlay').play();
const that = this;
document.querySelector('#audioPlay').onended = function() {
that.currentAudioList.shift();
if (that.currentAudioList.length > 0) {
that.playEachAudio(that.currentAudioList[that.currentAudioIndex]);
} else {
that.isPlay = false;
}
overConversationMessage(that.$route.query.group, audioObject.id).then(res=>{
that.currentAudioList.shift();
if (that.currentAudioList.length > 0) {
that.playEachAudio(that.currentAudioList[that.currentAudioIndex]);
} else {
that.isPlay = false;
that.$store.dispatch('scriptRecord/updateAudioPlay', false);
}
});
};
});
},
@ -141,8 +148,12 @@ export default {
return name;
},
playAudio(audioUrl) {
document.querySelector('#audioPlay').src = audioUrl;
document.querySelector('#audioPlay').play();
if (!this.isPlay) {
document.querySelector('#audioPlay').src = audioUrl;
document.querySelector('#audioPlay').play();
document.querySelector('#audioPlay').onended = function() {
};
}
},
conversationChange() {
this.currentAudioList = [];

View File

@ -433,6 +433,13 @@ export default {
this.drivingShow = false;
break;
}
if (this.$route.query.type === 'ILW') {
this.$store.dispatch('training/setPrdType', '');
this.$store.dispatch('training/setRoles', 'AUDIENCE');
this.jl3dmaintainershow = false;
this.drivingShow = false;
this.hideIbp();
}
},
/* 竞赛系统倒计时 */
startCounting() {

View File

@ -1,6 +1,6 @@
<template>
<div>
<chat-box :group="group" :user-role="userRole" />
<chat-box v-if="$route.query.type !== 'ILW'" :group="group" :user-role="userRole" />
<!-- 地图没有报错-->
<!-- 地图错误判断 -->
<div v-if="!dataError&&hasOneButton" class="display_top_draft" :style="{top: offset+'px'}">
@ -14,9 +14,9 @@
<el-button v-if="isShowScheduling || isStationSupervisor" size="small" @click="jumpjl3dpassflow">{{ $t('display.demon.passengerflow') }}</el-button>
<el-button v-if="isShowScheduling || isStationSupervisor" size="small" @click="jumpjl3dfaultdevice">{{ $t('display.demon.maintainer') }}</el-button>
<!-- <el-button v-if="isAdmin" size="small" @click="otherVrView">VR第三人称视角</el-button> -->
<el-button v-if="isAdmin && !noQrcodeList.includes(project)" type="primary" size="small" @click="generateQrCode">生成二维码</el-button>
<el-button v-if="isAdmin" size="small" @click="memberManage">成员管理</el-button>
<el-button v-if="isAdmin && isProject" size="small" @click="handleEquipment">设备管理</el-button>
<el-button v-if="isAdmin && !noQrcodeList.includes(project) && $route.query.type !== 'ILW'" type="primary" size="small" @click="generateQrCode">生成二维码</el-button>
<el-button v-if="isAdmin && $route.query.type !== 'ILW'" size="small" @click="memberManage">成员管理</el-button>
<el-button v-if="(isAdmin && isProject) || $route.query.type === 'ILW'" size="small" @click="handleEquipment">设备管理</el-button>
<el-button v-if="isDeviceLogin" size="small" @click="handleTeach">教学系统</el-button>
<el-button v-if="isDeviceLogin || $route.query.type === 'IM'" size="small" @click="handleExam">考试系统</el-button>
</el-button-group>
@ -26,7 +26,7 @@
<el-button v-if="project==='refereeJsxt'" type="success" size="small" @click="refeeEndCompetition">退出</el-button> <!-- 竞赛退出 -->
<el-button v-if="project!=='jsxt' && project!=='refereeJsxt'" type="primary" :loading="backLoading" size="small" @click="back">退出</el-button>
<template v-if="!dataError"> <!-- 地图错误判断 -->
<template v-if="isAdmin && project != 'refereeJsxt'">
<template v-if="isAdmin && project != 'refereeJsxt' && $route.query.type !== 'ILW'">
<el-button type="danger" size="small" @click="end">{{ $t('joinTraining.initialize') }}</el-button>
<!-- 按计划行车 -->
<el-button type="success" :disabled="isDisable" size="small" @click="selectBeginTime">{{ $t('joinTraining.drivingByPlan') }}</el-button>

View File

@ -7,13 +7,13 @@
<el-button-group>
<el-button v-if="userRole=== 'STATION_SUPERVISOR' && !$route.query.projectDevice" size="small" @click="goIbp">IBP盘</el-button>
<el-button v-if="userRole=== 'DISPATCHER' && !$route.query.projectDevice" size="small" @click="goBigScreen">大屏</el-button>
<el-button v-if="running && !dataError" size="small" :disabled="viewDisabled" @click="viewRunPlan">{{ $t('joinTraining.runGraphPreview') }}</el-button>
<el-button v-if="running && !dataError && $route.query.type !== 'ILW'" size="small" :disabled="viewDisabled" @click="viewRunPlan">{{ $t('joinTraining.runGraphPreview') }}</el-button>
<template v-if="isAdmin">
<el-button v-if="!running && !dataError" size="small" type="warning" @click="loadRunPlan">
<el-button v-if="!running && !dataError && $route.query.type !== 'ILW'" size="small" type="warning" @click="loadRunPlan">
{{ $t('joinTraining.runGraphLoading') }}</el-button><!-- -->
</template>
</el-button-group>
<el-button v-if="isAdmin && !dataError && !isScreen" size="small" :type="faultMode ? '' : 'primary' " @click="changeOperateMode()">{{ faultMode?' 切换到普通模式':'切换到故障模式' }}</el-button>
<el-button v-if="(isAdmin || $route.query.type === 'ILW') && !dataError && !isScreen" size="small" :type="faultMode ? '' : 'primary' " @click="changeOperateMode()">{{ faultMode?' 切换到普通模式':'切换到故障模式' }}</el-button>
<!-- isCenter && !dataError && !isAdmin 此判断用于以后(目前 暂时不用) -->
<el-button v-if="isShowDirective" size="small" :type="directiveMode ? 'primary' : ''" @click="changeDirectiveMode()">{{ directiveMode? '切换到普通模式':'切换到指令模式' }}</el-button>
</div>

View File

@ -14,7 +14,7 @@
</template>
<script>
import { DeviceMenu } from '@/scripts/ConstDic';
import { MenuEnum } from '../utils.js';
export default {
props: {
@ -29,6 +29,10 @@ export default {
default() {
return []
}
},
config: {
type: Object,
required: true
}
},
data() {
@ -38,8 +42,8 @@ export default {
this.stations[this.selected.dataIndex].kmRange -
this.stations[this.selected.dataIndex+1].kmRange
)
const min = Math.floor(offset / 19.4);
const max = Math.floor(offset / 8.3);
const min = Math.floor(offset / (this.config.maxSpeed * 1000/3600));
const max = Math.floor(offset / 1);
if (value < min) {
callback(new Error('Below minimum run time.'));
@ -69,7 +73,7 @@ export default {
},
watch: {
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](DeviceMenu.planJustRunning)) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](MenuEnum.planJustRunning)) {
this.doShow(this.$store.state.menuOperation.menuPosition);
} else {
this.doClose();

View File

@ -14,7 +14,7 @@
</template>
<script>
import { DeviceMenu } from '@/scripts/ConstDic';
import { MenuEnum } from '../utils.js';
export default {
props: {
@ -29,12 +29,16 @@ export default {
default() {
return []
}
},
config: {
type: Object,
required: true
}
},
data() {
var validator = (rule, value, callback) => {
if (value > 0 && value <= 15) {
callback(new Error('Stop time cannot be within 0-15 seconds.'));
if (value > 0 && value <= this.config.minStopTime) {
callback(new Error(`Stop time cannot be within 0-${this.config.minStopTime} seconds.`));
} else {
callback()
}
@ -59,7 +63,7 @@ export default {
},
watch: {
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](DeviceMenu.planJustDeparture)) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](MenuEnum.planJustStop)) {
this.doShow(this.$store.state.menuOperation.menuPosition);
} else {
this.doClose();

View File

@ -0,0 +1,82 @@
<template>
<el-dialog v-dialogDrag append-to-body title="Modify turn back time" :visible.sync="dialogShow" width="30%" :close-on-click-modal="false" :before-close="doClose">
<el-form ref="form" label-width="160px" :model="formModel" :rules="rules">
<el-form-item label="Turn back time" prop="time">
<el-input-number v-model="formModel.time" controls-position="right" :min="0" />
<span style="padding-left: 10px">s</span>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogShow = false">{{ $t('map.cancel') }}</el-button>
<el-button type="primary" @click="doConfirm">{{ $t('map.confirm') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { MenuEnum } from '../utils.js';
export default {
props: {
selected: {
type: Object,
default() {
return null
}
},
stations: {
type: Array,
default() {
return []
}
},
config: {
type: Object,
required: true
}
},
data() {
return {
dialogShow: false,
formModel: {
time: 0,
},
rules: {
time: [
{
type: 'number', min: 0, message: 'Please select turn back time.', trigger: 'blur'
}
],
}
};
},
watch: {
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](MenuEnum.planJustTurnBack)) {
this.doShow(this.$store.state.menuOperation.menuPosition);
} else {
this.doClose();
}
},
selected: function(val) {
if (val) this.formModel.time = val.runTime;
}
},
methods: {
doShow() {
this.dialogShow = true;
},
doClose() {
this.dialogShow = false;
},
doConfirm() {
this.$refs.form.validate((valid) => {
if(valid) {
this.$emit('justTurnBack', this.formModel.time);
this.doClose();
}
});
}
}
};
</script>

View File

@ -0,0 +1,158 @@
<template>
<el-dialog v-dialogDrag append-to-body title="Modify area parameters" :visible.sync="dialogShow" width="30%" :close-on-click-modal="false" :before-close="doClose">
<el-form ref="form" label-width="160px" :model="formModel" :rules="rules">
<el-form-item label="Start station" prop="startStationCode">
<el-select v-model="formModel.startStationCode" placeholder="请选择">
<el-option
v-for="(el,i) in stations"
:key="i"
:label="el.name"
:value="el.code">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="End station" prop="endStationCode">
<el-select v-model="formModel.endStationCode" placeholder="请选择">
<el-option
v-for="(el,i) in stations"
:key="i"
:label="el.name"
:value="el.code">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="Start time" prop="startTime">
<el-time-picker value-format="HH:mm:ss" v-model="formModel.startTime" />
</el-form-item>
<el-form-item label="End time" prop="endTime">
<el-time-picker value-format="HH:mm:ss" v-model="formModel.endTime" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogShow = false">{{ $t('map.cancel') }}</el-button>
<el-button type="primary" @click="doConfirm">{{ $t('map.confirm') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { MenuEnum } from '../utils.js';
import { getRpConfig } from '@/api/rpTools';
import { toTimeStamp } from '@/utils/date';
export default {
props: {
stations: {
type: Array,
required: true
},
target: {
type: Object,
default() {
return null
}
}
},
data() {
var startTimeValidator = (rule, value, callback) => {
const startTime = toTimeStamp(value);
const endTime = toTimeStamp(this.formModel.endTime);
if (startTime >= endTime) {
callback(new Error('The start time is greater than the end time.'));
} else if (Math.abs(startTime - endTime) < 10*60) {
callback(new Error('The time interval shall not be less than 10 min.'));
} else {
callback()
}
}
var endTimeValidator = (rule, value, callback) => {
const startTime = toTimeStamp(this.formModel.startTime);
const endTime = toTimeStamp(value);
if (endTime <= startTime) {
callback(new Error('The end time is less than the start time.'));
} else if (Math.abs(startTime - endTime) < 10*60) {
callback(new Error('The time interval shall not be less than 10 min.'));
} else {
callback()
}
}
return {
dialogShow: false,
formModel: {
areaNo: '',
startStationCode: '',
endStationCode: '',
startTime: 0,
endTime: 0
},
rules: {
startStationCode: [
{
required: true, message: 'Please select the farther station.', trigger: 'blur'
},
],
endStationCode: [
{
required: true, message: 'Please select the closer station.', trigger: 'blur'
},
],
startTime: [
{
required: true, message: 'Please select the start time.', trigger: 'blur'
},
{
validator: startTimeValidator, trigger: 'blur'
}
],
endTime: [
{
required: true, message: 'Please select the end time.', trigger: 'blur'
},
{
validator: endTimeValidator, trigger: 'blur'
}
]
}
};
},
watch: {
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](MenuEnum.planModifyArea)) {
this.doShow(this.$store.state.menuOperation.menuPosition);
} else {
this.doClose();
}
}
},
methods: {
doShow() {
if (this.target &&
this.target.model) {
const model = this.target.model;
this.formModel = {
areaNo: model.areaNo,
startStationCode: model.fartherStationCode,
endStationCode: model.closerStationCode,
startTime: model.startTime,
endTime: model.endTime
}
}
this.dialogShow = true;
},
doClose() {
this.dialogShow = false;
},
doConfirm() {
this.$refs.form.validate((valid) => {
if(valid) {
this.$emit('modifyArea', this.formModel);
this.doClose();
}
});
}
}
};
</script>

View File

@ -0,0 +1,72 @@
<template>
<el-dialog v-dialogDrag append-to-body title="Add area content" :visible.sync="dialogShow" width="30%" :close-on-click-modal="false" :before-close="doClose">
<el-form ref="form" label-width="100px" :model="formModel" >
<el-form-item label="Start station" prop="text">
<el-input type="textarea" :rows="2" placeholder="Please enter the content." v-model="formModel.text" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogShow = false">{{ $t('map.cancel') }}</el-button>
<el-button type="primary" @click="doConfirm">{{ $t('map.confirm') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { MenuEnum } from '../utils.js';
import { getRpConfig } from '@/api/rpTools';
import { toTimeStamp } from '@/utils/date';
export default {
props: {
target: {
type: Object,
default() {
return null
}
}
},
data() {
return {
dialogShow: false,
formModel: {
areaNo: '',
text: ''
},
}
},
watch: {
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](MenuEnum.planSetAreaNote)) {
this.doShow(this.$store.state.menuOperation.menuPosition);
} else {
this.doClose();
}
}
},
methods: {
doShow() {
if (this.target &&
this.target.model) {
const model = this.target.model;
this.formModel = {
areaNo: model.areaNo,
text: model.text
};
}
this.dialogShow = true;
},
doClose() {
this.dialogShow = false;
},
doConfirm() {
this.$refs.form.validate((valid) => {
if(valid) {
this.$emit('setAreaNote', this.formModel);
this.doClose();
}
});
}
}
};
</script>

View File

@ -0,0 +1,127 @@
<template>
<el-dialog v-dialogDrag append-to-body title="Modification of train diagram parameters" :visible.sync="dialogShow" width="30%" :close-on-click-modal="false" :before-close="doClose">
<el-form ref="form" label-width="160px" :model="formModel" :rules="rules">
<el-form-item label="Average speed" prop="averageSpeed">
<el-input-number v-model="formModel.averageSpeed" controls-position="right" :min="20" :max="60" />
<span style="padding-left: 10px">km/h</span>
</el-form-item>
<el-form-item label="Maximum speed" prop="maxSpeed">
<el-input-number v-model="formModel.maxSpeed" controls-position="right" :min="50" :max="80" />
<span style="padding-left: 10px">km/h</span>
</el-form-item>
<el-form-item label="Default stop time" prop="stopTime">
<el-input-number v-model="formModel.stopTime" controls-position="right" :min="10" :max="120" />
<span style="padding-left: 10px">s</span>
</el-form-item>
<el-form-item label="Minimum stop time" prop="minStopTime">
<el-input-number v-model="formModel.minStopTime" controls-position="right" :min="10" :max="30" />
<span style="padding-left: 10px">s</span>
</el-form-item>
<el-form-item label="Minimum interval time" prop="minIntervalTime">
<el-input-number v-model="formModel.minIntervalTime" controls-position="right" :min="30" :max="360" />
<span style="padding-left: 10px">s</span>
</el-form-item>
<el-form-item label="Turn back time" prop="turnBackTime">
<el-input-number v-model="formModel.turnBackTime" controls-position="right" :min="60" :max="180" />
<span style="padding-left: 10px">s</span>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogShow = false">{{ $t('map.cancel') }}</el-button>
<el-button type="primary" @click="doConfirm">{{ $t('map.confirm') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { MenuEnum } from '../utils.js';
export default {
props: {
config: {
type: Object,
required: true
}
},
data() {
return {
dialogShow: false,
formModel: {
averageSpeed: 40,
maxSpeed: 70,
stopTime: 30,
minStopTime: 10,
minIntervalTime: 180,
turnBackTime: 90
},
rules: {
averageSpeed: [
{
type: 'number', min: 20, max: 60, message: 'Please select the stop time.', trigger: 'blur'
}
],
maxSpeed: [
{
type: 'number', min: 50, max: 80, message: 'Please select the stop time.', trigger: 'blur'
}
],
stopTime: [
{
type: 'number', min: 10, max: 120, message: 'Please select the stop time.', trigger: 'blur'
}
],
minStopTime: [
{
type: 'number', min: 10, max: 30, message: 'Please select the stop time.', trigger: 'blur'
}
],
minIntervalTime: [
{
type: 'number', min: 30, max: 360, message: 'Please select the stop time.', trigger: 'blur'
}
],
turnBackTime: [
{
type: 'number', min: 60, max: 180, message: 'Please select the stop time.', trigger: 'blur'
}
]
}
};
},
watch: {
selected: function(val) {
},
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](MenuEnum.planSetParams)) {
this.doShow(this.$store.state.menuOperation.menuPosition);
} else {
this.doClose();
}
}
},
methods: {
doShow() {
this.formModel = {
averageSpeed: this.config.averageSpeed,
maxSpeed: this.config.maxSpeed,
stopTime: this.config.stopTime,
minStopTime: this.config.minStopTime,
minIntervalTime: this.config.minIntervalTime,
turnBackTime: this.config.turnBackTime
}
this.dialogShow = true;
},
doClose() {
this.dialogShow = false;
},
doConfirm() {
this.$refs.form.validate((valid) => {
if(valid) {
this.$emit('setParams', this.formModel.time);
this.doClose();
}
});
}
}
};
</script>

View File

@ -1,104 +1,527 @@
<template>
<div class="plan-tool">
<schedule
ref="schedule"
:line-code="lineCode"
:plan-convert="PlanConvert"
:max-height="height"
:max-width="width"
/>
<div class="monitor">
<schedule
ref="schedule"
:planUtil="planUtil"
:title="title"
:height="height"
:width="width"
:model="model"
@tag="onTarget"
@select="onSelected"
@clear="onClear"
@create="onCreate"
@translate="onTranslate"
>
<template slot="header">
<div class="header">
<div class="menus-left">
<el-button type="primary" @click="doNewPlan">New</el-button>
<el-button type="primary" @click="onDialog(MenuEnum.planSetParams)">Set Param</el-button>
</div>
<div class="menus-right">
<span style="font-size:22px;padding:0 17px;">Plan</span>
<menus
:model="model"
:selected="selected"
:target="target"
@remove="onRemove"
@clear="onClear"
/>
</div>
</div>
</template>
</schedule>
<plan-just-running :config="config" :selected="selected" :stations="stations" @justRunning="doJustRunning" />
<plan-just-stop :config="config" :selected="selected" :stations="stations" @justStop="doJustStop"/>
<plan-just-turn-back :config="config" :selected="selected" :stations="stations" @justTurnBack="doJustTurnBack"/>
<plan-set-params :config="config" @setParams="doSetPlanParams" />
<plan-set-area-note :target="target" @setAreaNote="doSetAreaNote" />
<plan-modify-area :target="target" :stations="stations" @modifyArea="doModifyArea" />
</div>
</template>
<script>
import Schedule from './schedule';
import Schedule from './schedule.vue';
import PlanJustRunning from './dialog/planJustRunning.vue';
import PlanJustStop from './dialog/planJustStop.vue';
import PlanJustTurnBack from './dialog/planJustTurnBack.vue';
import PlanSetParams from './dialog/planSetParams.vue';
import PlanModifyArea from './dialog/planModifyArea.vue';
import PlanSetAreaNote from './dialog/planSetAreaNote';
import Menus from './menus.vue';
import { MenuEnum } from './utils.js';
import { timeFormat } from '@/utils/date';
import { mapGetters } from 'vuex';
import { getStationList } from '@/api/runplan';
import {
getRpTools, clearRpPlan, addRpTrip, delRpTrip,
justTripNoRunning, justTripNoStop, justTripTurnBack,
translateRpService, delRpService,
getRpConfig, modifyRpConfig,
createRpArea, modifyRpArea, modifyAreaNote, delRpArea
} from '@/api/rpTools';
export default {
components: {
Schedule
Schedule,
PlanJustRunning,
PlanJustStop,
PlanJustTurnBack,
PlanSetParams,
PlanModifyArea,
PlanSetAreaNote,
Menus
},
data() {
return {
PlanConvert: {}
title: 'XXX',
canvasId: 'canvas-plan',
stations: [],
planData: [],
selected: null,
target: null,
model: {
choice: 'Plan',
action: '',
},
config: {
}
};
},
},
computed: {
lineCode() {
return '00';
},
width() {
width() {
return this.$store.state.app.width - 2;
},
height() {
return this.$store.state.app.height - 72;
}
},
created() {
document.title = '运行图编辑工具'
this.PlanConvert = this.$theme.loadPlanConvert(this.lineCode);
// const project = getSessionStorage('project');
// if (project) {
// document.querySelector("link[rel*='icon']").href =;
// }
},
planId() {
return this.$route.query.planId;
},
mapId() {
return 9;
},
lineCode() {
return '00';
},
MenuEnum() {
return MenuEnum;
}
},
watch: {
width() {
this.setPosition();
},
height() {
this.setPosition();
},
},
created() {
this.planUtil = this.$theme.loadPlanConvert(this.lineCode);
},
mounted() {
this.setPosition();
this.loadInitData();
},
methods: {
setPosition() {
this.$nextTick(() => {
this.$refs.schedule.setPosition();
this.$store.dispatch('rpTools/resize', { width: this.width, height: this.height });
});
},
dispatchDialog(dialogObj) {
this.$nextTick(() => {
if (this.$refs[dialogObj.name]) {
this.$refs[dialogObj.name].doShow(dialogObj.params);
loadInitData() {
getStationList(this.mapId).then(resp => {
const stations = this.stations = resp.data.filter(el => {
return ['车辆段', '停车场'].findIndex(it => { return el.name.includes(it) }) < 0;
});
this.$store.commit('rpTools/setStations', stations);
this.$refs.schedule.loadChartPage(stations);
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
getRpConfig().then(resm => {
const data = resm.data;
this.config = {
averageSpeed: data.averageSpeed,
maxSpeed: data.maxSpeed,
stopTime: data.stopTime,
minStopTime: data.minStopTime,
minIntervalTime: data.minIntervalTime,
turnBackTime: data.turnBackTime
}
}).catch(error => {
this.$message.info(error.message)
})
});
}).catch(error => {
this.$messageBox(error.message);
})
},
onClear() {
this.selected = null;
this.target = null;
this.$refs.schedule.setLineReset();
this.$refs.schedule.clearTrip();
if (this.model.action != 'Translate') {
this.$refs.schedule.clearDraggable();
}
if (this.model.action != 'Add') {
this.$refs.schedule.clearGraphic();
}
},
onDialog(menu) {
this.$store.dispatch('menuOperation/setPopMenu', { position: {x: 0, y: 0}, menu });
},
onTarget(target) {
this.target = target;
},
onSelected(selected) {
this.selected = selected;
},
onCreate(data) {
switch(this.model.choice) {
case 'Plan':
this.doCreateTrip(data);
break;
case 'Construction':
this.doCreateArea(data);
break;
}
},
onTranslate(data) {
switch(this.model.choice) {
case 'Plan':
this.doTranslateService(data);
break;
case 'Construction':
this.doTranslateArea(data);
break;
}
},
onRemove(){
this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
switch(this.model.choice) {
case 'Plan':
if (['Translate', 'Edit'].includes(this.model.action)) {
this.doRemoveService();
} else {
this.doRemoveTrip();
}
break;
case 'Construction':
this.doRemoveArea();
break;
}
}).catch(() => {
this.$message({ type: 'info', message: 'Deletion cancelled.' });
});
},
doNewPlan() {
clearRpPlan().then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
this.$store.dispatch('rpTools/setStations', []);
});
}).catch(error => {
this.$message.info(error.message);
})
},
doSetPlanParams(data) {
modifyRpConfig(data).then(resp => {
this.config = data;
this.$message.success('Parameters of plan were modified successfully.');
}).catch(error => {
this.$message.info(error.message);
})
},
doModifyArea(data) {
const startTime = data.startTime;
const endTime = data.endTime;
const startCodeIndex = this.stations.findIndex(el => { return el.code == data.startStationCode; })
const endCodeIndex = this.stations.findIndex(el => { return el.code == data.endStationCode; })
const model = {
fartherStationCode: startCodeIndex < endCodeIndex? data.endStationCode: data.startStationCode,
closerStationCode: startCodeIndex < endCodeIndex? data.startStationCode: data.endStationCode,
startTime: data.startTime,
endTime: data.endTime
}
modifyRpArea(data.areaNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
this.$message.success('Construction area modified successfully.');
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
},
doSetAreaNote(data) {
const model = {
text: data.text
}
modifyAreaNote(data.areaNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
this.$message.success('Construction area note modified successfully.');
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
},
doJustRunning(time) {
if (this.selected) {
const model = {
seconds: time,
stationCode: this.selected.stationCode
}
});
justTripNoRunning(this.selected.tripNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
}
},
dispatchOperate(operateObj) {
this.$nextTick(() => {
if (this.$refs[operateObj.dialogName]) {
this.$refs[operateObj.dialogName][operateObj.operate](operateObj.params);
doJustStop(time){
if (this.selected) {
const model = {
seconds: time,
stationCode: this.selected.stationCode
}
});
}
justTripNoStop(this.selected.tripNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
}
},
doJustTurnBack(time) {
if (this.selected) {
const model = {
seconds: time,
stationCode: this.selected.stationCode
}
justTripTurnBack(this.selected.tripNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
}
},
doCreateTrip(data) {
const model = {
endStationCode: data.endStationCode,
startStationCode: data.startStationCode,
startTime: timeFormat(data.startTime),
endTime: timeFormat(data.endTime)
}
addRpTrip(model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
this.$refs.schedule.clearGraphic(['mark']);
})
},
doCreateArea(data) {
const startTime = data.startTime;
const endTime = data.endTime;
const startCodeIndex = this.stations.findIndex(el => { return el.code == data.startStationCode; })
const endCodeIndex = this.stations.findIndex(el => { return el.code == data.endStationCode; })
if (Math.abs(endTime - startTime) < 10*60) {
this.$refs.schedule.clearGraphic(['mark']);
this.$message.info('The time interval shall not be less than 10 min.')
return;
}
const model = {
fartherStationCode: startCodeIndex < endCodeIndex? data.endStationCode: data.startStationCode,
closerStationCode: startCodeIndex < endCodeIndex? data.startStationCode: data.endStationCode,
startTime: endTime < startTime? timeFormat(data.endTime): timeFormat(data.startTime),
endTime: endTime < startTime? timeFormat(data.startTime): timeFormat(data.endTime)
}
createRpArea(model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
this.$refs.schedule.clearGraphic(['mark']);
})
},
doTranslateService() {
if (this.selected) {
const model = {
seconds : this.selected.sx
}
translateRpService(this.selected.serviceNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
});
}
},
doTranslateArea() {
if (this.target) {
const data = this.target.model;
const model = {
fartherStationCode: data.fartherStationCode,
closerStationCode: data.closerStationCode,
startTime: data.startTime,
endTime: data.endTime,
text: data.text
}
modifyRpArea(data.areaNo, model).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
});
}
},
doRemoveService() {
if (this.selected) {
delRpService(this.selected.serviceNo).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
this.onClear();
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
}
},
doRemoveTrip() {
if (this.selected) {
delRpTrip(this.selected.tripNo).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
this.onClear();
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
}
},
doRemoveArea() {
if (this.target) {
delRpArea(this.target.areaNo).then(resp => {
getRpTools().then(rest => {
const planData = rest.data;
this.$store.commit('rpTools/setPlanData', planData);
this.$refs.schedule.loadChartData(planData);
this.onClear();
}).catch(() => {
this.$messageBox('Failed to load the plan.');
});
}).catch(error => {
this.$message.info(error.message);
})
}
}
}
};
</script>
<style scoped rel="stylesheet/scss" lang="scss">
@import "src/styles/mixin.scss";
<style>
.plan-tool {
position: absolute;
.monitor {
z-index: 0;
width: 100%;
height: 100%;
position: relative;
.header {
margin: 0 80px;
display: flex;
justify-content: space-between;
align-items: center;
.menus-left {
display: flex;
align-items: center;
}
.menus-right {
display: flex;
align-items: center;
}
}
}
.plan-tool .pop-menu {
background: #F0F0F0;
}
.plan-tool .pop-menu span {
color: #000;
}
.plan-tool .system-close {
cursor: pointer;
height: 25px;
width: 25px;
background: -webkit-linear-gradient(#CD98A0, #C27D6E, #B63022, #C68770);
background: -o-linear-gradient(#CD98A0, #C27D6E, #B63022, #C68770);
background: -moz-linear-gradient(#CD98A0, #C27D6E, #B63022, #C68770);
background: linear-gradient(#CD98A0, #C27D6E, #B63022, #C68770);
border: 1px solid white;
border-radius: 4px;
}
.plan-tool .system-close::before {
position: absolute;
top: 0px;
left: 0px;
font-size: x-large;
}
.planEdit__tool {
overflow: hidden !important;
}
</style>

View File

@ -0,0 +1,153 @@
<template>
<div class="menus">
<el-select v-model="model.choice" placeholder="请选择功能类型" style="margin-right:20px" @change="doSelChange">
<el-option v-for="(el,i) in options" :key="i" :label="el.label" :value="el.value" />
</el-select>
<div v-if="option">
<el-button-group v-if="option.radioList" v-model="model.action">
<el-button v-for="(el,i) in option.radioList"
:key="i"
:type="el.value == model.action? 'primary':''"
@click="doBtnSelect(el, i)">
<span>{{ execProp('label', el, i) }}</span>
</el-button>
</el-button-group>
<el-button-group v-if="option.buttonList" style="margin-left: 20px">
<el-button v-for="(el,i) in option.buttonList"
:key="i"
:type="execProp('type', el, i)"
:icon="execProp('icon', el, i)"
@click="execProp('handle', el, i)">
<span>{{ execProp('name', el, i) }}</span>
</el-button>
</el-button-group>
</div>
</div>
</template>
<script>
export default {
props: {
model: {
type: Object,
required: true
},
selected: {
type: Object,
default() {
return null
}
},
target: {
type: Object,
default() {
return null
}
}
},
data() {
return {
}
},
computed: {
options() {
return [
{
label: "Planning",
value: "Plan"
},
{
label: "Construction area",
value: "Construction"
},
]
},
optionsMap() {
return {
Plan: {
radioList: [
{
label: 'Add',
value: 'Add',
},
{
label: 'Translate',
value: 'Translate'
},
{
label: 'Edit',
value: 'Edit'
}
],
buttonList: [
{
icon: 'el-icon-delete',
type: (el, i) => { return this.selected? 'danger':'info' },
handle: e => { this.$emit('remove') }
}
]
},
Construction: {
radioList: [
{
label: 'Add',
value: 'Add',
},
{
label: 'Translate',
value: 'Translate'
},
{
label: 'Edit',
value: 'Edit'
},
{
label: 'Note',
value: 'Note'
}
],
buttonList: [
{
icon: 'el-icon-delete',
type: (el, i) => { return this.target?'danger':'info' },
handle: e => { this.$emit('remove') }
}
]
}
}
},
option() {
return this.optionsMap[this.model.choice]
}
},
methods: {
execProp(prop, el, i) {
return el[prop]
? el[prop] instanceof Function
? el[prop](el, i)
: el[prop]
: '';
},
doSelChange() {
this.model.action = '';
this.$emit('clear');
},
doBtnSelect(el, i) {
if (this.option.radioList &&
this.model.action != el.value) {
this.model.action = el.value;
this.$emit('clear')
} else {
this.model.action = '';
this.$emit('clear')
}
}
}
}
</script>
<style scoped>
.menus {
display: flex;
align-items: center;
}
</style>

View File

@ -1,16 +1,21 @@
import echarts from 'echarts';
import { DeviceMenu } from '@/scripts/ConstDic';
import { timeFormat } from '@/utils/date';
import * as utils from './utils'
import { timeFormat, toTimeStamp } from '@/utils/date';
import { MenuEnum } from './utils';
export default {
data() {
return {
createModel: {
callRegister: [],
markList: [],
buildModel: {
endStationCode: '',
startStationCode: '',
startTime: ''
startTime: 0,
endTime: 0
},
selected: null,
target: null,
dragging: false
}
},
@ -23,51 +28,20 @@ export default {
this.listenersOff();
},
methods: {
getStationByCoord(stations, y) {
for(var i = stations.length-1; i >= 0; i--) {
const station = stations[i];
const edge = this.planConvert.EdgeHeight
const preKm = i == 0? edge*2: Math.abs(station.kmRange-stations[i-1].kmRange)/2;
const nxtKm = i == stations.length-1? edge: Math.abs(station.kmRange-stations[i+1].kmRange)/2;
const min = edge + station.kmRange - preKm;
const max = edge + station.kmRange + nxtKm;
if (y >= min && y <= max) {
return station;
}
}
return null;
},
getStationByCoord2(stations, y) {
for(var i = stations.length-1; i >= 0; i--) {
const station = stations[i];
const edge = this.planConvert.EdgeHeight;
const rate = this.planConvert.CoordMultiple;
const preKm = i == 0? edge*2: rate/2;
const nxtKm = i == stations.length-1? edge: rate/2;
const min = edge + i*rate - preKm;
const max = edge + i*rate + nxtKm;
if (y >= min && y <= max) {
return station;
}
}
return null;
},
pixelExecCb(e, cb) {
const event = e.componentType ? e.event: e;
const myChart = this.myChart;
const pointInPixel = [event.offsetX, event.offsetY]
if (myChart.containPixel('grid', pointInPixel) && this.planConvert) {
const pointInGrid = myChart.convertFromPixel({seriesIndex:0},pointInPixel);
const pointInGrid = this.myChart.convertFromPixel('grid', pointInPixel);
if (this.myChart.containPixel('grid', pointInPixel) && this.planUtil) {
const xIndex = pointInGrid[0];
const yIndex = pointInGrid[1];
const option = myChart.getOption();
const option = this.myChart.getOption();
const minY = option.yAxis[0].min;
const xVal = option.xAxis[0].data[xIndex];
const yObj = this.getStationByCoord(this.stations, yIndex-minY);
const yObj = this.planUtil.getStationByCoordinate(this.stations, yIndex-minY);
if (yObj && cb) {
cb({yObj, xVal, pointInPixel, e});
cb({yObj, xVal, pointInPixel, pointInGrid, e});
}
}
},
@ -75,94 +49,151 @@ export default {
if (this.myChart) {
const zr = this.myChart.getZr();
zr.on('mouseover', this.onZrMouseOver, this);
zr.on('mousedown', this.onZrMouseDown, this);
zr.on('mouseup', this.onZrMouseUp, this);
zr.on('mouseout', this.onZrMouseOut, this);
this.myChart.on('mousedown', this.onMouseDown);
this.myChart.on('mouseover', this.onMouseOver);
this.myChart.on('mouseout', this.onMouseOut);
this.myChart.on('mouseup', this.onMouseUP);
this.myChart.on('datazoom', this.onUpdatePosition);
window.addEventListener('resize', this.onUpdatePosition);
this.myChart.on('datazoom', this.onUpdateZoom);
window.addEventListener('resize', this.onUpdateZoom);
}
},
listenersOff() {
if (this.myChart) {
const zr = this.myChart.getZr();
zr.off('mousedown', this.onZrMouseDown);
zr.off('mouseover', this.onZrMouseOver, this);
zr.off('mousedown', this.onZrMouseDown, this);
zr.off('mouseup', this.onZrMouseUp, this);
zr.off('mouseout', this.onZrMouseOut, this);
this.myChart.off('mousedown', this.onMouseDown);
this.myChart.off('mouseover', this.onMouseOver);
this.myChart.off('mouseout', this.onMouseOut);
this.myChart.off('mouseup', this.onMouseUP);
this.myChart.off('datazoom', this.onUpdatePosition);
window.removeEventListener('resize', this.onUpdatePosition);
this.myChart.off('datazoom', this.onUpdateZoom);
window.removeEventListener('resize', this.onUpdateZoom);
}
},
onUpdatePosition(e) {
this.handleCancel();
onUpdateZoom(e) {
const fixedList = ['area'];
const option = this.myChart.getOption();
const elements = option.graphic[0].elements
const graphic = echarts.util.map(elements, (item) => {
return { position: this.myChart.convertToPixel('grid', item.point)};
const graphic = echarts.util.map(elements, (el) => {
if (fixedList.includes(el.subType)) {
const position = this.myChart.convertToPixel('grid', el.point1);
const position2 = this.myChart.convertToPixel('grid', el.point2);
const width = Math.abs(position[0] - position2[0]);
const height = Math.abs(position[1] - position2[1])
return {
position,
shape: { width, height }
}
} else {
return {
position: this.myChart.convertToPixel('grid', el.point)
};
}
})
this.$emit('clear');
this.myChart.setOption({graphic});
},
onZrMouseOver(e) {
this.pixelExecCb(e, this.doSetTarget);
if (this.model.action == 'Translate') {
this.pixelExecCb(e, this.doSetAreaTranslate);
} else if (this.model.action == 'Edit') {
this.pixelExecCb(e, this.doSetAreaDrags);
}
},
onZrMouseDown(e) {
switch(this.action) {
case 'Add':
this.pixelExecCb(e, this.handleCreateMark);
break;
if (e.target && ['area'].includes(e.target.subType)) {
this.dragging = true;
if (this.model.choice == 'Construction') {
if (this.model.action == 'Note') {
this.pixelExecCb(e, this.doPopDialog);
}
}
}
if (this.model.choice == 'Plan') {
if (this.model.action == 'Add') {
this.pixelExecCb(e, this.doCreateMark);
}
} else if (this.model.choice == 'Construction') {
if (this.model.action == 'Add') {
this.pixelExecCb(e, this.doCreateArea);
}
// if (this.model.action == 'Translate') {
// this.pixelExecCb(e, this.doSetAreaTranslate);
// } else if (this.model.action == 'Edit') {
// this.pixelExecCb(e, this.doSetAreaDrags);
// }
}
},
onZrMouseUp(e) {
switch(this.action) {
case 'Translate':
if (this.dragging) {
this.dragging = false;
this.handleTranslate(this.createModel)
if (['Plan', 'Construction'].includes(this.model.choice)) {
if(this.model.action == 'Translate' && this.dragging) {
this.pixelExecCb(e, this.doTranslate)
}
}
if (!e.target) {
this.$emit('clear')
}
this.dragging = false;
},
onZrMouseOut(e) {
},
onMouseOver(e) {
this.pixelExecCb(e, args => {
if (this.model.choice == 'Plan') {
this.doSetSelected(args);
if (this.model.action == 'Translate') {
this.doCreateDrag(args)
}
break;
}
});
if (this.model.choice == 'Plan') {
if (this.model.action == 'Translate') {
setTimeout(_ => { this.onShapeMouseOver(e); }, 200);
}
}
},
onMouseDown(e) {
switch(this.action) {
case 'Edit':
this.pixelExecCb(e, this.handlePopDialog);
break;
}
},
onMouseOver(e) {
this.pixelExecCb(e, this.handleSelectLine);
if (this.action == 'Translate') {
setTimeout(() => {
this.onShapeMouseOver(e);
}, 200);
}
},
onMouseOut(e) {
this.pixelExecCb(e, this.handleSelectLine);
if (this.action == 'Translate') {
this.onShapeMouseOver(e);
this.dragging = true;
if (this.model.choice == 'Plan') {
if (this.model.action == 'Edit') {
this.pixelExecCb(e, this.doPopDialog);
}
}
},
onMouseUP(e) {
// switch(this.action) {
// case 'Translate':
// if (this.dragging) {
// this.dragging = false;
// this.handleTranslate(this.createModel)
// }
// break;
// }
},
onShapePointDragging(e) {
if (this.selected) {
this.dragging = true;
this.pixelExecCb(e, this.handleDragging);
if (['Construction'].includes(this.model.choice)) {
if(this.model.action == 'Translate' && this.dragging) {
this.pixelExecCb(e, this.doTranslate)
this.dragging = false;
}
}
},
onShapeMouseOver() {
onMouseOut(e) {
this.pixelExecCb(e, args => {
if (this.model.choice == 'Plan') {
this.doSetSelected(args);
if(this.model.action == 'Translate') {
this.doCreateDrag(args)
}
}
});
},
onShapeMouseOver(e) {
if (this.selected) {
this.myChart.dispatchAction({
type: 'showTip',
@ -171,213 +202,280 @@ export default {
});
}
},
onShapeMouseOut() {
onShapeDragging(e) {
if (this.selected &&
this.model.choice == 'Plan') {
if (this.model.action == 'Translate') {
this.pixelExecCb(e, this.doSeriesDragging);
}
} else if (this.target &&
this.model.choice == 'Construction') {
if (this.model.action == 'Translate') {
this.pixelExecCb(e, this.doAreaDragging);
}
}
},
onShapeMouseOut(e) {
if (this.selected) {
this.myChart.dispatchAction({
type: 'hideTip',
});
}
},
setLineLight() {
if (this.selected) {
this.myChart.setOption({
series: {
name: this.selected.seriesName,
symbolSize: 10,
showAllSymbol: true,
lineStyle: {
width: 2,
color: 'red'
}
}
doCreateDrag({e, pointInGrid, pointInPixel}) {
if (this.selected &&
e.componentType == "series" &&
e.componentSubType == "line" &&
e.seriesName.includes('service')) {
const option = this.myChart.getOption();
const filters = option.graphic[0].elements.filter(el => { return el.subType != 'drag'});
filters.push(utils.buildDragDataObj(pointInPixel, pointInGrid, this))
option.graphic[0].elements = filters;
this.myChart.setOption(option, {notMerge: true});
this.myChart.dispatchAction({
type: 'showTip',
seriesIndex: this.selected.seriesIndex,
dataIndex: this.selected.dataIndex
});
}
},
setLineReset() {
if (this.selected) {
this.myChart.setOption({
series: {
name: this.selected.seriesName,
symbolSize: 1,
showAllSymbol: true,
lineStyle: {
width: 1,
color: '#000'
}
}
});
}
},
clearGraphic(labels) {
const option = this.myChart.getOption();
const elements = option.graphic[0].elements;
option.graphic[0].elements = elements.filter(el => { return !labels.includes(el.subType)});
this.myChart.setOption(option, {notMerge: true});
},
createDragGraphicObj(point) {
return {
type: 'circle',
subType: 'drag',
position: this.myChart.convertToPixel('grid', point),
point: [...point],
shape: {
cx: 0,
cy: 0,
r: 10
},
invisible: true,
draggable: 'horizontal',
ondrag: echarts.util.curry(this.onShapePointDragging),
onmouseover: echarts.util.curry(this.onShapeMouseOver),
onmouseout: echarts.util.curry(this.onShapeMouseOut),
z: 100
}
},
createMarkPointObj(point) {
return {
type: 'circle',
subType: 'mark',
z: 100,
position: point,
point: [...this.myChart.convertFromPixel('grid', point)],
shape: {
cx: 0,
cy: 0,
r: 10
},
style: {
fill: 'rgba(0,0,0,0.3)'
}
}
},
handlePopDialog({e, pointInPixel}) {
if (e.componentType == "series" &&
e.componentSubType == "line" &&
e.seriesName.includes('run-')) {
const value = e.value;
const point = {
x: pointInPixel[0],
y: pointInPixel[1]
}
const option = this.myChart.getOption();
const dataList = option.series[e.seriesIndex].data;
const length = dataList.length;
const nxt = dataList[e.dataIndex+1];
const pre = dataList[e.dataIndex-1];
this.selected = {
dataIndex: e.dataIndex,
seriesIndex: e.seriesIndex,
seriesName: e.seriesName,
seriesId: e.seriesName.replace('run-', ''),
depTime: e.dataIndex < length - 1? nxt[0] - value[0]: 0,
runTime: e.dataIndex < length - 1? nxt[0] - value[0]: 0,
stationCode: value[2],
_x: value[0],
dx: 0,
time: 0
}
if (e.dataIndex < length - 1 && value[2] == nxt[2]) {
this.$store.dispatch('menuOperation/setPopMenu', { position: point, menu: DeviceMenu.planJustDeparture });
} else if (e.dataIndex == 0 || e.dataIndex > 0 && value[1] == pre[1]) {
this.$store.dispatch('menuOperation/setPopMenu', { position: point, menu: DeviceMenu.planJustRunning });
}
}
},
handleSelectLine({e}) {
if (e.componentType == "series" &&
e.componentSubType == "line" &&
e.seriesName.includes('run-')) {
const value = e.value;
const option = this.myChart.getOption();
const dataList = option.series[e.seriesIndex].data;
const length = dataList.length;
const nxt = dataList[e.dataIndex+1];
const pre = dataList[e.dataIndex-1];
if (this.selected &&
this.selected.seriesName != e.seriesName) {
this.setLineReset();
}
this.selected = {
dataIndex: e.dataIndex,
seriesIndex: e.seriesIndex,
seriesName: e.seriesName,
seriesId: e.seriesName.replace('run-', ''),
depTime: e.dataIndex < length - 1? nxt[0] - value[0]: 0,
runTime: e.dataIndex < length - 1? nxt[0] - value[0]: 0,
stationCode: value[2],
_x: value[0],
dx: 0,
time: 0
}
this.setLineLight();
switch(this.action) {
case 'Translate':
this.handleCreateDrag({e})
break;
}
}
},
handleCreateDrag({e}) {
const option = this.myChart.getOption();
const filters = option.graphic[0].elements.filter(el => { return el.subType != 'drag'});
filters.push(this.createDragGraphicObj(e.value))
option.graphic[0].elements = filters;
this.myChart.setOption(option, {notMerge: true});
this.myChart.dispatchAction({
type: 'showTip',
seriesIndex: this.selected.seriesIndex,
dataIndex: this.selected.dataIndex
});
},
handleCreateMark({pointInPixel, yObj, xVal}) {
const myChart = this.myChart;
doCreateMark({e, pointInGrid, pointInPixel, yObj, xVal}) {
const option = this.myChart.getOption();
const graphic = option.graphic;
const elements = graphic[0].elements;
elements.push(this.createMarkPointObj(pointInPixel))
myChart.setOption(option, {notMerge: true});
const filters = elements.filter(el => { return el.subType == 'mark'});
if (filters.length == 1) {
this.createModel.startStationCode = yObj.code;
this.createModel.startTime = timeFormat(xVal);
} else if (filters.length >= 2) {
this.createModel.endStationCode = yObj.code;
this.handleCreateTrip(this.createModel);
}
},
handleDragging({e, xVal}) {
this.selected.dx = xVal - this.selected._x;
this.selected.time += this.selected.dx;
this.selected._x = xVal;
const option = this.myChart.getOption();
const model = option.series[this.selected.seriesIndex]
if (model) {
model.data.forEach(el => {
el[0] += this.selected.dx;
});
}
if (e.target &&
e.target.point &&
e.target.position) {
e.target.point[0] += this.selected.dx;
}
elements.push(utils.buildMarkPointObj(pointInPixel, pointInGrid, this))
this.myChart.setOption(option, {notMerge: true});
const markList = this.markList = elements.filter(el => { return el.subType == 'mark'});
const elemList = elements.filter(el => { return el.subType != 'mark'});
if (markList.length == 1) {
this.buildModel.startStationCode = yObj.code;
this.buildModel.startTime = xVal;
} else if (markList.length >= 2) {
this.buildModel.endStationCode = yObj.code;
this.buildModel.endTime = xVal;
option.graphic[0].elements = elemList;
this.$emit('create', this.buildModel);
}
},
doCreateArea({e, pointInGrid, pointInPixel, yObj, xVal}) {
if (!e.target) {
const option = this.myChart.getOption();
const graphic = option.graphic;
const elements = graphic[0].elements;
elements.push(utils.buildMarkPointObj(pointInPixel, pointInGrid, this))
this.myChart.setOption(option, {notMerge: true});
const markList = this.markList = elements.filter(el => { return el.subType == 'mark'});
const elemList = elements.filter(el => { return el.subType != 'mark'});
if (markList.length == 1) {
this.buildModel.startStationCode = yObj.code;
this.buildModel.startTime = xVal;
} else if (markList.length >= 2) {
this.buildModel.endStationCode = yObj.code;
this.buildModel.endTime = xVal;
option.graphic[0].elements = elemList;
this.$emit('create', this.buildModel);
}
}
},
doSetTarget({e, pointInGrid}) {
if (e.target && ['area'].includes(e.target.subType)) {
const target = e.target;
const model = target.model
Object.assign(model, {
_x: pointInGrid[0],
_y: pointInGrid[1],
dx: 0,
dy: 0,
sx: 0,
sy: 0
})
this.target = target;
this.$emit('tag', target);
}
},
doSetSelected({e, pointInGrid}) {
if (e.componentType == "series" &&
e.componentSubType == "line" &&
e.seriesName.includes('service')) {
const value = e.value;
const option = this.myChart.getOption();
const dataList = option.series[e.seriesIndex].data;
const length = dataList.length;
const last = utils.findNext(dataList, e.dataIndex, (el, i) => { return el instanceof Array});
const isService = this.model.choice == 'Plan' && ['Translate', 'Edit'].includes(this.model.action);
if (this.selected &&
this.selected.seriesName != e.seriesName) {
this.setLineReset();
this.clearTrip();
}
if (!isService) {
const service = option.series[e.seriesIndex];
const index = option.series.findIndex(el => { return el.name.includes('trip') })
if (index < 0) {
option.series.push({
name: 'service-trip',
type: 'line',
symbolSize: 1,
showAllSymbol: true,
data: []
})
}
const series = option.series[option.series.findIndex(el => { return el.name.includes('trip') })];
series.data = service.data.filter(el => { return el instanceof Array && el[2].tripNo == value[2].tripNo })
this.myChart.setOption(option, {notMerge: true});
}
this.selected = {
dataIndex: e.dataIndex,
seriesIndex: e.seriesIndex,
seriesName: isService? e.seriesName: 'service-trip',
seriesId: e.seriesId,
depTime: e.dataIndex < length - 1? last[0] - value[0]: 0,
runTime: e.dataIndex < length - 1? last[0] - value[0]: 0,
... value[2],
_x: pointInGrid[0],
_y: pointInGrid[1],
dx: 0,
dy: 0,
sx: 0,
sy: 0
}
this.$emit('select', this.selected);
this.setLineLight();
}
},
doSetAreaTranslate({e}) {
if (e.target && ['area'].includes(e.target.subType)) {
const option = this.myChart.getOption();
const shape = option.graphic[0].elements.find(el => { return ['area'].includes(el.subType) && el.areaNo == this.target.areaNo; });
shape.draggable = true;
shape.ondrag = echarts.util.curry(this.onShapeDragging);
this.myChart.setOption(option, {notMerge: true});
console.log(shape);
}
},
doSetAreaDrags({e}) {
console.log('set drag')
},
doPopDialog({e, pointInGrid, pointInPixel}) {
const point = {
x: pointInPixel[0],
y: pointInPixel[1]
}
if (e.componentType == "series" &&
e.componentSubType == "line" &&
e.seriesName.includes('service')) {
const option = this.myChart.getOption();
const dataList = option.series[e.seriesIndex].data;
const length = dataList.length;
const next = dataList[e.dataIndex+1];
const prev = utils.findPrev(dataList, e.dataIndex, (el, i) => { return el instanceof Array});
this.doSetSelected({e, pointInGrid});
if (e.dataIndex < length - 1 && e.value[1] == next[1]) {
this.$store.dispatch('menuOperation/setPopMenu', { position: point, menu: MenuEnum.planJustStop });
} else if (e.dataIndex < length - 1 && e.value[1] != next[1]) {
this.$store.dispatch('menuOperation/setPopMenu', { position: point, menu: MenuEnum.planJustTurnBack });
} else if (e.dataIndex == 0 || e.dataIndex > 0 && e.value[1] == prev[1]) {
this.$store.dispatch('menuOperation/setPopMenu', { position: point, menu: MenuEnum.planJustRunning });
}
} else if (e.target && e.target.subType == 'area') {
this.doSetTarget({e, pointInGrid})
if (this.model.action == 'Note') {
this.$store.dispatch('menuOperation/setPopMenu', { position: point, menu: MenuEnum.planSetAreaNote });
}
}
},
doSeriesDragging({e, pointInGrid}) {
if (this.selected && this.dragging) {
this.selected.dx = pointInGrid[0] - this.selected._x;
this.selected.dy = pointInGrid[1] - this.selected._y;
this.selected.sx += this.selected.dx;
this.selected.sy += this.selected.dy;
this.selected._x = pointInGrid[0];
this.selected._y = pointInGrid[1];
if (this.selected.dx || this.selected.dy) {
const option = this.myChart.getOption();
const model = option.series[this.selected.seriesIndex]
model.data.forEach(el => {
if (el instanceof Array) {
el[0] += this.selected.dx;
} else {
el.value[0] += this.selected.dx;
}
});
model.markPoint.data.forEach(el => {
el.coord[0] += this.selected.dx;
})
if (e.target &&
e.target.point &&
e.target.position) {
e.target.point[0] += this.selected.dx;
}
this.myChart.setOption(option, {notMerge: true});
}
}
},
doAreaDragging({e, pointInGrid}) {
if (this.target && ['area'].includes(this.target.subType) && this.dragging) {
const model = this.target.model;
if (model.sx != undefined && model.sy != undefined) {
model.dx = pointInGrid[0] - model._x;
model.dy = pointInGrid[1] - model._y;
model.sx += model.dx;
model.sy += model.dy;
model._x = pointInGrid[0];
model._y = pointInGrid[1];
}
}
},
doTranslate({e}) {
if (this.target && ['area'].includes(this.target.subType)) {
const model = this.target.model;
const sx = model.sx||0;
const sy = model.sy||0;
const fartherStationValue = this.planUtil.getCoordinateYByStationCode(this.stations, model.fartherStationCode) + sy;
const closerStationValue = this.planUtil.getCoordinateYByStationCode(this.stations, model.closerStationCode) + sy;
const fartherStation = this.planUtil.getStationByCoordinate(this.stations, fartherStationValue)||{code: model.fartherStationCode};
const closerStation = this.planUtil.getStationByCoordinate(this.stations, closerStationValue)||{code: model.closerStationCode};
model.startTime = timeFormat(toTimeStamp(model.startTime)+sx);
model.endTime = timeFormat(toTimeStamp(model.endTime)+sx);
model.fartherStationCode = fartherStation.code;
model.closerStationCode = closerStation.code;
}
this.$emit('translate');
}
}
}

View File

@ -1,110 +1,57 @@
<template>
<div id="PlanSchedule">
<el-card class="box-card">
<div slot="header" class="header">
<div class="menus-left">
<el-button type="primary" @click="handleNewPlan">New</el-button>
</div>
<div class="menus-right">
<span style="font-size:22px;padding:0 17px;">Plan</span>
<el-button-group v-model="active">
<el-button v-for="(el,i) in buttonList"
:type="active == i? 'primary':''"
:key="i" @click="handleBtnSelect(el,i)">{{el.name}}</el-button>
</el-button-group>
<el-button-group style="margin-left: 20px">
<el-button :type="selected?'danger':'info'" icon="el-icon-delete" @click="handleRemove" />
</el-button-group>
</div>
<el-card class="box-card">
<div slot="header" >
<slot name="header" />
</div>
<div :id="runPlanId" />
</el-card>
<plan-just-running :selected="selected" :stations="stations" @justRunning="handleJustRunning" />
<plan-just-stop :selected="selected" :stations="stations" @justStop="handleJustStop"/>
<div :id="canvasId" />
</el-card>
</div>
</template>
<script>
import echarts from 'echarts';
import PlanJustRunning from './dialog/planJustRunning.vue';
import PlanJustStop from './dialog/planJustStop.vue';
import Monitor from './monitor.js';
import { mapGetters } from 'vuex';
import { timeFormat } from '@/utils/date';
import { getStationList } from '@/api/runplan';
import { getRpTools, clearRpPlan, addRpTrip, delRpTrip, justTripNoRunning, justTripNoStop, translateTripNo} from '@/api/rpTools';
import { getPublishMapInfo } from '@/api/jmap/map';
export default {
components: {
PlanJustRunning,
PlanJustStop
},
mixins: [Monitor],
props: {
planConvert: {
planUtil: {
type: Object,
required: true
},
maxWidth: {
},
model: {
type: Object,
required: true
},
width: {
type: Number,
required: true
},
maxHeight: {
height: {
type: Number,
required: true
},
loadRunPlanId: {
type: String,
default() {
return '';
}
},
loadRunPlanName: {
type: String,
default() {
return '';
}
}
},
mixins: [Monitor],
},
title: {
type: String,
default: ''
},
canvasId: {
type: String,
default: 'service-tool'
}
},
data() {
return {
height: 0,
mapName: 'XXX',
runPlanId: 'plan-tool',
myChart: null,
kmRangeCoordMap: {},
stationsObj: {},
active: -1,
action: '',
buttonList: [
{
name: 'Add',
type: 'Add'
},
{
name: 'Translate',
type: 'Translate'
},
{
name: 'Edit',
type: 'Edit'
}
]
myChart: null,
stations: [],
planData: [],
};
},
computed: {
...mapGetters('rpTools', [
'stations'
]),
planId() {
return this.$route.query.planId;
},
mapId() {
return 9;
},
option() {
return {
},
computed: {
option() {
return {
title: {
text: '',
left: 'center',
@ -189,148 +136,177 @@ export default {
},
min: 0,
max: 0
},
graphic: [{
id: 'shape',
elements: []
}],
},
graphic: [{
id: 'shape',
elements: []
}],
series: [],
dataZoom: [
{
type: 'inside',
zoomOnMouseWheel : 'ctrl',
moveOnMouseMove : 'ctrl',
moveOnMouseWheel: 'ctrl'
type: 'inside',
zoomOnMouseWheel : true,
moveOnMouseMove : 'ctrl',
},
{
type: 'slider',
filterMode: 'empty',
fiterMode: 'filter',
handleSize: '80%',
handleStyle: {
color: '#fff',
shadowBlur: 3,
shadowColor: 'rgba(0, 0, 0, 0.6)',
shadowOffsetX: 2,
shadowOffsetY: 2
},
bottom: '20px'
}
]
}
}
},
watch: {
maxWidth() {
this.setPosition();
},
maxHeight() {
this.setPosition();
},
'$store.state.rpTools.planSizeCount': function () {
this.reSize({ width: this.$store.state.rpTools.width, height: this.$store.state.rpTools.height });
},
'$store.state.rpTools.refreshCount': function() {
this.loadChartPage();
},
$route() {
this.$nextTick(() => {
this.loadChartPage();
});
},
loadRunPlanId() {
this.loadChartPage();
}
}
},
mounted() {
this.setPosition();
this.loadChartPage();
},
},
watch: {
width() {
this.reSize({width: this.width, height: this.height})
},
height() {
this.reSize({width: this.width, height: this.height})
}
},
mounted() {
this.loadInitChart();
},
beforeDestroy() {
this.destroy();
},
methods: {
setPosition() {
this.$nextTick(() => {
const width = this.maxWidth;
const height = this.maxHeight;
this.$store.dispatch('rpTools/resize', { width, height });
});
xAxisPointFormat(params) {
return timeFormat(params.value);
},
yAxisPointFormat(params) {
return this.planUtil.computedFormatYAxis(this.stations, params);
},
xAxisLableFormat(value, index) {
if (value % 60 === 0) {
return timeFormat(value);
}
},
yAxisLableFormat(value, index) {
return '';
},
loadInitChart() {
axisTooltip(param) {
let data = '';
if (param.data &&
param.data.length) {
const xVal = param.data[0];
const yObj = param.data[1];
const model = param.value[2];
const station = this.stations.find(el => { return el.code == yObj.stationCode })||{ name: '', kmRange: ''};
const list = [
`Service No: ${model.serviceNo}<br>`,
`Trip No: ${model.tripNo}<br>`,
`direction: ${model.direction == 2? 'Up': 'Down'}<br>`,
`Station name: ${station.name}<br>`,
`Kilometer post: ${station.kmRange} m <br>`,
`Arrival Time: ${timeFormat(xVal + this.planUtil.TranslationTime)}<br>`,
`<hr size=1 style="margin: 3px 0">`
];
data += list.join('');
}
return data;
},
loadInitChart() {
return new Promise((resolve, reject) => {
try {
if (this.myChart && this.myChart.isDisposed) {
this.myChart.clear();
}
if (this.$route.query.planName || this.$route.query.prdType === '05') {
this.option.title.text = this.mapName;
}
this.myChart = echarts.init(document.getElementById(this.runPlanId));
this.option.title.text = this.this.title;
}
this.myChart = echarts.init(document.getElementById(this.canvasId));
this.myChart.setOption(this.option, {notMerge: true});
this.reSize({ width: this.$store.state.rpTools.width, height: this.$store.state.rpTools.height });
this.reSize({ width: this.width, height: this.height });
resolve(true);
} catch (error) {
reject(error);
}
});
},
async loadChartPage() {
},
loadChartPage(stations) {
try {
this.$store.dispatch('rpTools/clear').then(() => {
this.loadInitChart().then(() => {
if (this.mapId) {
getStationList(this.mapId).then(resp => {
const stations = resp.data.filter(el => {
return ['车辆段', '停车场'].findIndex(it => {
return el.name.includes(it)
}) < 0;
});
if (this.myChart) {
this.myChart.showLoading();
this.stationsObj = {};
stations.forEach(item => {
this.stationsObj[Math.floor(item.kmRange)] = item;
});
this.stations = stations;
this.xAxisInit(stations);
this.yAxisInit(stations);
this.$store.dispatch('rpTools/setStations', stations).then(() => {
this.loadInitData();
this.myChart && this.myChart.showLoading();
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
this.myChart && this.myChart.hideLoading();
});
}).catch(() => {
this.myChart && this.myChart.hideLoading();
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
});
});
}).catch(() => {
this.$messageBox(this.$t('tip.requestingStationDataFailed'));
this.$store.dispatch('rpTools/setStations', []);
});
}
});
});
this.myChart.setOption(this.option, {notMerge: true});
this.myChart.hideLoading();
}
} catch (error) {
this.$messageBox(this.$t('error.loadingOperationGraphFailed'));
this.$messageBox(error.message);
}
},
async loadInitData() {
await this.xAxisInit();
await this.yAxisInit();
await this.loadInitChart();
},
async loadChartData() {
loadChartData(planData) {
try {
const stations = this.$store.state.rpTools.stations;
const planData = this.$store.state.rpTools.planData;
const option = this.myChart.getOption();
option.series = [];
option.graphic[0].elements = [];
option.graphic[0].elements = [];
this.kmRangeCoordMap = this.planConvert.convertStationsToMap(stations);
this.pushModels(option.series, [this.planConvert.initializeYaxis(this.stations)]);
this.pushModels(option.series, this.planConvert.convertDataToModels(planData, stations, this.kmRangeCoordMap, { width: 0.5, color: '#000' }));
this.planData = planData;
this.myChart.setOption(option, {notMerge: true});
this.pushModels(option.series, [this.planUtil.initializeYaxis(this.stations)]);
this.pushModels(option.series, this.planUtil.parseDataToSeries(this.myChart, planData, this.stations));
this.pushModels(option.graphic[0].elements, this.planUtil.parseDataToGraph(this.myChart, planData, this.stations));
this.myChart.setOption(option, {notMerge: true});
} catch (error) {
this.$messageBox(this.$t('error.loadingOperationGraphFailed') + this.$t('global.colon') + error.message);
this.$messageBox(error.message);
}
},
xAxisInit(stations) {
const option = this.option;
const startValue = 3600 * 6;
const offsetTime = 3600 / 2;
const list = [];
for (var time = 0 + this.planUtil.TranslationTime; time < 3600 * 24 + this.planUtil.TranslationTime; time++) {
list.push(time);
}
option.xAxis[0].data = list;
if (!option.dataZoom[0].startValue) {
option.dataZoom[0].startValue = option.dataZoom[1].startValue = startValue - offsetTime;
}
if (!option.dataZoom[0].endValue) {
option.dataZoom[0].endValue = option.dataZoom[1].endValue = startValue + offsetTime;
}
},
yAxisInit(stations) {
const option = this.option;
if (Object.keys(this.planUtil).length) {
this.pushModels(option.series, [this.planUtil.initializeYaxis(stations)]);
option.yAxis.min = this.planUtil.computedYaxisMinValue(stations);
option.yAxis.max = this.planUtil.computedYaxisMaxValue(stations);
}
},
reSize({width, height}) {
if (this.myChart) {
this.myChart.resize({ width, height, silent: false });
}
},
pushModels(series, models) {
destroy() {
if (this.myChart && this.myChart.isDisposed) {
this.myChart.dispose();
this.myChart = null;
}
},
pushModels(series, models) {
if (models && models.length) {
models.forEach(elem => {
if (elem) {
@ -353,196 +329,62 @@ export default {
return series;
},
destroy() {
if (this.myChart && this.myChart.isDisposed) {
this.myChart.dispose();
this.myChart = null;
}
},
xAxisPointFormat(params) {
return timeFormat(params.value);
},
yAxisPointFormat(params) {
return this.planConvert.computedFormatYAxis(this.stations, params);
},
xAxisLableFormat(value, index) {
if (value % 60 === 0) {
return timeFormat(value);
}
},
yAxisLableFormat(value, index) {
return '';
},
xAxisInit() {
const list = [];
for (var time = 0 + this.planConvert.TranslationTime; time < 3600 * 24 + this.planConvert.TranslationTime; time++) {
list.push(time);
}
const startValue = 3600 * 6;
const offsetTime = 3600 / 2;
this.option.xAxis[0].data = list;
if (!this.option.dataZoom[0].startValue) {
this.option.dataZoom[0].startValue = this.option.dataZoom[1].startValue = startValue - offsetTime;
}
if (!this.option.dataZoom[0].endValue) {
this.option.dataZoom[0].endValue = this.option.dataZoom[1].endValue = startValue + offsetTime;
}
},
yAxisInit() {
if (Object.keys(this.planConvert).length) {
this.pushModels(this.option.series, [this.planConvert.initializeYaxis(this.stations)]);
this.option.yAxis.min = this.planConvert.computedYaxisMinValue(this.stations);
this.option.yAxis.max = this.planConvert.computedYaxisMaxValue(this.stations);
}
},
axisTooltip(param) {
let data = '';
const arr = [];
const station = this.stations.find(el => { return el.code == param.value[2] })||{ name: '', kmRange: ''};
if (!arr.includes(`${param.data[0]}${param.data[1]}`)) {
arr.push(`${param.data[0]}${param.data[1]}`);
const list = [
`Station name: ${station.name}<br>`,
`Kilometer post: ${station.kmRange} m <br>`,
`Arrival Time: ${timeFormat(param.data[0] + this.planConvert.TranslationTime)}<br>`,
`Train number: ${param.seriesName}${param.data[3]}`,
`<hr size=1 style="margin: 3px 0">`
];
data += list.join('');
}
return data;
},
reSize(opt) {
if (this.myChart) {
this.myChart.resize({
width: opt.width,
height: opt.height,
silent: false
});
}
},
handleBtnSelect(el, i) {
if (this.active != i) {
this.handleCancel();
this.active = i;
this.action = el.type;
} else {
this.handleCancel();
}
},
handleCancel() {
this.setLineReset();
this.clearGraphic(['drag', 'mark']);
this.active = -1;
this.action = '';
this.selected = null;
},
handleNewPlan() {
clearRpPlan().then(resp => {
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
});
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
setLineLight() {
if (this.selected) {
this.myChart.setOption({
series: {
name: this.selected.seriesName,
symbolSize: 6,
showAllSymbol: true,
lineStyle: {
width: 2,
color: '#0000FF'
}
}
});
}).catch(error => {
this.$message(error.message);
}
},
setLineReset() {
if (this.selected) {
this.myChart.setOption({
series: {
name: this.selected.seriesName,
symbolSize: 1,
showAllSymbol: true,
lineStyle: {
width: 1,
color: '#000000'
}
}
});
}
},
clearTrip() {
const option = this.myChart.getOption();
const index = option.series.findIndex(el => { return el.name.includes('service-trip') });
if (index >= 0) {
option.series[index].data = [];
this.myChart.setOption(option, {notMerge: true});
}
},
clearGraphic(labels=['drag', 'mark']) {
const option = this.myChart.getOption();
const elements = option.graphic[0].elements;
option.graphic[0].elements = elements.filter(el => { return !labels.includes(el.subType)});
this.myChart.setOption(option, {notMerge: true});
},
clearDraggable(labels=['drag', 'area']) {
const option = this.myChart.getOption();
const elements = option.graphic[0].elements;
const elemList = elements.filter(el => { return labels.includes(el.subType)});
elemList.forEach(el => {
el.draggable = false;
el.ondrag = null;
el.onmousemove = null;
})
},
handleCreateTrip(data) {
if (this.myChart) {
addRpTrip(data).then(resp => {
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
});
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
});
}).catch(error => {
this.$message(error.message);
this.clearGraphic(['mark']);
})
}
},
handleTranslate(data) {
if (this.selected) {
const model = {
seconds : this.selected.time
}
translateTripNo(this.selected.seriesId, model).then(resp => {
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
});
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
});
}).catch(error => {
this.$message(error.message);
});
}
},
handleJustRunning(time) {
if (this.selected) {
const model = {
seconds: time,
stationCode: this.selected.stationCode
}
justTripNoRunning(this.selected.seriesId, model).then(resp => {
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
});
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
});
}).catch(error => {
this.$message(error.message);
})
}
},
handleJustStop(time){
if (this.selected) {
const model = {
seconds: time,
stationCode: this.selected.stationCode
}
justTripNoStop(this.selected.seriesId, model).then(resp => {
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
});
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
});
}).catch(error => {
this.$message(error.message);
})
}
},
handleRemove() {
if (this.myChart && this.selected) {
delRpTrip(this.selected.seriesId).then(resp => {
getRpTools().then(rest => {
this.$store.dispatch('rpTools/setPlanData', rest.data).then(() => {
this.loadChartData();
this.handleCancel();
});
}).catch(() => {
this.$messageBox(this.$t('error.obtainOperationGraphFailed'));
});
}).catch(error => {
this.$message(error.message);
})
}
this.myChart.setOption(option, {notMerge: true});
}
}
};
@ -555,22 +397,5 @@ export default {
width: 100%;
height: 100%;
position: relative;
.header {
margin: 0 80px;
display: flex;
justify-content: space-between;
align-items: center;
.menus-left {
display: flex;
align-items: center;
}
.menus-right {
display: flex;
align-items: center;
}
}
}
</style>

View File

@ -0,0 +1,81 @@
import echarts from 'echarts';
export const MenuEnum = {
planJustRunning: '1000',
planJustStop: '1001',
planSetParams: '1002',
planModifyArea: '1003',
planSetAreaNote: '1004',
planJustTurnBack: '1005'
}
export function buildDragDataObj(position, point, that) {
return {
type: 'circle',
subType: 'drag',
position: [...position],
point: [...point],
shape: {
cx: 0,
cy: 0,
r: 10
},
invisible: true,
draggable: 'horizontal',
onmouseover: echarts.util.curry(that.onShapeMouseOver),
ondrag: echarts.util.curry(that.onShapeDragging),
onmouseout: echarts.util.curry(that.onShapeMouseOut),
z: 100
}
}
export function buildMarkPointObj(position, point, that) {
return {
type: 'circle',
subType: 'mark',
z: 100,
position: [...position],
point: [...point],
shape: {
cx: 0,
cy: 0,
r: 10
},
style: {
fill: 'rgba(0,0,0,0.3)'
}
}
}
export function createTripModel(opt, lineStyle={}, itemStyle={}) {
return {
z: opt.z || 10,
type: 'line',
name: opt.name,
data: opt.data,
sampling: 'average',
symbolSize: opt.symbolSize,
showAllSymbol: opt.showAllSymbol||'auto',
lineStyle: lineStyle,
itemStyle: itemStyle,
animation: false
};
}
export function findNext(list, idx, cb) {
for(var i = idx+1; i < list.length; i++) {
if (cb(list[i], i)) {
return list[i];
}
}
return null;
}
export function findPrev(list, idx, cb) {
for(var i = idx-1; i >= 0; i--) {
if (cb(list[i], i)) {
return list[i];
}
}
return null;
}

View File

@ -1,70 +1,48 @@
<template>
<el-dialog v-dialogDrag :title="title" :visible.sync="dialogVisible" width="60%" :before-close="handleClose" center :close-on-click-modal="false">
<data-form ref="datatop" :form="formTop" :inline="inline" :form-model="formModel" :rules="topRules" />
<el-form v-if="data.type === 'PSL' || data.type === 'PSC'" ref="form" :model="formModel" label-width="220px" :rules="topRules" :inline="inline">
<el-form-item label="关联地图:" prop="mapId">
<el-select v-model="mapId" placeholder="请选择" size="small" style="width: 180px" @change="mapIdChange">
<el-option
v-for="item in mapList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="关联车站:" prop="stationCode">
<el-select v-model="stationCode" placeholder="请选择" size="small" style="width: 180px" @change="stationCodeChange">
<el-option
v-for="item in stationList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
<el-form-item label="关联站台:" prop="standCode">
<el-select v-model="standCode" placeholder="请选择" size="small" style="width: 180px" @change="standCodeChange">
<el-option
v-for="item in standList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
<el-form-item label="关联屏蔽门:" prop="psdCode">
<el-select v-model="formModel.psdCode" placeholder="请选择" style="width: 180px" size="small">
<el-option
v-for="item in psdList"
:key="item.code"
:label="item.code"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-form>
<el-row :gutter="20">
<el-col :span="data.type !== 'PSC'?12:24">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>输入配置:</span>
</div>
<div style="margin-top: 20px">
<data-form ref="dataleft" :form="formLeft" :form-model="formModel" :rules="leftRules" :inline="data.type === 'PSC'" />
</div>
</el-card>
</el-col>
<el-col v-if="data.type !== 'PSC'" :span="12">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>输出配置:</span>
</div>
<div style="margin-top: 20px">
<data-form ref="dataright" :form="formRight" :form-model="formModel" :rules="rightRules" />
</div>
</el-card>
</el-col>
</el-row>
<!--<el-form v-if="data.type === 'PSL' || data.type === 'PSC'" ref="form" :model="formModel" label-width="220px" :rules="topRules" :inline="inline">-->
<!--<el-form-item label="关联地图:" prop="mapId">-->
<!--<el-select v-model="mapId" placeholder="请选择" size="small" style="width: 180px" @change="mapIdChange">-->
<!--<el-option-->
<!--v-for="item in mapList"-->
<!--:key="item.id"-->
<!--:label="item.name"-->
<!--:value="item.id"-->
<!--/>-->
<!--</el-select>-->
<!--</el-form-item>-->
<!--<el-form-item label="关联车站:" prop="stationCode">-->
<!--<el-select v-model="stationCode" placeholder="请选择" size="small" style="width: 180px" @change="stationCodeChange">-->
<!--<el-option-->
<!--v-for="item in stationList"-->
<!--:key="item.code"-->
<!--:label="item.name"-->
<!--:value="item.code"-->
<!--/>-->
<!--</el-select>-->
<!--</el-form-item>-->
<!--<el-form-item label="关联站台:" prop="standCode">-->
<!--<el-select v-model="standCode" placeholder="请选择" size="small" style="width: 180px" @change="standCodeChange">-->
<!--<el-option-->
<!--v-for="item in standList"-->
<!--:key="item.code"-->
<!--:label="item.name"-->
<!--:value="item.code"-->
<!--/>-->
<!--</el-select>-->
<!--</el-form-item>-->
<!--<el-form-item label="关联屏蔽门:" prop="psdCode">-->
<!--<el-select v-model="formModel.psdCode" placeholder="请选择" style="width: 180px" size="small">-->
<!--<el-option-->
<!--v-for="item in psdList"-->
<!--:key="item.code"-->
<!--:label="item.code"-->
<!--:value="item.code"-->
<!--/>-->
<!--</el-select>-->
<!--</el-form-item>-->
<!--</el-form>-->
<el-input v-model="jsonConfig" autosize type="textarea" />
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
<el-button @click="handleClose">{{ $t('global.cancel') }}</el-button>
@ -91,89 +69,19 @@ export default {
addrName: '',
data: {},
titleMap: { SWITCH: '道岔', PSD:'屏蔽门', SIGNAL: '信号机', PSL:'端头控制盒', PSC: 'PSC控制柜' },
psdLeftValue: [
{label: '输入-是否关门位', value: 'i_c'},
{label: '输入-PSL关门按钮位', value: 'i_dc_b'},
{label: '输入-PSL开门按钮位', value: 'i_do_b'},
{label: '输入-互锁解除钥匙开关位', value: 'i_ir'},
{label: '输入-是否锁闭位', value: 'i_l'},
{label: '输入-PSL允许钥匙开关位', value: 'i_psl'},
{label: '输入-PSL试灯按钮位', value: 'i_ts_b'}
],
psdRightValue: [
{label: '输出-关门位', value: 'o_c'},
{label: '输出-关门信号灯控制位', value: 'o_dc_s'},
{label: '输出-关门且锁闭信号灯控制位', value: 'o_dcl_s'},
{label: '输出-开门信号灯控制位', value: 'o_do_s'},
{label: '输出-互锁解除信号灯控制位', value: 'o_ir_s'},
{label: '输出-锁闭位', value: 'o_l'},
{label: '输出-开门位', value: 'o_o'},
{label: '输出-PSL信号灯控制位', value: 'o_psl_s'}
],
switchValue: [
{label: '网关地址', value: 'addr'},
{label: '定位表示', value: 'rnp'},
{label: '反位表示', value: 'rrp'},
{label: '定位控制', value: 'wnp'},
{label: '反位控制', value: 'wrp'},
{label: '锁闭控制', value: 'wl'}
],
signalLeftValue: [
{label: '输入-故障表示位', value: 'i_f'},
{label: '输入-绿灯表示位', value: 'i_g'},
{label: '输入-黄灯表示位', value: 'i_y'},
{label: '输入-黄红灯表示位', value: 'i_yr'}
],
signalRightValue: [
{label: '输出-故障控制位', value: 'o_f'},
{label: '输出-绿灯控制位', value: 'o_g'},
{label: '输出-红灯控制位', value: 'o_r'},
{label: '输出-黄灯控制位', value: 'o_y'},
{label: '输出-黄红灯控制位', value: 'o_yr'}
],
pslLeftValue: [
{label: '读PSL操作旋钮位', value: 'rpslcz'},
{label: '读关门按钮位', value: 'rgman'},
{label: '读开门按钮位', value: 'rkman'},
{label: '读互锁解除开关位', value: 'rjc'},
{label: '读试灯按钮位', value: 'rsdan'},
{label: '读紧急停车按钮位', value: 'rjtan'}
],
pslRightValue: [
{label: '写全部关门指示灯位', value: 'wqbgbd'},
{label: '写开门到位指示灯位', value: 'wkmdwd'},
{label: '写PSL允许指示灯位', value: 'wpslyxd'},
{label: '写互锁解除指示灯位', value: 'wjcd'},
{label: '写IBP盘操作指示灯位', value: 'wibpczd'},
{label: '写PST操作指示灯位', value: 'wpstczd'}
],
mapId: '',
mapList: [],
stationCode: '',
stationList: [],
standList: [],
standCode: '',
psdList: []
psdList: [],
jsonConfig: ''
};
},
computed: {
formTop() {
return {
labelWidth: '220px',
items: [
{ prop:'addr', label: this.addrName, type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'quantity', label: '位数量:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0 }
]
};
},
topRules() {
return {
addr: [
{ required: true, message: '请填写网关地址', trigger: 'blur' }
],
quantity: [
{ required: true, message: '请填写位数量', trigger: 'blur'}
],
psdCode: [
{ required: true, message: '请选择关联屏蔽门', trigger: 'change'}
]
@ -185,372 +93,40 @@ export default {
},
methods: {
initForm(row) {
var validateDevice = (rule, value, callback) => {
const list = [];
rule.list.forEach(item=> {
if (this.formModel[item.value] && this.formModel[item.value] === value) {
list.push(item.label);
}
});
if (!this.formModel.quantity) {
this.$refs.datatop.validateField('quantity');
}
if (list.length > 1) {
let repeatedValue = '';
list.forEach((item, index) => {
repeatedValue += item;
if (index !== list.length - 1) {
repeatedValue += '与';
}
});
callback(new Error(repeatedValue + '位置重复,请调整!'));
} else if (this.formModel.quantity && value >= this.formModel.quantity) {
callback(new Error('网关位应小于位数量!'));
} else {
callback();
}
};
var validateAddr = (rule, value, callback) => {
if (!value && value !== 0) {
callback(new Error(rule.messageEmpty));
} else if (this.formModel.i_addr === this.formModel.o_addr) {
callback(new Error('输入网关字地址与输出网关字地址不能相同!'));
} else {
callback();
}
};
switch (row.type) {
case 'PSD': {
this.setDeviceConfigFunction = setPsdConfig;
this.formLeft = {
labelWidth: '220px',
items: [
{ prop:'i_addr', label:'输入网关字地址:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'i_c', label: '输入-是否关门位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_dc_b', label: '输入-PSL关门按钮位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_do_b', label: '输入-PSL开门按钮位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_ir', label: '输入-互锁解除钥匙开关位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_l', label: '输入-是否锁闭位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_psl', label: '输入-PSL允许钥匙开关位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_ts_b', label: '输入-PSL试灯按钮位:', type: 'text', rightWidth: '100px', maxlength: 4}
]
};
this.leftRules = {
i_addr: [
{ validator: validateAddr, messageEmpty: '请填写输入网关字地址', trigger: 'blur' }
],
i_c: [
{ validator: validateDevice, messageEmpty: '请填写输入-是否关门位', list: this.psdLeftValue, trigger: 'blur' }
],
i_dc_b: [
{validator: validateDevice, messageEmpty: '请填写输入-PSL关门按钮位', list: this.psdLeftValue, trigger: 'blur' }
],
i_do_b: [
{ validator: validateDevice, messageEmpty: '请填写输入-PSL开门按钮位', list: this.psdLeftValue, trigger: 'blur' }
],
i_ir: [
{ validator: validateDevice, messageEmpty: '请填写输入-互锁解除钥匙开关位', list: this.psdLeftValue, trigger: 'blur' }
],
i_l: [
{ validator: validateDevice, messageEmpty: '请填写输入-是否锁闭位', list: this.psdLeftValue, trigger: 'blur' }
],
i_psl: [
{ validator: validateDevice, messageEmpty: '请填写输入-PSL允许钥匙开关位', list: this.psdLeftValue, trigger: 'blur' }
],
i_ts_b: [
{ validator: validateDevice, messageEmpty: '请填写输入-PSL试灯按钮位', list: this.psdLeftValue, trigger: 'blur' }
]
};
this.formRight = {
labelWidth: '220px',
items: [
{ prop: 'o_addr', label: '输出网关字地址:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'o_c', label: '输出-关门位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_dc_s', label: '输出-关门信号灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_dcl_s', label: '输出-关门且锁闭信号灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_do_s', label: '输出-开门信号灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_ir_s', label: '输出-互锁解除信号灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_l', label: '输出-锁闭位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_o', label: '输出-开门位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_psl_s', label: '输出-PSL信号灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4}
]
};
this.rightRules = {
o_addr: [
{ validator: validateAddr, messageEmpty: '请填写输出网关字地址', trigger: 'blur' }
],
o_c: [
{ validator: validateDevice, messageEmpty: '请填写输出-关门位', list: this.psdRightValue, trigger: 'blur' }
],
o_dc_s: [
{ validator: validateDevice, messageEmpty: '请填写输出-关门信号灯控制位', list: this.psdRightValue, trigger: 'blur' }
],
o_dcl_s: [
{ validator: validateDevice, messageEmpty: '请填写输出-关门且锁闭信号灯控制位', list: this.psdRightValue, trigger: 'blur' }
],
o_do_s: [
{ validator: validateDevice, messageEmpty: '请填写输出-开门信号灯控制位', list: this.psdRightValue, trigger: 'blur' }
],
o_ir_s: [
{ validator: validateDevice, messageEmpty: '请填写输出-互锁解除信号灯控制位', list: this.psdRightValue, trigger: 'blur' }
],
o_l: [
{ validator: validateDevice, messageEmpty: '请填写输出-锁闭位', list: this.psdRightValue, trigger: 'blur' }
],
o_o: [
{ validator: validateDevice, messageEmpty: '请填写输出-开门位', list: this.psdRightValue, trigger: 'blur' }
],
o_psl_s: [
{ validator: validateDevice, messageEmpty: '请填写输出-PSL信号灯控制位', list: this.psdRightValue, trigger: 'blur' }
]
};
break;
}
case 'SIGNAL': {
this.setDeviceConfigFunction = setSignalConfig;
this.formTop.labelWidth = '150px';
this.formLeft = {
labelWidth: '150px',
items: [
{ prop:'i_addr', label:'输入网关字地址:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'i_f', label: '输入-故障表示位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_g', label: '输入-绿灯表示位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_y', label: '输入-黄灯表示位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'i_yr', label: '输入-黄红灯表示位:', type: 'text', rightWidth: '100px', maxlength: 4}
]
};
this.leftRules = {
i_addr: [
{ validator: validateAddr, messageEmpty: '请填写输入网关字地址', trigger: 'blur' }
],
i_f: [
{ validator: validateDevice, messageEmpty: '请填写输入-故障表示位', list: this.signalLeftValue, trigger: 'blur' }
],
i_g: [
{ validator: validateDevice, messageEmpty: '请填写输入-绿灯表示位', list: this.signalLeftValue, trigger: 'blur' }
],
i_y: [
{ validator: validateDevice, messageEmpty: '请填写输入-黄灯表示位', list: this.signalLeftValue, trigger: 'blur' }
],
i_yr: [
{ validator: validateDevice, messageEmpty: '请填写输入-黄红灯表示位', list: this.signalLeftValue, trigger: 'blur'}
]
};
this.formRight = {
labelWidth: '150px',
size: 'mini',
items: [
{ prop: 'o_addr', label: '输出网关字地址:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'o_f', label: '输出-故障控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_g', label: '输出-绿灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_r', label: '输出-红灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_y', label: '输出-黄灯控制位:', type: 'text', rightWidth: '100px', maxlength: 4},
{ prop: 'o_yr', label: '输出-黄红灯控制位', type: 'text', rightWidth: '100px', maxlength: 4}
]
};
this.rightRules = {
o_addr: [
{ validator: validateAddr, messageEmpty: '请填写输出网关字地址', trigger: 'blur' }
],
o_f: [
{ validator: validateDevice, messageEmpty: '请填写输出-故障控制位', list: this.signalRightValue, trigger: 'blur' }
],
o_g: [
{ validator: validateDevice, messageEmpty: '请填写输出-绿灯控制位', list: this.signalRightValue, trigger: 'blur' }
],
o_r: [
{ validator: validateDevice, messageEmpty: '请填写输出-红灯控制位', list: this.signalRightValue, trigger: 'blur' }
],
o_y: [
{ validator: validateDevice, messageEmpty: '请填写输出-黄灯控制位', list: this.signalRightValue, trigger: 'blur' }
],
o_yr: [
{ validator: validateDevice, messageEmpty: '请填写输出-黄红灯控制位', list: this.signalRightValue, trigger: 'blur'}
]
};
break;
}
case 'SWITCH': {
this.setDeviceConfigFunction = setSwitchConfig;
this.addrName = '网关地址:';
this.formTop.labelWidth = '220';
this.formLeft = {
labelWidth: '220px',
items: [
{ prop: 'rnp', label: '定位表示:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'rrp', label: '反位表示:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0}
]
};
this.leftRules = {
rnp: [
{ required: true, message: '请填写-定位表示', trigger: 'blur' },
{ validator: validateDevice, list: this.switchValue, trigger: ['blur', 'change'] }
],
rrp: [
{ required: true, message: '请填写反位表示', trigger: 'blur' },
{ validator: validateDevice, list: this.switchValue, trigger: ['blur', 'change'] }
]
};
this.formRight = {
labelWidth: '160px',
items: [
{ prop: 'wnp', label: '定位控制:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wrp', label: '反位控制:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wl', label: '锁闭控制:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0}
]
};
this.rightRules = {
wnp: [
{ required: true, message: '请填写定位控制', trigger: 'blur' },
{ validator: validateDevice, list: this.switchValue, trigger: ['blur', 'change'] }
],
wrp: [
{ required: true, message: '请填写反位控制', trigger: 'blur' },
{ validator: validateDevice, list: this.switchValue, trigger: ['blur', 'change'] }
],
wl: [
{ required: true, message: '请填写锁闭控制', trigger: 'blur' },
{ validator: validateDevice, list: this.switchValue, trigger: ['blur', 'change'] }
]
};
break;
}
case 'PSL': {
this.setDeviceConfigFunction = setPslConfig;
this.addrName = '网关地址:';
this.formLeft = {
labelWidth: '170px',
items: [
{ prop: 'rpslcz', label: '读PSL操作旋钮位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'rgman', label: '读关门按钮位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'rkman', label: '读开门按钮位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'rjc', label: '读互锁解除开关位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'rsdan', label: '读试灯按钮位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'rjtan', label: '读紧急停车按钮位', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0}
]
};
this.leftRules = {
rpslcz: [
{ required: true, message: '请填写\'读PSL操作旋钮位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
rgman: [
{ required: true, message: '请填写\'读关门按钮位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
rkman: [
{ required: true, message: '请填写\'读开门按钮位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
rjc: [
{ required: true, message: '请填写\'读互锁解除开关位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
rsdan: [
{ required: true, message: '请填写\'读试灯按钮位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
rjtan: [
{ required: true, message: '请填写\'读紧急停车按钮位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
]
};
this.formRight = {
labelWidth: '170px',
items: [
{ prop: 'wqbgbd', label: '写全部关门指示灯位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wkmdwd', label: '写开门到位指示灯位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wpslyxd', label: '写PSL允许指示灯位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wjcd', label: '写互锁解除指示灯位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wibpczd', label: '写IBP盘操作指示灯位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wpstczd', label: '写PST操作指示灯位:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0}
]
};
this.rightRules = {
wqbgbd: [
{ required: true, message: '请填写\'写全部关门指示灯位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslRightValue, trigger: ['blur', 'change'] }
],
wkmdwd: [
{ required: true, message: '请填写\'写开门到位指示灯位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslRightValue, trigger: ['blur', 'change'] }
],
wpslyxd: [
{ required: true, message: '请填写\'写PSL允许指示灯位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslRightValue, trigger: ['blur', 'change'] }
],
wjcd: [
{ required: true, message: '请填写\'写互锁解除指示灯位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslRightValue, trigger: ['blur', 'change'] }
],
wibpczd: [
{ required: true, message: '请填写\'写IBP盘操作指示灯位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslRightValue, trigger: ['blur', 'change'] }
],
wpstczd: [
{ required: true, message: '请填写\'写PST操作指示灯位\'', trigger: 'blur' },
{ validator: validateDevice, list: this.pslRightValue, trigger: ['blur', 'change'] }
]
};
break;
}
case 'PSC': {
this.setDeviceConfigFunction = setPscConfig;
this.addrName = '网关位地址:';
this.formLeft = {
labelWidth: '220px',
items: [
{ prop: 'wpslsn', label: 'PSL使能:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wpslkm', label: 'PSL开门:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wpslgm', label: 'PSL关门:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wpslhsjc', label: 'PSL互锁解除:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wibpsn', label: 'IBP使能:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wibpkm', label: 'IBP开门:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0},
{ prop: 'wibpgm', label: 'IBP关门:', type: 'number', min: 0, max: 20000, step: 1, precisionFlag: true, precision: 0}
]
};
this.leftRules = {
wpslsn: [
{ required: true, message: '请填写PSL使能', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
wpslkm: [
{ required: true, message: '请填写PSL开门', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
wpslgm: [
{ required: true, message: '请填写PSL关门', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
wpslhsjc: [
{ required: true, message: '请填写PSL互锁解除', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
wibpsn: [
{ required: true, message: '请填写IBP使能', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
wibpkm: [
{ required: true, message: '请填写IBP开门', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
],
wibpgm: [
{ required: true, message: '请填写IBP关门', trigger: 'blur' },
{ validator: validateDevice, list: this.pslLeftValue, trigger: ['blur', 'change'] }
]
};
this.formRight = {};
this.rightRules = {};
break;
}
}
},
initData(row) {
this.jsonConfig = '{}';
getDeviceDetail(row.id).then(resp => {
if (resp.data.config) {
this.formModel = JSON.parse(resp.data.config);
this.jsonConfig = JSON.stringify(JSON.parse(resp.data.config), null, 4);
}
}).catch(()=> {
}).catch((e)=> {
this.$message.error('获取项目设备详情失败!');
});
if (row.type === 'PSL' || row.type === 'PSC') {
@ -579,36 +155,28 @@ export default {
flag = valid;
});
}
this.$refs.datatop.validateForm(() => {
self.$refs.dataleft.validateForm(()=> {
if (this.data.type === 'PSC') {
flag && self.setDeviceConfigFunction(this.data.id, this.formModel).then(response => {
self.$message.success('设置设备网关映射配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {
self.$message.error(this.$t('tip.modifyTheFailure') + error.message);
});
} else {
self.$refs.dataright.validateForm(()=> {
flag && self.setDeviceConfigFunction(this.data.id, this.formModel).then(response => {
self.$message.success('设置设备网关映射配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {
self.$message.error(this.$t('tip.modifyTheFailure') + error.message);
});
});
}
});
const form = JSON.parse(this.jsonConfig);
// if (this.data.type === 'PSC' || this.data.type === 'PSL') {
// form.psdCode = this.formModel.psdCode;
// flag && self.setDeviceConfigFunction(this.data.id, form).then(response => {
// self.$message.success('');
// self.handleClose();
// self.$emit('reloadTable');
// }).catch(error => {
// self.$message.error(this.$t('tip.modifyTheFailure') + error.message);
// });
// } else {
flag && self.setDeviceConfigFunction(this.data.id, form).then(response => {
self.$message.success('设置设备网关映射配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {
self.$message.error(this.$t('tip.modifyTheFailure') + error.message);
});
// }
},
handleClose() {
this.formModel = {};
this.formLeft = {};
this.formRight = {};
this.leftRules = {};
this.rightRules = {};
this.data = {};
this.mapList = [];
this.stationList = [];
@ -618,9 +186,6 @@ export default {
this.stationCode = '';
this.standCode = '';
this.dialogVisible = false;
this.$refs.datatop.resetForm();
this.$refs.dataleft.resetForm();
this.$refs.dataright && this.$refs.dataright.resetForm();
this.$refs.form && this.$refs.form.resetFields();
},
mapIdChange(mapId) {

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
</template>
<script>
import { getDevicesByType, getDeviceDetail, setLswConfig, setCctvConfig, setVrPsdConfig, setPlcConfig, setSandboxConfig } from '@/api/project';
import { getDevicesByType, getDeviceDetail, setLswConfig, setCctvConfig, setVrPsdConfig, setPlcConfig, setSandboxConfig, setIlwConfig } from '@/api/project';
import { getAllMapOnline, getStationListNeedAttendant, getPsdListByStandCode, getStandListByStationCode } from '@/api/jmap/map';
export default {
@ -108,6 +108,13 @@ export default {
{ prop: 'deviceCode', label: '教研机', type: 'select', options: this.deviceList, optionLabel: 'code', optionValue: 'code'}
]
};
} else if (this.data.type === 'ILW') {
form = {
labelWidth: '150px',
items: [
{ prop: 'deviceCode', label: '教研机', type: 'select', options: this.deviceList, optionLabel: 'code', optionValue: 'code'}
]
};
}
return form;
}
@ -245,7 +252,20 @@ export default {
deviceCode: this.formData.deviceCode
};
setSandboxConfig(this.data.id, param).then(() => {
self.$message.success('设置电子沙盘配置成员');
self.$message.success('设置电子沙盘配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {
self.$message.error(this.$t('tip.modifyTheFailure') + error.message);
});
});
} else if (this.data.type === 'ILW') {
this.$refs.dataForm.validateForm(() => {
const param = {
deviceCode: this.formData.deviceCode
};
setIlwConfig(this.data.id, param).then(() => {
self.$message.success('设置联锁工作站配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {

View File

@ -183,7 +183,7 @@ export default {
this.$refs.editConfig.doShow(row);
} else if (row.type === 'SWITCH' || row.type === 'SIGNAL' || row.type === 'PSD' || row.type === 'PSL' || row.type === 'PSC') {
this.$refs.editConfigGateway.doShow(row);
} else if (row.type == 'LSW' || row.type == 'CCTV' || row.type == 'VR_PSD' || row.type === 'PLC_GATEWAY' || row.type === 'SANDBOX') {
} else if (row.type == 'LSW' || row.type == 'CCTV' || row.type == 'VR_PSD' || row.type === 'PLC_GATEWAY' || row.type === 'SANDBOX' || row.type === 'ILW') {
this.$refs.editConfigScreen.doShow(row);
} else if (row.type === 'IBP') {
this.$refs.editConfigIbp.doShow(row);
@ -196,7 +196,7 @@ export default {
},
getPath(index, row) {
let url = '';
url = `${window.location.protocol}//${window.location.host}/login?project=${row.project.toLowerCase()}&projectDevice=${row.code}&type=${row.type}`;
url = `${window.location.protocol}//${window.location.host}/cbtc/login?project=${row.project.toLowerCase()}&projectDevice=${row.code}&type=${row.type}`;
this.url = url;
this.$messageBox();
this.$confirm(`登录路径:${url}`, '登录路径', {

View File

@ -0,0 +1,167 @@
<template>
<el-dialog v-dialogDrag title="添加出题规则" :visible.sync="dialogVisible" width="30%" :before-close="handleClose" center :close-on-click-modal="false">
<data-form ref="dataform" :form="form" :form-model="formModel" :rules="rules" />
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="doSave">{{ update? '修改' : $t('global.confirm') }}</el-button>
<el-button @click="dialogVisible = false">{{ $t('global.cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { addQuestionRule, updateQuestionRule } from '@/api/questionsRule';
export default {
name: 'Add',
props: {
companyList: {
type: Array,
required: true
}
},
data() {
return {
dialogVisible: false,
formModel: {
id: '',
companyId: '',
judgeNum: 0,
judgePoint: 0,
selectNum: 0,
selectPoint: 0,
multiNum: 0,
multiPoint: 0,
fillNum: 0,
fillPoint: 0,
answerNum: 0,
answerPoint: 0
},
update: false
};
},
computed:{
form() {
const form = {
labelWidth: '100px',
items: [
{ prop: 'companyId', label: '公司名称', type: 'select', options: this.companyList, optionValue: 'id', optionLabel: 'name' },
{ prop: 'judgeNum', label: '判断题数量', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'judgePoint', label: '判断题分数', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'selectNum', label: '单选题数量', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'selectPoint', label: '单选题分数', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'multiNum', label: '多选题数量', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'multiPoint', label: '多选题分数', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'fillNum', label: '填空题数量', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'fillPoint', label: '填空题分数', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'answerNum', label: '问答题数量', type: 'number', min: 0, max: 99, step: 1 },
{ prop: 'answerPoint', label: '问答题分数', type: 'number', min: 0, max: 99, step: 1 }
]
};
return form;
},
rules() {
const crules = {
companyId: [
{ required: true, message: '请选择单位', trigger: 'change' }
]
};
return crules;
}
},
methods: {
doShow(data) {
this.dialogVisible = true;
this.update = false;
if (data) {
this.update = true;
this.formModel.id = data.id;
this.formModel.companyId = data.companyId;
data.rules.forEach(item => {
if (item.type === 'judge') {
this.formModel.judgeNum = item.num;
this.formModel.judgePoint = item.point;
} else if (item.type === 'select') {
this.formModel.selectNum = item.num;
this.formModel.selectPoint = item.point;
} else if (item.type === 'multi') {
this.formModel.multiNum = item.num;
this.formModel.multiPoint = item.point;
} else if (item.type === 'fill') {
this.formModel.fillNum = item.num;
this.formModel.fillNum = item.point;
} else if (item.type === 'answer') {
this.formModel.answerNum = item.num;
this.formModel.answerPoint = item.point;
}
});
} else {
this.formModel = {
id: '',
companyId: '',
judgeNum: 0,
judgePoint: 0,
selectNum: 0,
selectPoint: 0,
multiNum: 0,
multiPoint: 0,
fillNum: 0,
fillPoint: 0,
answerNum: 0,
answerPoint: 0
};
}
},
handleClose() {
this.dialogVisible = false;
},
doSave() {
this.$refs.dataform.validateForm(() => {
const params = {
id: this.formModel.id,
companyId: this.formModel.companyId,
rules: []
};
if (this.formModel.judgeNum && this.formModel.judgePoint) {
params.rules.push({ type:'judge', num: this.formModel.judgeNum, point: this.formModel.judgePoint });
}
if (this.formModel.selectNum && this.formModel.selectPoint) {
params.rules.push({ type: 'select', num: this.formModel.selectNum, point: this.formModel.selectPoint});
}
if (this.formModel.multiNum && this.formModel.multiPoint) {
params.rules.push({ type: 'multi', num: this.formModel.multiNum, point: this.formModel.multiPoint});
}
if (this.formModel.fillNum && this.formModel.fillPoint) {
params.rules.push({ type: 'fill', num: this.formModel.fillNum, point: this.formModel.fillPoint });
}
if (this.formModel.answerNum && this.formModel.answerPoint) {
params.rules.push({ type: 'answer', num: this.formModel.answerNum, point: this.formModel.point});
}
if (this.update) {
updateQuestionRule(this.formModel.id, params).then(resp => {
this.$message.success('更新出题规则成功!');
this.dialogVisible = false;
this.$emit('reloadTable');
}).catch(e => {
this.$message.error('更新出题规则失败!');
});
} else {
addQuestionRule(params).then(resp => {
this.$message.success('添加出题规则成功!');
this.dialogVisible = false;
this.$emit('reloadTable');
}).catch(e => {
if (e.code == 10010) {
this.$message.error('关联改公司数据已存在!');
} else {
this.$message.error('添加出题规则失败!');
}
});
}
});
}
}
};
</script>
<style scoped>
</style>

View File

@ -0,0 +1,177 @@
<template>
<div>
<QueryListPage ref="queryListPage" :pager-config="pagerConfig" :query-form="queryForm" :query-list="queryList" />
<edit-questions-rule ref="editQuestionsRule" :company-list="companyList" @reloadTable="reloadTable" />
</div>
</template>
<script>
import { getQustionRuleListPage, deleteQuestionRule } from '@/api/questionsRule';
import { getCompanyList } from '@/api/company';
import EditQuestionsRule from './add';
export default {
name: 'CompanyManage',
components: {
EditQuestionsRule
},
data() {
return {
companyList: [],
pagerConfig: {
pageSize: 'pageSize',
pageIndex: 'pageNum'
},
queryForm: {
labelWidth: '80px',
reset: true,
queryObject: {
}
},
queryList: {
query: getQustionRuleListPage,
selectCheckShow: false,
columns: [
{
title: '公司名称',
prop: 'companyId',
type: 'tag',
columnValue: (row) => { return this.$convertField(row.companyId, this.companyList, ['id', 'name']); },
tagType: (row) => { return 'default'; }
},
{
title: '判断题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'judge', 'num'); },
tagType: (row) => { return 'success'; }
},
{
title: '判断题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'judge', 'point'); },
tagType: (row) => { return 'success'; }
},
{
title: '单选题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'select', 'num'); },
tagType: (row) => { return 'success'; }
},
{
title: '单选题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'select', 'point'); },
tagType: (row) => { return 'success'; }
},
{
title: '多选题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'multi', 'num'); },
tagType: (row) => { return 'success'; }
},
{
title: '多选题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'multi', 'point'); },
tagType: (row) => { return 'success'; }
},
{
title: '填空题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'fill', 'num'); },
tagType: (row) => { return 'success'; }
},
{
title: '填空题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'fill', 'point'); },
tagType: (row) => { return 'success'; }
},
{
title: '问答题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'answer', 'num'); },
tagType: (row) => { return 'success'; }
},
{
title: '问答题数量',
prop: 'rules',
type: 'tag',
columnValue: (row) => { return this.handlerRuleData(row.rules, 'answer', 'point'); },
tagType: (row) => { return 'success'; }
},
{
type: 'button',
title: this.$t('global.operate'),
width: '250',
buttons: [
{
name: this.$t('global.edit'),
handleClick: this.handleUpdate
},
{
name: '删除',
handleClick: this.handleDeleteCompany,
type: 'danger'
}
]
}
],
actions: [
{ text: '添加', btnCode: 'employee_auto', handler: this.handlerAddCompany },
{ text: '返回', btnCode: 'employee_auto', handler: this.handlerBack}
]
},
currentModel: {}
};
},
mounted() {
getCompanyList().then(resp => {
this.companyList = resp.data;
});
},
methods: {
handlerAddCompany() {
this.$refs.editQuestionsRule.doShow();
},
handleDeleteCompany(index, row) {
deleteQuestionRule(row.id).then(resp => {
this.$message.success('删除单位信息成功!');
this.reloadTable();
}).catch(() => {
this.$message.error('删除单位信息失败!');
});
},
handleUpdate(index, row) {
this.$refs.editQuestionsRule.doShow(row);
},
reloadTable() {
this.queryList.reload();
},
handlerBack() {
this.$router.go(-1);
},
handlerRuleData(rules, type, param) {
let value = 0;
rules && rules.forEach(item => {
if (item.type === type) {
value = item[param];
}
});
return value;
}
}
};
</script>
<style scoped>
</style>