Merge remote-tracking branch 'origin/test_device_login' into test

# Conflicts:
#	src/layout/components/Title.vue
#	src/views/demonstration/detail/index.vue
This commit is contained in:
fan 2020-07-07 09:47:21 +08:00
commit 421e591f52
42 changed files with 2882 additions and 720 deletions

View File

@ -26,8 +26,8 @@ export default {
}
},
watch: {
'$store.state.socket.roomInvite': function (val) {
if (val.creatorId) {
'$store.state.socket.simulationInvite': function (val) {
if (val.creator) {
this.subscribeMessage(val);
}
},
@ -73,7 +73,7 @@ export default {
if (getSessionStorage('project') != 'refereeJsxt' && getSessionStorage('project') != 'jsxt' && !(getSessionStorage('project').includes('design'))) {
this.$refs.deomonTopic.doShow(res);
}
this.$store.dispatch('socket/setRoomInvite');
this.$store.dispatch('socket/setSimulationInvite');
}
},
subscribe() {

View File

@ -360,4 +360,47 @@ export function quitCoversition(group, conversationId) {
method: 'delete'
});
}
/** 发起会话 */
export function startConversition(group, data) {
return request({
url: `/api/simulation/${group}/conversation`,
method: 'post',
data: data
});
}
/** 根据会话id获取仿真会话 */
export function getSimulationConversition(group, conversationId) {
return request({
url: `/api/simulation/${group}/conversation/${conversationId}`,
method: 'get'
});
}
/** 发送会话消息 */
export function sendSimulationConversition(group, conversationId, file) {
return request({
url: `/api/simulation/${group}/conversation/${conversationId}/chat`,
method: 'post',
data: file
});
}
/** 成员接收仿真会话邀请 */
export function acceptConversitionInvite(group, conversationId) {
return request({
url: `/api/simulation/${group}/conversation/${conversationId}/connect`,
method: 'post'
});
}
/** 结束仿真会话 */
export function overSimulationConversition(group, conversationId) {
return request({
url: `/api/simulation/${group}/conversation/${conversationId}/over`,
method: 'put'
});
}
/** 获取所有会话 */
export function getAllConversition(group) {
return request({
url: `/api/simulation/${group}/conversation/listAll`,
method: 'get'
});
}

View File

@ -208,3 +208,17 @@ export function getByGroupStationList(group) {
method: 'get'
});
}
/** 查询所有上线的地图信息列表 */
export function getAllMapOnline() {
return request({
url: `/api/map/online/all`,
method: 'get'
});
}
/** 查询地图下所有需要值班员的车站 */
export function getStationListNeedAttendant(id) {
return request({
url: `/api/map/${id}/station/needSupervisor`,
method: 'get'
});
}

View File

@ -0,0 +1,47 @@
import request from '@/utils/request';
// 分配(取消)用户角色扮演
export function assignUsersPlayRoles(data, group) {
return request({
url: `/api/jointSimulation/${group}/assignRoles`,
method: 'put',
data: data
});
}
// 添加新仿真成员
export function addSimulationMember(data, group) {
return request({
url: `/api/jointSimulation/${group}/member`,
method: 'post',
data: data
});
}
// 获取权限生成仿真用户
export function jointSimulationByPermission(group) {
return request({
url: `/api/jointSimulation/${group}/permission`,
method: 'post'
});
}
// 生成综合仿真分享二维码
export function getSimulationQrcode(group) {
return request({
url: `/api/jointSimulation/${group}/qrCode`,
method: 'get'
});
}
// 获取用户所在的综合演练
export function getSimulationListCantainUser() {
return request({
url: `/api/jointSimulation/list/containUser`,
method: 'get'
});
}
// 将制定用户踢出房间
export function kickOutMember(group, userId) {
return request({
url: `/api/jointSimulation/${group}/kickOut?userId=${userId}`,
method: 'delete'
});
}

View File

@ -83,3 +83,13 @@ export function checkLoginLine() {
method: 'get'
});
}
// 获取登录信息(用户&设备)
export function getLoginInfo(token) {
return request({
url: '/api/login/loginUserInfo',
method: 'get',
params: {
token
}
});
}

View File

@ -770,4 +770,24 @@ export function getMemberInfo(group, memberId) {
method: 'get'
});
}
/** 获取新版综合仿真仿真成员列表 */
export function getSimulationMemberList(group) {
return request({
url: `/simulation/${group}/members`,
method: 'get'
});
}
/** 获取仿真用户信息 */
export function getSimulationUserInfo(group) {
return request({
url: `/simulation/${group}/simulationUser`,
method: 'get'
});
}
// 获取所有仿真用户
export function getAllSimulationUser(group) {
return request({
url: `/simulation/${group}/simulationUsers`,
method: 'get'
});
}

View File

@ -206,5 +206,5 @@ export default {
permissionAllNum:'权限总数',
set: '设 置',
joinNewRoom: '加入新房间',
roomId: '房间号:'
roomId: '仿真号:'
};

View File

@ -30,7 +30,7 @@
</template>
<script>
import DeomonList from '@/views/demonstration/deomonList/index_APP_TARGET';
import DeomonList from '@/views/demonstration/deomonList/index';
import Qcode from './Qcode';
import { getSessionStorage } from '@/utils/auth';
import LangStorage from '@/utils/lang';

View File

@ -1,7 +1,6 @@
<template>
<el-dialog v-dialogDrag :title="$t('global.chooseRoom')" :visible.sync="dialogShow" width="30%" center>
<el-input v-model="input" :placeholder="$t('global.inputRoomNumber')" />
<el-checkbox v-if="!isShow" v-model="isNewMap">是否新版地图房间</el-checkbox>
<el-dialog v-dialogDrag title="选择仿真" :visible.sync="dialogShow" width="30%" center>
<el-input v-model="input" placeholder="请输入仿真号" />
<span slot="footer" class="dialog-footer">
<el-button @click="dialogShow = false">{{ $t('global.cancel') }}</el-button>
<el-button v-loading="loading" :disabled="!input.length" type="primary" @click="comit">{{ $t('global.confirm') }}</el-button>
@ -10,8 +9,7 @@
</template>
<script>
import { getPermissionJoint } from '@/api/chat';
import { getPermissionJointNew } from '@/api/jointTraining';
import { jointSimulationByPermission } from '@/api/jointSimulation';
export default {
name: 'Dashboard',
@ -19,8 +17,7 @@ export default {
return {
input: '',
dialogShow: false,
loading: false,
isNewMap: false
loading: false
};
},
computed: {
@ -38,11 +35,7 @@ export default {
async comit() {
try {
this.loading = true;
if (this.isNewMap || this.isShow) {
await getPermissionJointNew(`${this.input}`);
} else {
await getPermissionJoint(`${this.input}`);
}
await jointSimulationByPermission(`${this.input}`);
this.dialogShow = false;
} catch (error) {
const errorMessage = this.isShow ? this.$t('tip.failedToAddNewRoom') : this.$t('error.scanningError');

View File

@ -1,10 +1,8 @@
<template>
<div class="avatar-container" style="margin-left:40px;">
<img v-if="isHyd||isJyd" class="logo_hyd" :src="logoImg" @click="goToMain">
<img v-else-if="isTky" style="position: absolute;width: 120px;" :src="logoImg" @click="goToMain">
<img v-else class="logo" :src="logoImg" @click="goToMain">
<div class="titleInner" :style="marginLeft" @click="goToMain">{{ systemTitle }}</div>
<img class="logo" :src="logoImg" :style="{width: navigationLogoWidth}" @click="goToMain">
<div class="titleInner" :style="{marginLeft: navigationMarginLeft}" @click="goToMain">{{ systemTitle }}</div>
</div>
</template>
<script>
@ -16,26 +14,16 @@ export default {
return {
logoImg: '',
systemTitle: '',
isHyd: false,
isJyd: false,
isTky: false,
marginLeft: 'margin-left:60px;'
navigationLogoWidth: '',
navigationMarginLeft: ''
};
},
mounted() {
const project = getSessionStorage('project');
this.systemTitle = loginInfo[project].homeTitle || loginInfo[project].title;
this.logoImg = ProjectIcon[project];
if (project.endsWith('hyd')) {
this.isHyd = true;
this.marginLeft = 'margin-left:140px;';
} else if (project.endsWith('jyd')) {
this.isJyd = true;
this.marginLeft = 'margin-left:140px;';
} else if (project.endsWith('tky')) {
this.isTky = true;
this.marginLeft = 'margin-left:140px;';
}
this.navigationLogoWidth = loginInfo[project].navigationLogoWidth;
this.navigationMarginLeft = loginInfo[project].navigationMarginLeft;
},
methods: {
goToMain() {

View File

@ -50,6 +50,11 @@ function getRouteInfo(to) {
} else {
const whitePage = PermissionParam[current_session] ? PermissionParam[current_session].whitePage : '';
loginPath = whitePage || loginPage;
if (to.query.projectDevice && to.query.ibpDevice) {
loginPath = `${loginPath}?projectDevice=${to.query.projectDevice}&ibpDevice=${to.query.ibpDevice}`;
} else if (to.query.projectDevice) {
loginPath = `${loginPath}?projectDevice=${to.query.projectDevice}`;
}
if (current_session && current_session.startsWith('jsxt') || current_session && current_session.startsWith('refereeJsxt')) {
const raceId = getSessionStorage('raceId'); // 登陆时候保存 竞赛id
loginPath = `${loginPath}?raceId=${raceId}`;

View File

@ -10,79 +10,110 @@ import Link_Jyd from '@/assets/icon/link_jyd.png';
import FaviconTky from '@/assets/icon/favicon_tky.png';
import { LoginParams } from '@/utils/login';
export const loginInfo = { // 页面title & 退出登录跳转路径
// title:页面title; loginPath:退出登录跳转路径; loginParam:登录接口参数project;loginTitle:登录页左上角titlelogoWidth登录页左上角logo宽度
// homeTitle:导航栏title(没有采用title); browserTitle:浏览器窗口titlebottomColumn底部栏描述bottomIcon底部栏Icon;linkIcon:浏览器窗口icon(没有采用ProjectIcon)
export const loginInfo = {
xty: {
title: '西安铁路职业技术学院城市轨道交通实训平台',
loginPath: '/xty/login',
loginParam: 'XTY'
loginParam: 'XTY',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
login: {
title: LangStorage.getLang() == 'en' ? ' Urban Rail Transit Practical Training Platform' : '城市轨道交通实训平台',
loginPath: '/login',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
design: {
title: LangStorage.getLang() == 'en' ? ' Urban Rail Transit Design Platform' : '城市轨道交通设计平台',
loginPath: '/design/login',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
designxty: {
title: '西安铁路职业技术学院城市轨道交通设计平台',
loginPath: '/designxty/login',
loginParam: 'XTY'
loginParam: 'XTY',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
gzb: {
title: '贵州装备制造职业学院城市轨道交通实训平台',
loginPath: '/gzb/login',
loginParam: 'GZB'
loginParam: 'GZB',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
designgzb: {
title: '贵州装备制造职业学院城市轨道交通设计平台',
loginPath: '/designgzb/login',
loginParam: 'GZB'
loginParam: 'GZB',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
hyd: {
title: '城市轨道交通综合行车模拟仿真系统V1.0',
loginPath: '/login',
bottomColumn: '哈尔滨盈达科技有限公司 联系电话:0451-87001273',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '120px',
navigationMarginLeft: '140px'
},
designhyd: {
title: '城市轨道交通设计平台V1.0',
loginPath: '/design/login',
bottomColumn: '哈尔滨盈达科技有限公司 联系电话:0451-87001273',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '120px',
navigationMarginLeft: '140px'
},
xadt: {
title: '城市轨道交通实训平台',
logoWidth: '60px',
loginTitle: '调度一部',
homeTitle: '调度一部',
browserTitle: '西安地铁调度一部城市轨道交通实训平台',
loginPath: '/xadt/login',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
designxadt: {
title: '城市轨道交通设计平台',
logoWidth: '60px',
loginTitle: '调度一部',
homeTitle: '调度一部',
browserTitle: '西安地铁调度一部城市轨道交通设计平台',
loginPath: '/designxadt/login',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
jsxt:{
title: '城市轨道交通竞赛平台',
loginPath: '/jsxt/login',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
refereeJsxt:{
title: '城市轨道交通裁判平台',
loginPath: '/refereeJsxt/login',
loginParam: 'DEFAULT'
loginParam: 'DEFAULT',
navigationLogoWidth: '40px',
navigationMarginLeft: '60px'
},
jyd: {
title: '城市轨道交通实训平台',
loginPath: '/jyd/login',
loginTitle: 'jyd',
logoWidth: '300px',
navigationLogoWidth: '120px',
navigationMarginLeft: '140px',
loginTitle: '空串',
bottomColumn: '',
bottomIcon: Bottom_Jyd,
linkIcon: Link_Jyd,
@ -90,7 +121,10 @@ export const loginInfo = { // 页面title & 退出登录跳转路径
},
designjyd: {
title: '城市轨道交通设计平台',
loginTitle: 'jyd',
loginTitle: '空串',
logoWidth: '300px',
navigationLogoWidth: '120px',
navigationMarginLeft: '140px',
loginPath: '/designjyd/login',
bottomColumn: '',
bottomIcon: Bottom_Jyd,

View File

@ -23,7 +23,7 @@ function handle(state, data) {
case 'Simulation_DeviceStatus': // 仿真-设备状态消息
state.equipmentStatus = msg;
break;
case 'Simulation_User': // 仿真-聊天界面用户进出仿真消息
case 'Simulation_User': // 仿真-进出仿真消息
handleSimulationUserinfo(state, msg); // 用户进出仿真消息
break;
case 'Simulation_Script_Tip': // 仿真-聊天界面用户进出仿真消息
@ -64,7 +64,7 @@ function handle(state, data) {
}
break;
case 'Simulation_Error': // 仿真-异常消息
state.simulationError = msg;
state.simulationError += 1;
break;
case 'Simulation_RunAsPlan_Start': // 仿真-仿真开始按计划行车消息
state.simulationStart = msg;
@ -73,9 +73,8 @@ function handle(state, data) {
state.simulationReset = 'reset';
break;
case 'Simulation_Conversation': // 仿真-用户交互消息(聊天/命令)
{ handleSimulationInfo(state, msg);
state.simuConversitionCount++;
break; }
handleSimulationInfo(state, msg);
break;
case 'Simulation_PlayBack_Conversation': // 回放-用户交互消息
handleSimulationInfo(state, msg);
break;
@ -85,8 +84,8 @@ function handle(state, data) {
case 'JointTraining_User_Permit': // 综合演练室-用户获取权限消息
state.userPermit = msg;
break;
case 'JointTraining_Room_Invite': // 综合演练室-房间邀请消息
state.roomInvite = msg;
case 'Simulation_Invite': // 综合演练-仿真邀请消息
state.simulationInvite = msg;
break;
case 'Big_Screen_Simulation_DeviceStatus': // 大屏仿真状态数据
state.equipmentStatus = msg;
@ -128,6 +127,9 @@ function handle(state, data) {
duration: 0
});
break;
case 'Simulation_Member':
state.memberChangeCount++;
break;
}
}
@ -158,28 +160,20 @@ function handleRecordList(state, data) {
}
// 仿真内部聊天
function handleSimulationInfo(state, data) {
const userId = store.state.user.id;
let isSelf = false;
if (data.member.userId == userId) {
isSelf = true;
switch (data.messageType) {
case 'INVITE':
state.inviteSimulationConversition = data;
break;
case 'CONNECT':
state.acceptConversionInvite = data;
break;
case 'OVER':
state.overConversition = data;
break;
case 'MESSAGE':
state.conversationInfo = data;
break;
}
const myDate = new Date();
const myDate1 = myDate.toLocaleDateString().replace(/\//g, '-');
const chatTime = /\d{2}:\d{2}:\d{2}/.exec(data.chatTime)[0] || data.chatTime;
const params = {
id:data.conversationId,
self: isSelf,
message: data.message,
voice: data.isAudio,
src: data.isAudio ? `/audio/${data.audioPath}` : '',
member:data.member,
memberOnline:data.member.online,
chatTime: data.chatTime,
targetUser:data.targetMember ? data.targetMember : 'All',
all: data.all,
date: +new Date(`${myDate1} ${chatTime}`)
};
state.simulationText = params;
}
// 剧本提示
@ -224,7 +218,7 @@ const socket = {
jointRoomPrepare: false, // 演练房间准备状态
equipmentStatus: [], // 仿真-设备状态消息
trainStationList: [], // 仿真-列车实际到发车站消息
simulationError: '', // 仿真-异常消息
simulationError: 0, // 仿真-异常消息
simulationStart: '', // 仿真-开始消息
simulationOver:0, // 退出仿真推送消息
simulationReset: '', // 仿真-异常消息
@ -233,6 +227,10 @@ const socket = {
acceptInviteChat:{}, // 综合演练仿真-聊天界面用户接受聊天邀请,
quitCoversition:{}, // 综合演练仿真-聊天界面用户退出群聊推送消息,
// coversitionList:{}, // 历史仿真-用户消息列表
inviteSimulationConversition: {}, // 仿真会话邀请消息
acceptConversionInvite:{}, // 仿真会话成员接收邀请
overConversition: {}, // 仿真会话结束
conversationInfo: {}, // 仿真会话消息
message: {}, // 仿真聊天
msgQueue: [], // 命令请求列表
@ -244,7 +242,7 @@ const socket = {
userOutRoom: {}, // 用户退出房间消息
userInSimulation: {}, // 用户进入仿真消息
userBackRoom: {}, // 用户从仿真返回房间消息
roomInvite: {}, // 用户扫码信息
simulationInvite: {}, // 用户扫码信息
permissionOver: {}, // 权限结束
@ -255,7 +253,8 @@ const socket = {
tipOperateCount: 0, // 任务结束提示消息
realDeviceInfo: 0, // 真实设备信息
beLogoutCount: 0, // 被登出
runPlanReloadCount: 0 // 仿真运行图变更
runPlanReloadCount: 0, // 仿真运行图变更
memberChangeCount: 0 // 仿真成员变更
},
getters: {
},
@ -276,10 +275,6 @@ const socket = {
state.trainStationList = trainStationList;
},
setSimulationError: (state, simulationError) => {
state.simulationError = simulationError;
},
setSimulationStart: (state, simulationStart) => {
state.simulationStart = simulationStart;
},
@ -288,10 +283,6 @@ const socket = {
state.simulationReset = simulationReset;
},
setSimulationTextList: (state, simulationText) => {
state.simulationText = simulationText;
},
setPayOrder: (state, payOrder) => {
state.payOrder = payOrder;
},
@ -305,8 +296,8 @@ const socket = {
handlePushMsgQueue(state, msg);
},
setRoomInvite: (state, roomInvite) => {
state.roomInvite = roomInvite;
setSimulationInvite: (state, simulationInvite) => {
state.simulationInvite = simulationInvite;
},
setRoomSubscribe:(state, roomIsSubscribe)=>{
state.roomIsSubscribe = roomIsSubscribe;
@ -340,10 +331,6 @@ const socket = {
commit('setTrainStationList', []);
},
setSimulationError: ({ commit }) => {
commit('setSimulationError', '');
},
setSimulationStart: ({ commit }) => {
commit('setSimulationStart', '');
},
@ -352,12 +339,8 @@ const socket = {
commit('setSimulationReset', '');
},
setSimulationTextList: ({ commit }) => {
commit('setSimulationTextList', {});
},
setRoomInvite: ({ commit }) => {
commit('setRoomInvite', {});
setSimulationInvite: ({ commit }) => {
commit('setSimulationInvite', {});
},
setMessage: ({ state }, data) => {

View File

@ -4,6 +4,7 @@ import OperateHandler from '@/scripts/plugin/OperateHandler';
import deviceType from '../../jmap/constant/deviceType';
import LangStorage from '@/utils/lang';
import Handler from '@/scripts/cmdPlugin/Handler';
import { deepAssign } from '@/utils/index';
/**
* 实训状态数据
@ -34,7 +35,10 @@ const training = {
prdType: '', // 产品类型
roles: '', // 角色权限类型
group: '', // 设置全局 group
centerStationCode:'' // 当前居中的集中站code
centerStationCode:'', // 当前居中的集中站code
memberList: [], // 综合仿真成员列表
memberData: {}, // 综合仿真成员列表
simulationUserList: [] // 综合仿真用户列表
},
getters: {
@ -77,6 +81,12 @@ const training = {
roles: (state) => {
return state.roles;
},
memberList: (state) => {
return state.memberList;
},
simulationUserList: (state) => {
return state.simulationUserList;
},
// 视图中的列车列表
viewTrainList: (state) => () =>{
const trainList = [];
@ -107,6 +117,8 @@ const training = {
},
over: (state) => {
state.started = false;
state.memberList = [];
state.simulationUserList = [];
state.switchcount += 1;
},
updateMapState: (state, deviceStatus) => {
@ -204,6 +216,52 @@ const training = {
},
setCenterStationCode:(state, centerStationCode) => {
state.centerStationCode = centerStationCode;
},
setMemberList: (state, {memberList, userId}) => {
state.memberList = memberList;
state.memberData = {};
if (memberList && memberList.length) {
memberList.forEach(item => {
state.memberData[item.id] = deepAssign({userId: ''}, item);
state.memberData[item.id].disabled = userId == item.userId;
});
}
},
setSimulationUserList: (state, simulationUserList) => {
state.simulationUserList = simulationUserList;
},
updateMemberAndUser: (state, {simulationUserList, userId}) => {
simulationUserList.forEach(item => {
let memberIndex = -1;
let memberId = '';
state.simulationUserList.forEach((user, index) =>{
if (user.userId === item.userId) {
memberId = user.memberId;
user.online = item.online;
user.memberId = item.memberId;
user.role = item.role;
memberIndex = index;
}
});
try {
if (state.memberData && memberId !== item.memberId && memberId && state.memberData[memberId]) {
state.memberData[memberId].userId = '';
state.memberData[memberId].disabled = false;
}
if (state.memberData && memberId !== item.memberId && item.memberId && state.memberData[item.memberId]) {
state.memberData[item.memberId].userId = item.userId;
state.memberData[item.memberId].disabled = item.userId == userId;
}
if (item.messageType === 'ENTER' && memberIndex < 0) {
delete item.messageType;
state.simulationUserList.push(item);
} else if (item.messageType === 'KICK_OUT' && memberIndex > -1) {
state.simulationUserList.splice(memberIndex, 1);
}
} catch (e) {
console.error(e);
}
});
}
},
@ -599,6 +657,18 @@ const training = {
/** 设置当前居中的集中站code */
setCenterStationCode:({ commit }, centerStationCode) => {
commit('setCenterStationCode', centerStationCode);
},
/** 设置综合演练仿真成员列表 */
setMemberList: ({ commit }, data) => {
commit('setMemberList', data);
},
/** 设置综合演练仿真用户列表 */
setSimulationUserList: ({ commit }, simulationUserList) => {
commit('setSimulationUserList', simulationUserList);
},
/** 更新综合演练仿真成员和用户列表 */
updateMemberAndUser: ({ commit }, data) => {
commit('updateMemberAndUser', data);
}
}
};

View File

@ -17,7 +17,8 @@ const user = {
admin: false,
wxId: '',
wxUnionId: '',
account: ''
account: '',
projectDevice: ''
},
mutations: {
@ -30,6 +31,9 @@ const user = {
SET_NICKNAME: (state, nickname) => {
state.nickname = nickname;
},
SET_PROJECTDEVICE: (state, projectDevice) => {
state.projectDevice = projectDevice;
},
SET_ROLES: (state, roles) => {
state.roles = roles;
},
@ -106,7 +110,9 @@ const user = {
});
});
},
SetProjecteDevice({ commit }, deviceVo) {
commit('SET_PROJECTDEVICE', deviceVo);
},
// 获取用户信息
GetInfo({ commit }, token) {
return new Promise((resolve, reject) => {

View File

@ -2,9 +2,9 @@ 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 = 'https://test.joylink.club/jlcloud';
// BASE_API = 'http://192.168.3.5:9000'; // 袁琪
// BASE_API = 'http://192.168.3.6:9000'; // 旭强
BASE_API = 'http://192.168.3.6:9000'; // 旭强
// BASE_API = 'http://192.168.3.41:9000'; // 张赛
// BASE_API = 'http://192.168.3.82:9000'; // 杜康
// BASE_API = 'http://b29z135112.zicp.vip';

View File

@ -22,8 +22,8 @@
:style="{height: height+'px'}"
>
<div slot-scope="{ node, data }" class="list-elem custom-tree-node">
<span v-if="data.state=='01'">{{ '['+data.mapName+']'+($t('global.trainingNotStart').replace('{name}', data.creator.nickName)) }}</span>
<span v-else>{{ '['+data.mapName+']'+($t('global.trainingHasStart').replace('{name}', data.creator.nickName)) }}</span>
<span v-if="data.state=='01'">{{ '['+data.map.name+']'+($t('global.trainingNotStart').replace('{name}', data.creator.nickname)) }}</span>
<span v-else>{{ '['+data.map.name+']'+($t('global.trainingHasStart').replace('{name}', data.creator.nickname)) }}</span>
<el-button
type="text"
size="mini"
@ -43,8 +43,7 @@
</template>
<script>
import { getjointTrainListNew, putJointTrainingSimulationEntranceNew, getjointTrainingNew } from '@/api/jointTraining';
import { getPublishMapInfo } from '@/api/jmap/map';
import { getSimulationListCantainUser } from '@/api/jointSimulation';
import { launchFullscreen } from '@/utils/screen';
import { getToken } from '@/utils/auth';
import { creatSubscribe, clearSubscribe, roomTopic} from '@/utils/stomp';
@ -100,8 +99,11 @@ export default {
this.pageLoading = true;
this.dialogShow = true;
this.loading = false;
const resp = await getjointTrainListNew();
this.trainingList = resp.data || [];
this.trainingList = [];
const resp = await getSimulationListCantainUser();
if (resp.data) {
this.trainingList = resp.data;
}
} catch (e) {
console.error(e);
} finally {
@ -113,18 +115,9 @@ export default {
},
async handleJoinRoom(data) {
try {
const rest = await getPublishMapInfo(data.mapId);
await getjointTrainingNew(data.group);
if (data.state == '02') {
this.subscribe(data.group);
launchFullscreen();
const query = { lineCode: rest.data.lineCode, mapId: data.mapId, group: data.group, drawWay: true };
await putJointTrainingSimulationEntranceNew(data.group);
this.$router.push({ path: `/jointTrainingNew`, query: query });
} else if (data.state == '01') {
const query = { group: data.group, drawWay: true };
this.$router.push({ path: `/trainroom`, query: query });
}
const query = { lineCode: data.map.lineCode, mapId: data.map.id, group: data.group};
this.$router.push({path:'/jointTrainingNew', query:query});
} catch (e) {
console.error(e);
} finally {
@ -146,7 +139,7 @@ export default {
}
.el-tree {
overflow: hidden !important;
overflow: auto !important;
.list-elem {
height: 30px;
line-height: 30px;

View File

@ -1,190 +0,0 @@
<template>
<el-dialog
v-dialogDrag
v-dialogLoading="pageLoading"
:title="title"
:visible.sync="show"
width="600px"
:before-close="doClose"
:z-index="2000"
:modal="false"
:close-on-click-modal="false"
>
<el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: height+'px'}">
<el-tree
ref="tree"
node-key="group"
class="filter-tree"
default-expand-all
:data="trainingList"
:props="defaultProps"
:filter-node-method="filterNode"
:style="{height: height+'px'}"
>
<div slot-scope="{ node, data }" class="list-elem custom-tree-node">
<span v-if="data.state=='01'">{{ '['+data.mapName+']'+($t('global.trainingNotStart').replace('{name}', data.creator.nickName)) }}</span>
<span v-else>{{ '['+data.mapName+']'+($t('global.trainingHasStart').replace('{name}', data.creator.nickName)) }}</span>
<el-button
type="text"
size="mini"
@click="handleJoinRoom(data)"
>进入</el-button>
</div>
</el-tree>
</el-scrollbar>
<span
slot="footer"
class="dialog-footer"
>
<el-button v-loading="loading" type="primary" @click="handleJoin">{{ $t('global.joinNewRoom') }}</el-button>
<el-button @click="dialogShow = false">{{ $t('global.cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { getjointTrainList, getjointTraining, putJointTrainingSimulationEntrance } from '@/api/chat';
import { getjointTrainListNew, putJointTrainingSimulationEntranceNew, getjointTrainingNew } from '@/api/jointTraining';
import { getPublishMapInfo } from '@/api/jmap/map';
import { launchFullscreen } from '@/utils/screen';
import { getSessionStorage } from '@/utils/auth';
import { ProjectCode } from '@/scripts/ProjectConfig';
import { getToken } from '@/utils/auth';
import { creatSubscribe, clearSubscribe, roomTopic} from '@/utils/stomp';
export default {
name: 'DeomonList',
data() {
return {
dialogShow: false,
height: 120,
trainingList: [],
defaultProps: {
label: 'roomName'
},
group: '',
loading: false,
pageLoading: false
};
},
computed: {
show() {
return this.dialogShow;
},
title() {
return this.$t('global.synthesisTrainingTitle');
},
isWatch() {
return true;
},
isjoin() {
return true;
}
},
methods: {
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
async subscribe(group) {
if (!this.$store.state.socket.roomIsSubscribe) {
this.clearSubscribe(group);
const header = { group: group || '', 'X-Token': getToken() };
creatSubscribe(`${roomTopic}\/${group}`, header);
await this.$store.dispatch('socket/setRoomSubscribe', true);
}
},
async clearSubscribe(group) {
clearSubscribe(`${roomTopic}\/${group}`);
await this.$store.dispatch('socket/setRoomSubscribe', false);
},
async doShow() {
try {
this.pageLoading = true;
this.dialogShow = true;
this.loading = false;
const project = getSessionStorage('project');
const param = {};
if (ProjectCode[project]) {
param.projectCode = ProjectCode[project];
}
const resp = await getjointTrainListNew(param);
const rest = await getjointTrainList(param);
const newMapData = resp.data || [];
const oldMapData = rest.data || [];
this.trainingList = [...newMapData, ...oldMapData];
} catch (e) {
console.error(e);
} finally {
this.pageLoading = false;
}
},
async doClose() {
this.dialogShow = false;
},
async handleJoinRoom(data) {
try {
const rest = await getPublishMapInfo(data.mapId);
let path = '';
if (rest.data.drawWay) {
await getjointTrainingNew(data.group);
path = '/jointTrainingNew';
} else {
await getjointTraining(data.group);
path = '/jointTraining';
}
if (data.state == '02') {
this.subscribe(data.group);
launchFullscreen();
const query = { lineCode: rest.data.lineCode, mapId: data.mapId, group: data.group, drawWay: rest.data.drawWay };
if (rest.data.drawWay) {
await putJointTrainingSimulationEntranceNew(data.group);
} else {
await putJointTrainingSimulationEntrance(data.group);
}
this.$router.push({ path: path, query: query });
} else if (data.state == '01') {
const query = { group: data.group, drawWay: rest.data.drawWay };
this.$router.push({ path: `/trainroom`, query: query });
}
} catch (e) {
console.error(e);
} finally {
this.loading = false;
}
},
handleJoin() {
this.$emit('enterQcode');
this.dialogShow = false;
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
/deep/ {
.el-dialog__body {
padding: 0px 30px !important;
}
.el-tree {
overflow: auto !important;
.list-elem {
height: 30px;
line-height: 30px;
}
}
.el-tree-node.is-current>.el-tree-node__content {
background-color: #e4e3e3 !important;
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>

View File

@ -18,12 +18,7 @@
</template>
<script>
import { getjointTraining, putJointTrainingSimulationEntrance } from '@/api/chat';
import { getjointTrainingNew, putJointTrainingSimulationEntranceNew} from '@/api/jointTraining';
import { getPublishMapInfo } from '@/api/jmap/map';
import { launchFullscreen } from '@/utils/screen';
import { getToken } from '@/utils/auth';
import { creatSubscribe, clearSubscribe, roomTopic} from '@/utils/stomp';
export default {
name: 'DeomonList',
@ -32,8 +27,8 @@ export default {
dialogShow: false,
group: '',
roomName: '',
state: '',
mapId: '',
lineCode: '',
loading: false
};
},
@ -49,53 +44,22 @@ export default {
},
methods: {
doShow(data) {
this.roomName = data.creator.nickName;
this.roomName = data.creator.nickname;
this.group = data.group;
this.state = data.state;
this.mapId = data.mapId;
this.mapId = data.map.id;
this.lineCode = data.map.lineCode;
this.dialogShow = true;
this.loading = false;
},
doClose() {
this.dialogShow = false;
},
async subscribe() {
if (!this.$store.state.socket.roomIsSubscribe) {
this.clearSubscribe();
const header = { group: this.group || '', 'X-Token': getToken() };
creatSubscribe(`${roomTopic}\/${this.group}`, header);
await this.$store.dispatch('socket/setRoomSubscribe', true);
}
},
async clearSubscribe() {
clearSubscribe(`${roomTopic}\/${this.group}`);
await this.$store.dispatch('socket/setRoomSubscribe', false);
},
async handleJoin() {
try {
this.loading = true;
const rest = await getPublishMapInfo(this.mapId);
const drawWay = rest.data.drawWay;
if (drawWay) {
await getjointTrainingNew(this.group);
} else {
await getjointTraining(this.group);
}
if (this.state == '02') {
this.subscribe();
launchFullscreen();
const query = { lineCode: rest.data.lineCode, mapId: this.mapId, group: this.group, drawWay: drawWay };
if (drawWay) {
await putJointTrainingSimulationEntranceNew(this.group);
const query = { lineCode: this.lineCode, mapId: this.mapId, group: this.group};
this.$router.push({path: `/jointTrainingNew`, query: query});
} else {
await putJointTrainingSimulationEntrance(this.group);
this.$router.push({ path: `/jointTraining`, query: query });
}
} else if (this.state == '01') {
const query = { group: this.group, drawWay: drawWay };
this.$router.push({ path: `/trainroom`, query: query });
}
this.dialogShow = false;
} catch (e) {
this.$messageBox(this.$t('tip.enterTrainingRoomFailed'));

View File

@ -17,8 +17,6 @@
<el-button v-if="!isLocal" type="success" :disabled="disabled" @click="buy">{{ $t('global.buy') }}</el-button>
<el-button v-if="hasPermssion && !isComprehensive && !isLocal" type="primary" :disabled="disabled" @click="distribute">{{ $t('global.distributePermission') }}</el-button>
<el-button v-show="isStartDemon" :disabled="disabled" type="primary" @click="start">{{ $t('demonstration.startSimulation') }}</el-button>
<el-button v-show="isCreateRoom" :disabled="disabled" type="primary" @click="start">{{ $t('demonstration.createRoom') }}</el-button>
<el-button v-show="isInRoom" :disabled="disabled" type="primary" @click="joinRoom">{{ $t('demonstration.enterRoom') }}</el-button>
</div>
</div>
</template>
@ -28,8 +26,7 @@ import { getPublishMapInfo } from '@/api/jmap/map';
import { getGoodsTryUse } from '@/api/management/goods';
import { PermissionType, UrlConfig } from '@/scripts/ConstDic';
import { launchFullscreen } from '@/utils/screen';
import { postCreateRoom, getjointTraining } from '@/api/chat';
import { postCreateRoomNew, getjointTrainingNew, checkRoomExistNew } from '@/api/jointTraining';
import { } from '@/scripts/ConstDic';
import { simulationNotify, schedulingNotify, createSimulationNew } from '@/api/simulation';
import LimitList from '@/views/components/limits/index';
import { getSubSystemDetail } from '@/api/trainingPlatform';
@ -60,8 +57,6 @@ export default {
prdType: '',
pmsList: []
},
jointShow: false,
jointGroup: '',
lineCode:'',
drawWay: false //
};
@ -87,13 +82,7 @@ export default {
return this.courseModel.prdType === '03';
},
isStartDemon() {
return this.courseModel.prdType !== '03' && (this.hasPermssion || this.tryTime > 0);
},
isCreateRoom() {
return this.courseModel.prdType === '03' && this.hasPermssion && !this.jointShow;
},
isInRoom() {
return this.courseModel.prdType === '03' && this.hasPermssion && this.jointShow;
return this.hasPermssion || this.tryTime > 0;
},
mapId() {
return this.$route.query.mapId;
@ -103,7 +92,7 @@ export default {
}
},
watch: {
'$route': function (val) {
'$route': function (val, oldval) {
this.loadInitData();
}
},
@ -142,9 +131,6 @@ export default {
PermissionType: PermissionType.SIMULATION
};
this.currentPrdType = resp.data.prdType;
if (resp.data.prdType === '03') {
this.getJointTrainingList();
}
if (!this.courseModel.pmsList) {
this.tryUser = 1;
const paras = {
@ -167,67 +153,22 @@ export default {
}
} catch (error) {
// this.loading = false;
// this.$message.error(this.$t('error.refreshFailed'));
this.$message.error(this.$t('error.refreshFailed'));
}
},
refresh() {
this.loadInitData();
},
async getJointTrainingList() {
try {
if (this.mapId) {
const res = await checkRoomExistNew({mapId: this.mapId});
this.jointGroup = res.data;
this.jointShow = false;
if (res.data) {
this.jointShow = true;
}
}
} catch (error) {
console.error(error, '获取是否拥有综合演练房间');
}
},
async joinRoom() {
this.disabled = true;
if (this.drawWay) {
await getjointTrainingNew(this.jointGroup);
} else {
await getjointTraining(this.jointGroup);
}
this.$store.dispatch('socket/setInRoom', true);
const query = { lineCode: this.courseModel.lineCode, group: this.jointGroup, drawWay: this.drawWay};
this.$router.push({ path: `/trainroom`, query: query });
},
async createRoom() {
try {
this.disabled = true;
const param = {
mapId: Number(this.mapId),
prdType: this.courseModel.prdType
};
let res = '';
if (this.drawWay) {
res = await postCreateRoomNew(param);
} else {
res = await postCreateRoom(param);
}
if (res && res.code == 200) {
const query = { lineCode: this.courseModel.lineCode, group: res.data, drawWay: this.drawWay };
this.$router.push({ path: `/trainroom`, query: query });
}
} catch (error) {
async enterIntegratedSimulation() {
const data = { mapId: this.courseModel.mapId, prdType: this.currentPrdType };
createSimulationNew(data).then(resp => {
const query = { lineCode: this.courseModel.lineCode, group: resp.data, mapId: this.courseModel.mapId, drawWay: true };
this.$router.push({ path: `/jointTrainingNew`, query: query });
launchFullscreen();
}).catch(error => {
this.$messageBox(this.$t('error.createSimulationFailed') + error.message);
this.disabled = false;
if (error.code == 20001) {
this.$confirm(this.$t('tip.createRoomFailedHint'), this.$t('global.tips'), {
confirmButtonText: this.$t('global.confirm'),
cancelButtonText: this.$t('global.cancel'),
type: 'warning'
}).then(() => {}).catch(() => {});
}
if (error.code == 500009) {
this.$messageBox(error.message);
}
}
});
},
async enterISCS() {
try {
@ -245,7 +186,6 @@ export default {
}
} catch (error) {
this.disabled = false;
console.log(error);
}
},
async enterScreen() {
@ -262,7 +202,7 @@ export default {
if (this.courseModel.prdType == '05') {
this.jumpScheduling();
} else if (this.courseModel.prdType == '03') {
this.createRoom();
this.enterIntegratedSimulation();
} else if (this.courseModel.prdType == '06') {
this.enterISCS();
} else if (this.courseModel.prdType == '07') {

View File

@ -9,11 +9,8 @@
import Vue from 'vue';
import IbpPan from '@/ibp/ibpPan';
import { parser } from '@/ibp/utils/parser';
// import ibpData from '@/ibp/constant/ibpData';
import { mapGetters } from 'vuex';
import { exitFullscreen } from '@/utils/screen';
import { putJointTrainingSimulationUser } from '@/api/chat';
import { putJointTrainingSimulationUserNew} from '@/api/jointTraining';
import { handlerIbpEvent } from '@/api/simulation';
import { IbpOperation } from '@/scripts/ConstDic';
import { getIbpInfoByStation } from '@/api/ibp';
@ -124,8 +121,6 @@ export default {
if (!deviceCode) {
return;
}
// console.log(deviceCode);
// const ibpDatas = ibpData[deviceCode];
try {
const res = await getIbpInfoByStation(this.$route.query.mapId, deviceCode);
if (res.data.data) {
@ -241,16 +236,13 @@ export default {
back() {
this.group = this.$route.query.group;
this.$store.dispatch('training/over').then(() => {
if (this.drawWay === 'true') {
putJointTrainingSimulationUserNew(this.group).then(() => {
this.$router.replace({ path: `/trainroom`, query: { group: this.group, lineCode:this.$route.query.lineCode, drawWay: this.drawWay } });
exitFullscreen();
if (this.$route.query.projectDevice) {
this.$store.dispatch('LogOut').then(() => {
location.reload();
});
} else {
putJointTrainingSimulationUser(this.group).then(() => {
this.$router.replace({ path: `/trainroom`, query: { group: this.group, lineCode:this.$route.query.lineCode } });
history.go(-1);
exitFullscreen();
});
}
});
},

View File

@ -1,15 +1,23 @@
<template>
<div class="login-container" :style="{'background-image': 'url('+bgImg+')'}">
<div class="text-box">
<div
v-loading="ibpDevice && !loadingCode"
class="login-container"
:style="{'background-image': 'url('+bgImg+')'}"
element-loading-spinner="el-icon-loading"
element-loading-text="检测主工作站登录中"
element-loading-background="rgba(0, 0, 0, 0)"
>
<el-button v-if="ibpDevice && loadingCode" type="text" style="font-size: 24px;font-weight: bold;" @click="loginRefresh">主工作站未登录,点击重新检测</el-button>
<div v-if="!ibpDevice" class="text-box">
<img class="logo" :src="logoImg" style="width: 140px">
<span>{{ title }}</span>
</div>
<div class="language_box">
<div v-if="!ibpDevice" class="language_box">
<el-tooltip effect="dark" :content="this.$t('login.clickSwitchLanguage')" placement="bottom-end">
<el-button class="language_btn" type="text" @click="handleLanguage">{{ language }}</el-button>
</el-tooltip>
</div>
<div class="content-box">
<div v-if="!ibpDevice" class="content-box">
<el-form ref="loginForm" class="login-form" :model="loginForm" :rules="loginRules" label-position="left">
<el-form-item prop="username" class="item_form_box">
<span class="svg-container svg-container_login">
@ -65,14 +73,18 @@
<script>
import QCode from '@/assets/erCode.jpg';
import { setSessionStorage, removeSessionStorage } from '@/utils/auth';
import { setSessionStorage, removeSessionStorage, getLoginInfo } from '@/utils/auth';
import Cookies from 'js-cookie';
import bgIbpImg from '@/assets/bg_ibp.png';
import md5 from 'js-md5';
import { UrlConfig } from '@/scripts/ConstDic';
import { loginInfo, ProjectIcon } from '@/scripts/ProjectConfig';
import { loginInfo, ProjectIcon, LoginParams } from '@/scripts/ProjectConfig';
import { removeToken } from '@/utils/auth';
import LangStorage from '@/utils/lang';
import logoImgHyd from '@/assets/project_icon/logo_hyd.png';
import { getSimulationInfoNew } from '@/api/simulation';
import { getLoginWmurl, checkLoginStatus, getLoginInfo } from '@/api/login';
import { getToken } from '@/utils/auth';
export default {
name: 'Login',
data() {
@ -91,7 +103,6 @@ export default {
}
};
return {
bgImg: '',
QCode: QCode,
isAutoLogin: false,
loginForm: {
@ -127,6 +138,12 @@ export default {
computed: {
project() {
return this.$route.path.split('/')[1];
},
bgImg() {
return this.$route.query.ibpDevice ? bgIbpImg : '';
},
ibpDevice() {
return this.$route.query.ibpDevice;
}
},
created() {
@ -141,6 +158,8 @@ export default {
}).catch(error => {
if (error.code === '30001') {
this.tipsMsg = this.$t('login.accountOrPasswordIsIncorrect');
} else if (error.code == '10001') {
this.tipsMsg = '教研机尚未登录,请稍后重试!';
} else {
this.tipsMsg = error.message;
}
@ -155,6 +174,9 @@ export default {
} else {
this.title = loginInfo['hyd'].title;
}
if (this.ibpDevice) {
this.loginRefresh();
}
document.title = this.title;
},
methods: {
@ -168,7 +190,6 @@ export default {
this.path = UrlConfig.design.prefix;
sessionVal = 'designhyd';
}
const nowLang = LangStorage.getLang('zh');
if (nowLang === 'zh') {
this.lang = 'en';
@ -185,6 +206,50 @@ export default {
timer = null;
}
},
loginRefresh() {
this.loadingCode = true;
const params = LoginParams[this.loginClient];
params.project = loginInfo[this.project].loginParam;
if (this.$route.query.projectDevice) {
params.deviceCode = this.$route.query.projectDevice;
}
getLoginWmurl(params).then(response => {
this.sessionId = response.data.sessionId;
this.loginUrl = response.data.url;
this.loadingCode = false;
this.checkLoginStatus();
}).catch(() => {
this.loadingCode = false;
this.$messageBox(this.$t('login.getLoginQrCode'));
});
},
checkLoginStatus() {
const self = this;
//
if (this && this._isDestroyed) {
return;
}
//
//
this.clearTimer(this.checkLogin);
this.checkLogin = setTimeout(() => {
checkLoginStatus(self.sessionId).then(response => {
//
self.$store.dispatch('QrLoginSetting', { key: 'SET_TOKEN', value: response.data.token, type: this.modelType }).then(() => {
//
self.clearTimer(self.checkLogin);
this.handleLoginSucessRoute();
});
}).catch(error => {
if (error.data && error.data.status === 'EXPIRE') {
this.loadingCode = true;
this.loginUrl = '';
} else {
self.checkLoginStatus();
}
});
}, 3000);
},
showPwd() {
if (this.pwdType === 'password') {
this.pwdDisplay = false;
@ -207,19 +272,21 @@ export default {
const model = Object.assign({}, this.loginForm);
model.password = md5(model.password);
model.project = loginInfo[this.project].loginParam;
model.deviceCode = this.$route.query.projectDevice;
model.type = this.modelType;
this.loading = true;
if (this.isAutoLogin) {
Cookies.set(this.cookiesName, model.username, { expires: 2});
Cookies.set(this.cookiesToken, model.password, { expires: 2});
}
console.log(model, '111111111111');
this.$store.dispatch('Login', model).then(() => {
this.$store.dispatch('SetAccount', model.username);
this.handleLoginSucessRoute();
}).catch(error => {
if (error.code === '30001') {
this.tipsMsg = this.$t('login.accountOrPasswordIsIncorrect');
} else if (error.code == '10001') {
this.tipsMsg = '教研机尚未登录,请稍后重试!';
} else {
this.tipsMsg = error.message;
}
@ -237,7 +304,18 @@ export default {
this.loading = false;
this.tipsMsg = '';
removeSessionStorage('againEnter');
console.log(this.path);
if (this.$route.query.projectDevice) {
getLoginInfo(getToken()).then(res => {
getSimulationInfoNew(res.data.group).then(resp => {
const query = { group: res.data.group, drawWay: true, mapId: resp.data.map.id, lineCode:resp.data.map.lineCode, projectDevice: this.$route.query.projectDevice };
if (this.$route.query.ibpDevice) {
query.ibpDevice = true;
}
this.$router.push({ path: `/jointTrainingNew`, query: query });
});
});
}
this.$router.push({ path: this.path });
},
handleLanguage() {

View File

@ -9,8 +9,8 @@
>
<el-button v-if="ibpDevice && loadingCode" type="text" style="font-size: 24px;font-weight: bold;" @click="loginRefresh">主工作站未登录,点击重新检测</el-button>
<div v-if="loginTitle && !ibpDevice" class="left-logo-box">
<img class="logo" :src="logoImg" :style="{width: loginTitle==='jyd'?'300px':'60px'}">
<span>{{ loginTitle==='jyd'?'':loginTitle }}</span>
<img class="logo" :src="logoImg" :style="{width: logoWidth}">
<span>{{ loginTitle==='空串'?'':loginTitle }}</span>
</div>
<div v-if="isProject && !ibpDevice" class="text-box">
<img v-if="!loginTitle" class="logo" :src="logoImg" style="width: 80px">
@ -37,7 +37,7 @@
<div class="login-tip">
<span class="sub-title">{{ $t('login.scanCodeLogin') }}</span>
</div>
<div v-if="project !== 'hyd'" class="tip-info">
<div class="tip-info">
<fieldset>
<legend>{{ $t('login.recommendedConfiguration') }}</legend>
<span>{{ $t('login.browser') }}
@ -110,16 +110,17 @@ import { setSessionStorage, removeSessionStorage } from '@/utils/auth';
import Cookies from 'js-cookie';
import md5 from 'js-md5';
import QrcodeVue from 'qrcode.vue';
import { getLoginWmurl, checkLoginStatus } from '@/api/login';
import { getLoginWmurl, checkLoginStatus, getLoginInfo } from '@/api/login';
import { LoginParams } from '@/utils/login';
import bgImg from '@/assets/bg1.jpg';
import bgIbpImg from '@/assets/bg_ibp.png';
import { UrlConfig } from '@/scripts/ConstDic';
import { loginInfo, ProjectIcon, GenerateRouteProjectList, VersionBaseNoShow, MainBodyNoShow} from '@/scripts/ProjectConfig';
import { removeToken } from '@/utils/auth';
import { removeToken, getToken } from '@/utils/auth';
import LangStorage from '@/utils/lang';
import FloatPart from './floatPart';
import { getIsSignUp } from '@/api/competition';
import { getSimulationInfoNew } from '@/api/simulation';
export default {
name: 'Login',
@ -187,6 +188,9 @@ export default {
title() {
return loginInfo[this.$route.path.split('/')[1]].title;
},
logoWidth() {
return loginInfo[this.$route.path.split('/')[1]].logoWidth;
},
isProject() {
const projectName = this.$route.path.split('/')[1];
return GenerateRouteProjectList.includes(projectName);
@ -205,9 +209,6 @@ export default {
created() {
document.querySelector("link[rel*='icon']").href = loginInfo[this.project].linkIcon || ProjectIcon[this.project];
this.computedAttribute();
if (this.$route.query.projectDevice) {
}
if (Cookies.get(this.cookiesName) && Cookies.get(this.cookiesToken)) {
const model = {'username': Cookies.get(this.cookiesName), 'password': Cookies.get(this.cookiesToken), 'project':loginInfo[this.project].loginParam};
model.type = this.modelType;
@ -217,6 +218,8 @@ export default {
}).catch(error => {
if (error.code === '30001') {
this.tipsMsg = this.$t('login.accountOrPasswordIsIncorrect');
} else if (error.code == '10001') {
this.tipsMsg = '教研机尚未登录,请稍后重试!';
} else {
this.tipsMsg = error.message;
}
@ -224,9 +227,6 @@ export default {
setTimeout(() => { this.tipsMsg = ''; }, 5000);
});
}
if (this.project === 'hyd') {
this.bgImg = '';
}
},
mounted() {
document.title = loginInfo[this.project].browserTitle || loginInfo[this.project].title;
@ -288,7 +288,6 @@ export default {
if (this && this._isDestroyed) {
return;
}
//
//
this.clearTimer(this.checkLogin);
@ -344,6 +343,8 @@ export default {
}).catch(error => {
if (error.code === '30001') {
this.tipsMsg = this.$t('login.accountOrPasswordIsIncorrect');
} else if (error.code == '10001') {
this.tipsMsg = '教研机尚未登录,请稍后重试!';
} else {
this.tipsMsg = error.message;
}
@ -378,8 +379,15 @@ export default {
this.$router.push({ path: this.path, query:{ raceId:this.$route.query.raceId } });
}
} else if (this.$route.query.projectDevice) {
const query = { group: '', drawWay: true };
this.$router.push({ path: `/trainroom`, query: query });
getLoginInfo(getToken()).then(res => {
getSimulationInfoNew(res.data.group).then(resp => {
const query = { group: res.data.group, drawWay: true, mapId: resp.data.map.id, lineCode:resp.data.map.lineCode, projectDevice: this.$route.query.projectDevice };
if (this.$route.query.ibpDevice) {
query.ibpDevice = true;
}
this.$router.push({ path: `/jointTrainingNew`, query: query });
});
});
} else if (!this.$route.path.includes('jsxt/login') && !this.$route.path.includes('refereeJsxt/login')) {
this.$router.push({ path: this.path });
} else {

View File

@ -81,7 +81,6 @@ export default {
async simulationError() {
await this.$store.dispatch('map/clearJlmapTrainView');
await this.$store.dispatch('map/setTrainWindowShow', false);
await this.$store.dispatch('socket/setSimulationError');
await this.$store.dispatch('training/setMapDefaultState');
this.clearSubscribe();
this.$confirm(this.$t('tip.getMapStateDataException'), this.$t('tip.hint'), {

View File

@ -13,19 +13,22 @@
:group="group"
:data-error="dataError"
:user-role="userRole"
:is-admin="isAdmin"
:device-code="deviceCode"
:countdown-time="countdownTime"
:admin-mode="adminMode"
@getUserRole="getUserRole"
@hidepanel="hidepanel"
@showIbp="showIbp"
@startCounting="startCounting"
@hidejl3dcctv="hidejl3dcctv"
@handlerMemberManage="handlerMemberManage"
/>
<menu-demon-schema
ref="menuSchema"
:group="group"
:offset="offset"
:user-role="userRole"
:is-admin="isAdmin"
:show-station="showStation"
:station-list="stationList"
:show-select-station="showSelectStation"
@ -34,6 +37,7 @@
@runPlanViewShow="runPlanViewShow"
@faultChooseShow="faultChooseShow"
@switchStationMode="switchStationMode"
@changeAdminMode="changeAdminMode"
/>
<join-fault-choose ref="faultChoose" :group="group" :offset="offset" />
<join-run-plan-Load ref="runPlanLoad" :group="group" />
@ -41,6 +45,8 @@
<menu-system-time ref="menuSystemTime" :offset="offset" :group="group" :right="right" />
<menu-train-list v-if="prdType=='02'" @setCenter="setCenter" />
<js-question v-if="project==='jsxt'" :offset="offset" :question-list="questionList" />
<members-manage ref="membersManage" :is-admin="isAdmin" @addSimulationMember="addSimulationMember" />
<add-member ref="addMember" />
</div>
</div>
@ -61,18 +67,19 @@ import { mapGetters } from 'vuex';
import { OperateMode, TrainingMode } from '@/scripts/ConstDic';
import { checkLoginLine } from '@/api/login';
import { loadNewMapDataByGroup } from '@/utils/loaddata';
import { getUserRolesNew, deljointTrainRoomNew} from '@/api/jointTraining';
import { clearSimulation, getSimulationInfoNew } from '@/api/simulation';
import { clearSimulation, getSimulationInfoNew, getSimulationUserInfo, getSimulationMemberList, getAllSimulationUser } from '@/api/simulation';
import {getRaceUserById, getTestPaperDatail} from '@/api/competition';
import { getSessionStorage } from '@/utils/auth';
import { getSessionStorage, getToken } from '@/utils/auth';
import Jl3dDrive from '@/views/jlmap3d/drive/jl3ddrive';
import Jl3dMaintainer from '@/views/jlmap3d/maintainer/jl3dmaintainer';
import { EventBus } from '@/scripts/event-bus';
import ibpData from '@/ibp/constant/ibpData';
import { timeFormat } from '@/utils/date';
import { Message } from 'element-ui';
import Vue from 'vue';
import localStore from 'storejs';
import MembersManage from './memberManage/membersManage';
import AddMember from './memberManage/addMember';
import { getLoginInfo } from '@/api/login';
export default {
name: 'JointTrainingDraft',
@ -88,7 +95,9 @@ export default {
Jl3dDrive,
Jl3dMaintainer,
IbpPlate,
JsQuestion
JsQuestion,
MembersManage,
AddMember
},
data() {
return {
@ -120,7 +129,9 @@ export default {
practicalTime: 0,
countdown: null,
questionList: [],
practicalExamTime: 0
practicalExamTime: 0,
isAdmin: false,
adminMode: true
};
},
computed: {
@ -183,6 +194,10 @@ export default {
this.mapBoxP.style.cursor = '';
this.mapViewLoadedOver = true;
this.showSelectStation && this.setShowStation(this.showStation);
this.initMemberUserInfo();
},
'$store.state.socket.memberChangeCount': function () {
this.initMemberUserInfo();
},
'$store.state.socket.permissionOver': function () {
this.$alert(this.$t('tip.userRightsHaveBeenReclaimed'), this.$t('tip.hint'), {
@ -191,24 +206,10 @@ export default {
callback: async (action) => {
await this.$store.dispatch('training/over');
await clearSimulation(this.group);
await deljointTrainRoomNew(this.group);
this.$router.go(-1);
}
});
},
'$store.state.socket.jointRoomInfo': function (val) { //
if (val.creatorId) {
this.handleRoomInfo(val);
}
},
'$store.state.socket.roleList': function (val) { //
val.forEach(elem => {
if (elem.id == this.userId && !elem.userRole) {
this.$router.go(-1);
this.messageInfo(this.$t('tip.beKickedOut'), 'warning');
}
});
},
'$store.state.app.windowSizeCount': function() {
this.setWindowSize();
},
@ -220,6 +221,11 @@ export default {
'$store.state.map.map': function (val) {
this.showSelectStation = val.skinVO.code === '06' && this.$store.state.training.prdType === '01';
this.setStationList(val);
},
'$store.state.socket.simulationRoleList':function(val) {
if (val && val.length) {
this.checkRoleChange(val);
}
}
},
async created() {
@ -248,18 +254,6 @@ export default {
mousemove(e) {
this.mouseNum = 1;
},
handleRoomInfo(data) {
if (data.state == '03') { // 退
this.$router.go(-1);
} else if (data.state == '01') { //
const query = { group: this.group, lineCode:this.lineCode };
if (this.drawWay) {
query.drawWay = this.drawWay;
}
this.$router.replace({ path: `/trainroom`, query: query });
}
this.$store.dispatch('socket/setJointRoomInfo'); //
},
// 线
clearAllTimer() {
if (this.ierval) {
@ -354,6 +348,23 @@ export default {
this.endViewLoading();
}
},
async initDeviceVo() {
getLoginInfo(getToken()).then(resp => {
this.$store.dispatch('SetProjecteDevice', resp.data.deviceVO);
});
},
initMemberUserInfo() {
getSimulationMemberList(this.$route.query.group).then(resp => {
this.$store.dispatch('training/setMemberList', {memberList:resp.data, userId: this.$store.state.user.id});
}).catch(() => {
this.$messageBox('获取仿真成员列表失败!');
});
getAllSimulationUser(this.$route.query.group).then(resp => {
this.$store.dispatch('training/setSimulationUserList', resp.data);
}).catch(() => {
this.$messageBox('获取所有仿真用户失败!');
});
},
async loadSimulationInfo() {
const resp = await getSimulationInfoNew(this.group);
if (resp && resp.code == 200 && resp.data && !resp.data.dataError) {
@ -366,24 +377,23 @@ export default {
} else {
this.$store.dispatch('training/over');
}
// if (this.isDemon) {
// this.$refs.menuDemon.initPlannedDriving(resp.data.planRunning);
// } else if (this.isScript) {
// this.$refs.menuScript.initPlannedDriving(resp.data.planRunning);
// }
} else if (resp && resp.code == 200 && resp.data && resp.data.dataError) {
this.dataError = true;
this.$messageBox('此地图数据正在维护中,无法运行!');
}
},
async getUserRole() {
const res = await getUserRolesNew(this.group);
const res = await getSimulationUserInfo(this.group);
const data = res.data || {};
this.userRole = data.userRole;
this.userRole = data.role || 'AUDIENCE';
this.deviceCode = data.deviceCode;
this.ibpPart = data.ibpPart;
if (this.userRole === 'IBP') {
this.isAdmin = data.admin;
const deviceVO = this.$store.state.user.projectDevice;
if (deviceVO && deviceVO.type === 'IBP') {
this.showIbp(this.deviceCode);
const config = JSON.parse(deviceVO.config);
this.ibpPart = config.part.toLowerCase();
} else {
this.hideIbp();
}
@ -421,30 +431,35 @@ export default {
resp['code'] = 200;
resp.data['userRole'] = 'ADMIN';
} else {
await this.initDeviceVo();
resp = await this.getUserRole();
}
// console.log('/////////////' + resp.data.userRole);
if (resp && resp.code == 200) {
// Admin Instructor Dispatcher STATION_SUPERVISOR Audience Driver MAINTAINER IBP:IBP
this.userRole = resp.data.userRole;
switch (this.userRole) {
case 'ADMIN': this.$store.dispatch('training/setPrdType', '02'); this.$store.dispatch('training/setRoles', 'ADMIN'); this.hideIbp(); break;
case 'INSTRUCTOR': this.$store.dispatch('training/setPrdType', '02'); this.$store.dispatch('training/setRoles', 'INSTRUCTOR'); this.hideIbp(); break;
case 'DISPATCHER': this.$store.dispatch('training/setPrdType', '02'); this.$store.dispatch('training/setRoles', 'DISPATCHER'); this.hideIbp(); break;
case 'STATION_SUPERVISOR': this.$store.dispatch('training/setPrdType', '01'); this.$store.dispatch('training/setRoles', 'STATION_SUPERVISOR'); this.hideIbp(); break;
case 'INTERLOCK': this.$store.dispatch('training/setPrdType', '01'); this.$store.dispatch('training/setRoles', 'INTERLOCK'); this.hideIbp(); break;
case 'AUDIENCE': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'AUDIENCE'); this.hideIbp(); break;
case 'DRIVER': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'DRIVER'); this.hideIbp(); break;
case 'MAINTAINER': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'MAINTAINER'); this.hideIbp(); break;
case 'IBP': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'IBP'); this.showIbp(resp.data.deviceCode); break;
case 'BIGSCREEN': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'BIGSCREEN'); this.hideIbp(); break;
}
this.userRole = resp.data.role || 'AUDIENCE';
this.setSimulationPrdType();
}
await this.getTrainDetail();
} else {
this.endViewLoading();
}
},
// prdTyperole
setSimulationPrdType(swch) {
// Admin Dispatcher STATION_SUPERVISOR Audience Driver MAINTAINER IBP:IBP
switch (this.userRole) {
// case 'ADMIN': this.$store.dispatch('training/setPrdType', '02'); this.$store.dispatch('training/setRoles', 'ADMIN'); this.hideIbp(); break;
case 'DISPATCHER': this.$store.dispatch('training/setPrdType', '02'); this.$store.dispatch('training/setRoles', 'DISPATCHER'); this.hideIbp(); break;
case 'STATION_SUPERVISOR': this.$store.dispatch('training/setPrdType', '01'); this.$store.dispatch('training/setRoles', 'STATION_SUPERVISOR'); this.hideIbp(); break;
case 'AUDIENCE': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'AUDIENCE'); this.hideIbp(); break;
case 'DRIVER': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'DRIVER'); this.hideIbp(); break;
case 'MAINTAINER': this.$store.dispatch('training/setPrdType', ''); this.$store.dispatch('training/setRoles', 'MAINTAINER'); this.hideIbp(); break;
}
if (this.isAdmin && this.adminMode) {
this.$store.dispatch('training/setPrdType', swch || '02');
this.$store.dispatch('training/setRoles', 'AUDIENCE');
this.hideIbp();
}
},
startCounting() {
const storeKey = this.$store.state.user.id + '' + this.$route.query.raceId + 'practical';
const startTime = localStore.get(storeKey);
@ -515,18 +530,10 @@ export default {
this.ibpShow = false;
},
showIbp(deviceCode) {
if (!this.ibpShow) {
this.drivingShow = false;
this.panelShow = false;
this.ibpShow = true;
if (!deviceCode || !ibpData[deviceCode]) {
Message.warning({message: this.$t('error.ibpNoDraw'), duration: 0, showClose: true, type: 'error'});
return;
} else {
Message.closeAll();
}
this.$refs.ibpPlate.show(deviceCode, this.ibpPart);
}
},
hidejl3dcctv() {
const routeData = this.$router.resolve({
@ -616,6 +623,27 @@ export default {
cancelBigScreenMode() {
this.$jlmap.on('zoom');
this.$jlmap.setRevoverBigScreen();
},
handlerMemberManage() {
this.$refs.membersManage.doShow();
},
addSimulationMember() {
this.$refs.addMember.doShow();
},
changeAdminMode(adminMode, swch) {
this.adminMode = adminMode;
this.setSimulationPrdType(swch);
},
checkRoleChange(data) {
data.forEach(item => {
if (item.messageType === 'KICK_OUT' && item.userId == this.userId) {
this.$messageBox('您已经被请离房间!');
this.$refs.demonMenu.back();
} else if (item.messageType === 'PLAY_CHANGE' && item.userId == this.userId) {
this.userRole = item.role || 'AUDIENCE';
this.setSimulationPrdType();
}
});
}
}
};

View File

@ -0,0 +1,80 @@
<template>
<el-dialog
v-dialogDrag
:title="title"
:visible.sync="dialogVisible"
width="500px"
:before-close="handleClose"
center
:close-on-click-modal="false"
>
<el-form ref="form" :model="formModel" label-width="120px" :rules="rules">
<el-form-item label="添加仿真成员:" prop="role">
<el-select v-model="formModel.role" placeholder="请选择" size="small">
<el-option
v-for="item in typeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
<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>
</span>
</el-dialog>
</template>
<script>
import { addSimulationMember } from '@/api/jointSimulation';
export default {
name: 'AddMember',
data() {
return {
dialogVisible: false,
formModel: {
role: ''
},
rules: {
role: [
{ required: true, message: '请选择显示位置', trigger: 'change' }
]
},
typeList: [{label: '行调', value: 'DISPATCHER'}, {label: '通号', value: 'MAINTAINER'}]
};
},
computed: {
title() {
return '添加仿真角色成员';
}
},
methods: {
initData(row) {
},
doShow(row) {
this.initData(row);
this.dialogVisible = true;
},
doSave() {
this.$refs.form.validate(() => {
addSimulationMember(this.formModel, this.$route.query.group).then(() => {
this.$message.success('添加仿真角色成员成功!');
this.handleClose();
}).catch(() => {
this.$message.error('添加仿真角色成员失败!');
});
});
},
handleClose() {
this.dialogVisible = false;
this.formModel = {
role: ''
};
this.$refs.form.resetFields();
}
}
};
</script>

View File

@ -0,0 +1,103 @@
<template>
<div class="jointRoomMenu">
<pop-menu ref="popMenu" :menu="menu" />
</div>
</template>
<script>
import PopMenu from '@/components/PopMenu';
import { DeviceMenu } from '@/scripts/ConstDic';
import { kickOutMember } from '@/api/jointSimulation';
export default {
components: {
PopMenu
},
props: {
clickUserId: {
type: String,
default: ''
},
menuDisabled: {
type: Boolean,
default: false
}
},
data() {
return {
// menu: [{
// label: this.$t('trainRoom.kickOutTheRoom'),
// handler: this.kicked
// }]
};
},
computed: {
userId() {
return this.$store.state.user ? this.$store.state.user.id : '';
},
position() {
return this.$store.state.menuOperation.menuPosition;
},
drawWay() {
return this.$route.query.drawWay + '';
},
menu() {
return [{
label: this.$t('trainRoom.kickOutTheRoom'),
handler: this.kicked,
disabled: this.menuDisabled
}];
}
},
watch: {
'$store.state.menuOperation.menuCount': function (val) {
if (this.$store.getters['menuOperation/checkDialogIsOpen'](DeviceMenu.JointRoom)) {
this.doShow();
} else {
this.doClose();
}
}
},
mounted() {
this.closeEvent();
},
methods: {
closeEvent() {
const self = this;
window.onclick = function (e) {
self.doClose();
};
},
doShow() {
this.closeEvent();
if (this.userId != this.clickUserId) {
if (this.$refs && this.$refs.popMenu) {
this.$refs.popMenu.resetShowPosition(this.position);
}
}
},
doClose() {
if (this.$refs && this.$refs.popMenu) {
this.$refs.popMenu.close();
}
},
async kicked() {
try {
await kickOutMember(this.$route.query.group, this.clickUserId);
} catch (error) {
console.error(error);
}
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
/deep/ {
.menu-item{
background: #f1ecec;
.pop-menu {
background: #5F9EA0;
}
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<div class="member">
<div class="member__head">
<div class="member__head--title"> 成员列表</div>
<div class="member__head--notes"> {{ members.length }}/{{ room.totalNum }}</div>
</div>
<div class="member__container">
<el-input v-model="filterText" :placeholder="this.$t('global.enterNameToFilter')" clearable />
<el-scrollbar class="member__container--list" wrap-class="scrollbar-wrapper" :style="{height: treeHeight+'px'}">
<el-tree
ref="tree"
:data="filterMembers"
:filter-node-method="handleFilterNode"
:lazy="false"
:props="defaultProps"
@node-contextmenu="handleShowContextMenu"
>
<span slot-scope="{ node, data }">
<span v-if="node.data.online" style="color: green;">{{ data.nickName + (data.admin? '管理员':'') + (data.referee? '裁判员':'') + (data.deviceVO? ` -- (${data.deviceVO.code})`:'') }}</span>
<span v-else style="color: #ccc;">{{ data.nickName + (data.admin? '【管理员】':'') + (data.referee? '【裁判员】':'') + (data.deviceVO? ` -- (${data.deviceVO.code})`:'') }}</span>
</span>
</el-tree>
</el-scrollbar>
</div>
<content-menu ref="menu" :click-user-id="clickUserId" :menu-disabled="menuDisabled" />
</div>
</template>
<script>
import { DeviceMenu } from '@/scripts/ConstDic';
import ContentMenu from './content-menu';
export default {
components: {
ContentMenu
},
props: {
room: {
type: Object,
required: true
},
members: {
type: Array,
required: true
},
height: {
type: Number,
required: true
},
isAdmin: {
type: Boolean,
default() {
return false;
}
}
},
data() {
return {
filterText: '',
clickUserId: '',
menuDisabled: false
};
},
computed: {
defaultProps() {
return { label: 'nickName' };
},
treeHeight() {
return this.height - 64;
},
filterMembers() {
return this.members.filter(e =>{ return e.nickName.includes(this.filterText); });
},
userId() {
return this.$store.state.user ? this.$store.state.user.id : '';
}
},
methods: {
handleFilterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
handleShowContextMenu(e, obj, node, vueElem) {
e.preventDefault();
const position = {
x: e.clientX,
y: e.clientY
};
if (this.isAdmin) {
this.clickUserId = `${obj.userId || ''}`;
this.menuDisabled = !!obj.deviceVO;
this.$store.dispatch('menuOperation/setPopMenu', { position, menu: DeviceMenu.JointRoom });
}
}
}
};
</script>
<style scoped lang="scss">
.member {
background: #f0f0f0;
display: flex;
flex-direction: column;
border: 1px solid #ccc;
&__head {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
border-bottom: 1px solid #ccc;
&--title {
padding:10px 0px;
font-size: 16px;
font-weight: bold;
}
&--notes {
font-size: 16px;
padding:10px 0px;
display: flex;
align-items: flex-end;
}
}
&__container {
flex-grow: 1;
&--list {
background: #fff;
height: auto;
min-height: calc(100% - 200px);
max-height: calc(100% - 200px);
border-bottom: 1px #ccc solid;
&::-webkit-scrollbar {
display: none;
}
}
}
}
</style>

View File

@ -0,0 +1,343 @@
<template>
<el-dialog
v-dialogDrag
title="仿真成员管理"
:visible.sync="show"
width="100%"
:before-close="doClose"
:z-index="2000"
:modal="false"
fullscreen
:close-on-click-modal="false"
center
>
<div class="room">
<div class="room__container">
<div style="width: 70%;">
<div style="margin-left: 10px;margin-right: 10px;">
<el-input v-model="queryMember" placeholder="请输入搜索人员">
<el-button slot="append" icon="el-icon-search" />
</el-input>
<el-button @click="addMember">添加仿真成员</el-button>
</div>
<el-tree
ref="tree"
:data="treeData"
:props="defaultProps"
default-expand-all
style="margin: 10px;margin-bottom: 0;border: 1px solid #ccc;overflow-y: auto;"
:style="{height: height - 35 + 'px'}"
:filter-node-method="filterNode"
@node-click="handleNodeClick"
>
<span :id="data.id" slot-scope="{ node, data }" class="custom-tree-node">
<span>{{ data.label }}</span>
<span v-if="data.role">
<el-select :key="data.id" v-model="data.userId" placeholder="请选择" clearable size="mini" @change="nodeMemberChange($event, data)">
<el-option
v-for="item in simulationUserList"
:key="item.userId"
:label="item.nickName"
:value="item.userId"
/>
</el-select>
</span>
</span>
</el-tree>
</div>
<e-members
class="room__container--members"
:room="room"
:members="simulationUserList"
:is-admin="isAdmin"
:height="height"
@message="messageInfo"
/>
</div>
<div class="room__footer" />
</div>
</el-dialog>
</template>
<script>
import eMembers from './e-members';
import { assignUsersPlayRoles } from '@/api/jointSimulation';
export default {
name: 'MembersManage',
components: {
eMembers
},
props: {
isAdmin: {
type: Boolean,
default() {
return false;
}
}
},
data() {
return {
show: false,
queryMember: '',
room: {
totalNum: 0,
group: '',
mapId: '',
creatorId: '',
creator: {
nickName: ''
},
permissionRest: 0,
permissionNum: 0,
state: ''
},
defaultProps: {
children: 'children',
label: 'label'
},
simulationUserList: [],
stationList: [],
availableStationList:[],
activeTrains: [],
standList: [],
doorList: [],
memberData: {},
treeData: [{
label: '行调',
type: 'role',
children: []
}, {
label: '车站值班员',
type: 'role',
children: []
}, {
label: '司机',
type: 'role',
children: []
}, {
label: '通号',
children: []
}]
};
},
computed: {
height() {
return this.$store.state.app.height - 130;
},
group() {
return this.$route.query.group;
},
drawWay() {
return this.$route.query.drawWay + '';
},
userId() {
return this.$store.state.user ? this.$store.state.user.id : '';
},
username() {
return this.$store.state.user.nickname;
},
projectDevice() {
return this.$store.state.user.projectDevice;
}
},
watch: {
queryMember(val) {
this.$refs.tree.filter(val);
},
'$store.state.socket.simulationRoleList':function(val) {
if (val && val.length) {
this.handlerMemberOnOff(val);
}
},
'$store.state.training.simulationUserList': function(val) {
this.simulationUserList = val;
},
'$store.state.training.memberList': function (val) {
if (val && val.length) {
this.memberData = this.$store.state.training.memberData;
const dispatcherList = [];
const electricDispatcherList = [];
const depotDispatcherList = [];
const stationSupervisorList = [];
const driverList = [];
const maintainerList = [];
val.forEach(item => {
const device = this.$store.getters['map/getDeviceByCode'](item.deviceCode);
switch (item.role) {
case 'DISPATCHER':
this.memberData[item.id].label = '行调' + (dispatcherList.length + 1);
dispatcherList.push(this.memberData[item.id]);
break;
case 'ELECTRIC_DISPATCHER':
electricDispatcherList.push(this.memberData[item.id]);
break;
case 'DEPOT_DISPATCHER':
depotDispatcherList.push(this.memberData[item.id]);
break;
case 'STATION_SUPERVISOR':
this.memberData[item.id].label = '值班员-' + device.name;
stationSupervisorList.push(this.memberData[item.id]);
break;
case 'DRIVER':
this.memberData[item.id].label = '司机-列车' + item.deviceCode;
driverList.push(this.memberData[item.id]);
break;
case 'MAINTAINER':
this.memberData[item.id].label = '通号' + (maintainerList.length + 1);
maintainerList.push(this.memberData[item.id]);
break;
}
});
this.treeData = [{
label: '行调',
id: 'dispatcher',
type: 'role',
children: dispatcherList
}, {
label: '车站值班员',
id: 'stationSupervisor',
type: 'role',
children: stationSupervisorList
}, {
label: '司机',
id: 'driver',
type: 'role',
children: driverList
}, {
label: '通号',
id: 'maintainer',
type: 'role',
children: maintainerList
}];
}
},
'$store.state.map.activeTrainListUpdate': function (val) {
this.activeTrains = [];
const activeTrainList = this.$store.state.map.activeTrainList;
if (activeTrainList && activeTrainList.length) {
activeTrainList.forEach(train => {
this.activeTrains.push(train.groupNumber);
});
}
this.$refs.tree.filter(this.queryMember);
}
},
mounted() {
},
methods: {
doShow() {
this.show = true;
this.memberData = this.$store.state.training.memberData;
this.simulationUserList = this.$store.state.training.simulationUserList;
this.$nextTick(() => {
if (this.$refs.tree) {
this.$refs.tree.filter(this.queryMember);
}
});
},
doClose() {
this.show = false;
},
messageInfo(info) {
this.$message({ showClose: true, ...info });
},
jumpInSimulation() {
},
clearSubscribe() {
},
handleNodeClick() {
},
nodeMemberChange(val, nodeData) {
let user = '';
this.simulationUserList.forEach(item => {
if (val && item.userId === val) {
user = item;
} else if (!val && item.memberId === nodeData.id) {
user = item;
}
});
const data = [{userId: user.userId, memberId:val ? nodeData.id : ''}];
const self = this;
assignUsersPlayRoles(data, this.$route.query.group).then(resp => {
this.$message.success('调整角色成员成功!');
}).catch(() => {
self.memberData[nodeData.id].userId = '';
this.$message.error('调整角色成员失败!');
});
},
addMember() {
this.$emit('addSimulationMember');
},
filterNode(value, data) {
let flag = false;
if (this.memberData[data.id] && this.memberData[data.id].nickName) {
flag = this.memberData[data.id].nickName.indexOf(value) !== -1;
}
let driverNoShow = true;
if (data.role && data.role === 'DRIVER' && !this.activeTrains.includes(data.deviceCode)) {
driverNoShow = false;
}
return (data.label.indexOf(value) !== -1 || flag) && driverNoShow;
},
handlerMemberOnOff(data) {
this.$store.dispatch('training/updateMemberAndUser', {simulationUserList:data, userId: this.userId});
}
}
};
</script>
<style scoped lang="scss">
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
margin: 2px;
}
.room {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
background: #f0f0f0;
&__container {
display: flex;
flex-grow: 1;
padding: 10px;
&--members {
flex-shrink: 1;
flex-grow: 1;
}
&--roles {
flex-grow: 5;
flex-shrink: 5;
}
&--chat {
flex-basis: 360px;
}
}
&__footer {
height: 20px;
}
}
/deep/ {
.el-input--mini .el-input__inner {
height: 24px;
line-height: 24px;
}
.el-input-group {
width: calc(100% - 146px);
}
.el-dialog__body {
padding: 6px 20px;
}
}
</style>

View File

@ -3,22 +3,23 @@
<chat-box :group="group" :user-role="userRole" />
<div class="display-draft" :class="{'display-type-hb': $route.query.lineCode == '07' && $store.state.training.prdType=='01'}">
<el-button-group>
<el-button v-if="isProject && !dataError " type="primary" @click="setRelDevice">{{ $t('joinTraining.connectRealDevices') }}</el-button>
<el-button v-if="isAdmin && adminMode" @click="memberManage">成员管理</el-button>
<el-button v-if="isAdmin && adminMode" type="primary" @click="generateQrCode">生成二维码</el-button>
<el-button v-if="hasRealDevice && !dataError " type="primary" @click="setRelDevice">{{ $t('joinTraining.connectRealDevices') }}</el-button>
<el-button v-if="isDriver && !dataError" type="jumpjlmap3d" @click="jumpjlmap3d">{{ $t('joinTraining.driverPerspective') }}</el-button>
<el-button v-if="isStationSupervisor && !dataError" type="jmap3dcctv" @click="jlmap3dcctv">cctv</el-button>
<template v-if="isAdmin && project != 'refereeJsxt'">
<template v-if="isAdmin && adminMode && project != 'refereeJsxt'">
<el-button type="success" :disabled="isDisable || dataError" @click="selectBeginTime">{{ $t('joinTraining.drivingByPlan') }}</el-button>
<el-button type="danger" :disabled="dataError" @click="end">{{ $t('joinTraining.initialize') }}</el-button>
</template>
<!-- <el-button type="primary" :loading="backLoading" @click="back">{{ $t('global.back') }}</el-button> -->
</el-button-group>
<template v-if="project==='jsxt'">
<div style="background: #FFF;display: inline-block;height: 40px;line-height: 40px;padding: 0 5px;border: 2px solid #F00;border-radius: 6px;margin-right: 8px;">{{ '剩余时间:'+countdownTime }}</div>
<el-button :disabled="!jsStart" type="success" @click="startCompetition">开始</el-button>
<el-button :disabled="jsStart" type="danger" @click="endCompetition">提交</el-button>
</template>
<el-button v-if="project==='refereeJsxt'" type="success" @click="refeeEndCompetition">返回</el-button>
<el-button v-if="project!=='jsxt'&&project!=='refereeJsxt'" type="primary" :loading="backLoading" @click="back">{{ $t('global.back') }}</el-button>
<el-button v-if="project==='refereeJsxt'" type="success" @click="refeeEndCompetition">退出</el-button>
<el-button v-if="project!=='jsxt'&&project!=='refereeJsxt'" type="primary" :loading="backLoading" @click="back">退出</el-button>
</div>
<qr-code ref="qrCode" />
<set-time ref="setTime" @ConfirmSelectBeginTime="start" />
@ -28,11 +29,11 @@
<script>
import QrCode from '@/components/QrCode';
import ChatBox from './chatView/chatBox';
import ChatBox from './newChatView/chatBox';
import SetTime from '@/views/newMap/displayNew/demon/setTime';
import { ranAsPlan, exitRunPlan } from '@/api/simulation';
import { ranAsPlan, exitRunPlan, clearSimulation } from '@/api/simulation';
import { exitFullscreen } from '@/utils/screen';
import { putJointTrainingSimulationUserNew} from '@/api/jointTraining';
import { getSimulationQrcode } from '@/api/jointSimulation';
import { EventBus } from '@/scripts/event-bus';
import { getSessionStorage } from '@/utils/auth';
import RealDevice from './menuDraft/realDevice';
@ -43,8 +44,6 @@ import localStore from 'storejs';
export default {
name: 'MenuDemonJoint',
components: {
// ChartView,
// ChartWindow,
ChatBox,
QrCode,
SetTime,
@ -74,6 +73,18 @@ export default {
default() {
return false;
}
},
isAdmin: {
type: Boolean,
default() {
return false;
}
},
adminMode: {
type: Boolean,
default() {
return false;
}
}
},
data() {
@ -85,7 +96,8 @@ export default {
userId: '',
stationList: [],
stationLists: [],
jsStart: true
jsStart: true,
isGoback: false
};
},
computed: {
@ -96,17 +108,12 @@ export default {
return this.userRole != 'DRIVER' && this.userRole != '';
},
isStationSupervisor() {
console.log(this.userRole);
return this.userRole == 'STATION_SUPERVISOR';
},
isDriver() {
console.log(this.userRole);
return this.userRole == 'DRIVER';
},
isAdmin() {
return this.userRole == 'ADMIN';
},
isProject() {
hasRealDevice() {
return getSessionStorage('project').endsWith('gzb') && this.userRole === 'CI';
},
project() {
@ -143,6 +150,10 @@ export default {
'$store.state.socket.simulationOver':function(val) {
if (val && this.project === 'refereeJsxt') {
this.$router.go(-1);
} else {
if (!this.isGoback) {
this.back();
}
}
}
},
@ -151,7 +162,6 @@ export default {
this.backLoading = false;
await this.initLoadPage();
this.isDisable = this.$store.state.map.runPlanStatus;
console.log(this.userRole);
},
beforeDestroy() {
this.$store.dispatch('training/setGroup', '');
@ -301,14 +311,21 @@ export default {
});
});
},
back() {
async back() {
this.isGoback = true;
if (this.isAdmin) {
await clearSimulation(this.group);
}
this.$store.dispatch('training/over').then(() => {
this.backLoading = true;
putJointTrainingSimulationUserNew(this.group).then(() => {
this.$router.replace({ path: `/trainroom`, query: { lineCode: this.lineCode, group: this.group, drawWay: true } });
exitFullscreen();
this.backLoading = false;
if (this.$route.query.projectDevice) {
this.$store.dispatch('LogOut').then(() => {
location.reload();
});
} else {
history.go(-1);
exitFullscreen();
}
});
},
jumpjlmap3d() {
@ -359,6 +376,24 @@ export default {
}).catch(()=> {
this.$message.error('提交试卷失败!');
});
},
memberManage() {
this.$emit('handlerMemberManage');
},
generateQrCode() {
const self = this;
getSimulationQrcode(this.$route.query.group).then(resp => {
const param = {
url: resp.data,
title: self.$t('综合演练二维码'),
group: self.$route.query.group
};
if (self.$refs) {
self.$refs.qrCode.doShow(param);
}
}).catch(() => {
this.$messageBox('仿真生成二维码失败!');
});
}
}
};

View File

@ -1,7 +1,7 @@
<template>
<div class="schema" :style="{top: offset+'px'}">
<el-select
v-if="userRole == 'INSTRUCTOR' || userRole == 'ADMIN'"
v-if="isAdmin && adminMode"
v-model="swch"
size="small"
style="width: 100px;"
@ -17,17 +17,16 @@
<template>
<el-button v-if="runing && !dataError" size="small" :disabled="viewDisabled" @click="viewRunPlan">{{ $t('joinTraining.runGraphPreview') }}</el-button>
</template>
<template v-if="userRole == 'ADMIN'">
<template v-if="isAdmin && adminMode">
<el-button v-if="!runing && !dataError" size="small" type="warning" @click="loadRunPlan">
{{ $t('joinTraining.runGraphLoading') }}</el-button>
</template>
<template v-if="userRole == 'INSTRUCTOR' || userRole == 'ADMIN'">
<template v-if="isAdmin && adminMode">
<el-button v-if="mode==OperateMode.FAULT && !dataError" size="small" type="danger" @click="setFault">{{ $t('joinTraining.faultSetting') }}</el-button>
</template>
</el-button-group>
<el-radio-group
v-if="(userRole == 'INSTRUCTOR' || userRole == 'ADMIN') && !dataError && !isScreen"
v-if="isAdmin && adminMode && !dataError && !isScreen"
v-model="mode"
size="small"
@change="changeOperateMode(mode)"
@ -35,6 +34,10 @@
<el-radio-button class="mode" :label="OperateMode.NORMAL">{{ $t('joinTraining.normalOperation') }}</el-radio-button>
<el-radio-button class="mode" :label="OperateMode.FAULT">{{ $t('joinTraining.faultOperation') }}</el-radio-button>
</el-radio-group>
<el-radio-group v-if="isAdmin" v-model="adminMode" size="small" @change="changeAdminMode">
<el-radio-button class="mode" :label="true">管理模式</el-radio-button>
<el-radio-button class="mode" :label="false">演练模式</el-radio-button>
</el-radio-group>
</div>
</template>
<script>
@ -82,6 +85,12 @@ export default {
default() {
return false;
}
},
isAdmin: {
type: Boolean,
default() {
return false;
}
}
},
data() {
@ -101,16 +110,14 @@ export default {
{ value: '07', name: '大屏'}
],
runing: false,
userId: ''
userId: '',
adminMode: true
};
},
computed: {
...mapGetters('runPlan', [
'stations'
]),
isShowMenuBar() {
return this.$store.state.map.roles == 'Admin';
},
isScreen() {
return this.$store.state.training.prdType === '07';
}
@ -138,7 +145,6 @@ export default {
if (opt && opt.mapId) {
this.viewDisabled = true;
getByGroupStationList(this.$route.query.group).then(response => {
// getStationList(opt.mapId).then(response => {
const stations = response.data;
this.$store.dispatch('runPlan/setStations', stations).then(() => {
getEveryDayRunPlanNew(this.group).then(resp => {
@ -184,6 +190,9 @@ export default {
},
switchStationMode(val) {
this.$emit('switchStationMode', val);
},
changeAdminMode(adminMode) {
this.$emit('changeAdminMode', adminMode, this.swch);
}
}
};

View File

@ -0,0 +1,731 @@
<template>
<!-- v-quickMenuDrag -->
<div class="chatBox" :style="{'bottom':bottom+'px'}">
<div v-show="!minimize" class="chat-box">
<div class="chat-box-main">
<div v-if="!conversitionId && userRole !== 'AUDIENCE'" class="chat-window">
<div class="chat-box-header">
<div class="chat-box-header-title">
<el-input v-model="queryMember" size="small" placeholder="请输入搜索人员">
<el-button slot="append" icon="el-icon-search" />
</el-input>
</div>
<div class="minimality" @click="handleMinimality('min')">
<i class="el-icon-remove" />
</div>
<div class="chat-setting" @click="handleSetting()">
<i class="el-icon-s-tools" />
</div>
</div>
<div class="chat-box-content">
<el-tree
ref="tree"
:data="treeData"
:props="defaultProps"
node-key="id"
default-expand-all
show-checkbox
:filter-node-method="filterNode"
style="margin: 10px;overflow-y: auto;height: 100%;margin-right: 0;"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
>
<span :id="data.id" slot-scope="{ node, data }">
<span style="font-size: 14px">{{ data.label + (data.userId? '(' + (simulationUsers[data.userId]||{}).nickName + ')': '') }}</span>
</span>
</el-tree>
</div>
<div class="chat-box-footer">
<div style="width: 400px;font-size: 14px;">{{ userString }}</div>
<el-button size="mini" type="primary" class="chat-box-footer-create" :loading="createLoading" @click="createCoversition()">创建群聊</el-button>
</div>
</div>
<div v-else class="chat-window">
<div class="chat-box-header">
<div class="chat-box-header-title">{{ headerTitle }}</div>
<div class="minimality" @click="handleMinimality('min')">
<i class="el-icon-remove" />
</div>
<div class="chat-setting" @click="handleSetting()">
<i class="el-icon-s-tools" />
</div>
</div>
<div class="chat-box-content">
<chat-content ref="chatContent" :project="project" :is-answering="IsAnswering" :conversition-id="conversitionId" :message-list="messageList" />
<div v-if="recordSending" class="chat_record_tip">
<div id="record_progress_bar" :style="'width:'+100/60*seconds+'%'" />
<div class="record_icon" />
<div class="record_tip_text">正在录音...</div>
<div class="record_tip_confirm" @click="stopRecording()">确定</div>
<div class="record_tip_cancle" @click="cancleRecording()">取消</div>
</div>
<chat-member-list ref="chatMemberList" :conversition-member-list="conversitionMemberList" :simulation-users="simulationUsers" @connectMember="connectMember" />
</div>
<div class="chat-box-footer">
<div class="chat-box-footer-tool" />
<el-button v-if="isConversitionCreator && isButtonShow" size="mini" type="danger" class="chat-box-footer-quit" :loading="quitLoading" @click="quitConversition()">退出群聊</el-button>
<el-button v-if="isButtonShow" class="chat-box-footer-send" size="mini" type="primary" :disabled="recordSending" @click="startRecording()">发送语音</el-button>
</div>
</div>
</div>
</div>
<div v-show="minimize" class="reminder-drag minimize-box">
<div class="chat-title">聊天窗口</div>
<div class="minimality" @click="handleMinimality('max')">
<i class="el-icon-circle-plus" />
</div>
</div>
<chat-setting ref="chatSetting" :form="form" @setSetting="setSetting" />
<chat-tooltip :group="group" :simulation-users="simulationUsers" @acceptInvite="acceptInvite" />
</div>
</template>
<script>
import ChatSetting from './chatSetting';
import ChatTooltip from './chatTooltip';
import ChatContent from './chatContent';
import ChatMemberList from './chatMemberList';
import RecordRTC from 'recordrtc';
import {sendSimulationConversition, startConversition, overSimulationConversition, getAllConversition} from '@/api/chat';
import { getSessionStorage } from '@/utils/auth';
export default {
name: 'ChatBox',
components:{
ChatSetting,
ChatTooltip,
ChatContent,
ChatMemberList
},
props: {
group: {
type: String,
required: true
},
userRole: {
type: String,
required: true
}
},
data() {
return {
minimize:true,
bottom:15,
recordSending:false,
currentCoversition:{},
conversitionId: '',
seconds:0,
inter:null,
recorders: null,
microphone:null,
isHasCoversition:false,
createLoading:false,
form:{
language:'zh',
sex:'1'
},
headerTitle:'',
treeData: [],
defaultProps: {
children: 'children',
label: 'label'
},
queryMember: '',
activeTrains: [],
firstClick: true,
memberData: {},
simulationUsers: {},
userString: '',
memberIdList: [],
quitLoading: false,
conversitionMemberList: [],
isConversitionCreator: true,
messageList: []
};
},
computed:{
isShow() {
return this.userRole != 'ADMIN' && this.userRole != 'AUDIENCE' && !this.isHasCoversition;
},
isButtonShow() {
return this.userRole != 'AUDIENCE';
},
project() {
return getSessionStorage('project');
},
IsAnswering() {
return !(this.$route.path.includes('refereeJsxtDisplay'));
}
},
watch:{
queryMember(val) {
if (this.$refs.tree) {
this.$refs.tree.filter(val);
}
},
userRole(val) {
if (val === 'AUDIENCE') {
this.isAudienceInitData();
}
},
'$store.state.map.mapViewLoadedCount':function(val) {
const object = document.querySelector('.menuButton');
if (object) {
const objectBottom = parseInt(object.style.bottom) || 0;
this.bottom = this.bottom + object.offsetHeight + objectBottom;
}
},
'$store.state.map.activeTrainListUpdate': function (val) {
this.activeTrains = [];
const activeTrainList = this.$store.state.map.activeTrainList;
if (activeTrainList && activeTrainList.length) {
activeTrainList.forEach(train => {
this.activeTrains.push(train.groupNumber);
});
}
if (this.$refs.tree) {
this.$refs.tree.filter(this.queryMember());
}
},
'$store.state.training.simulationUserList': function(val) {
this.simulationUsers = {};
if (val && val.length) {
val.forEach(user => {
this.simulationUsers[user.userId] = user;
});
}
},
'$store.state.socket.overConversition': function (val) {
this.conversitionId = '';
this.conversitionMemberList = [];
this.messageList = [];
},
'$store.state.training.memberList': function (val) {
if (val && val.length) {
this.memberData = this.$store.state.training.memberData;
const dispatcherList = [];
const electricDispatcherList = [];
const depotDispatcherList = [];
const stationSupervisorList = [];
const driverList = [];
const maintainerList = [];
val.forEach(item => {
const device = this.$store.getters['map/getDeviceByCode'](item.deviceCode);
switch (item.role) {
case 'DISPATCHER':
this.memberData[item.id].label = '行调' + (dispatcherList.length + 1);
dispatcherList.push(this.memberData[item.id]);
break;
case 'ELECTRIC_DISPATCHER':
electricDispatcherList.push(this.memberData[item.id]);
break;
case 'DEPOT_DISPATCHER':
depotDispatcherList.push(this.memberData[item.id]);
break;
case 'STATION_SUPERVISOR':
this.memberData[item.id].label = '值班员-' + device.name;
stationSupervisorList.push(this.memberData[item.id]);
break;
case 'DRIVER':
this.memberData[item.id].label = '司机-列车' + item.deviceCode;
driverList.push(this.memberData[item.id]);
break;
case 'MAINTAINER':
this.memberData[item.id].label = '通号' + (maintainerList.length + 1);
maintainerList.push(this.memberData[item.id]);
break;
}
});
this.treeData = [{
label: '行调',
id: 'dispatcher',
type: 'role',
children: dispatcherList
}, {
label: '车站值班员',
id: 'stationSupervisor',
type: 'role',
children: stationSupervisorList
}, {
label: '司机',
id: 'driver',
type: 'role',
children: driverList
}, {
label: '通号',
id: 'maintainer',
type: 'role',
children: maintainerList
}];
}
}
},
mounted() {
this.firstClick = true;
},
methods:{
handleMinimality(data) {
if (data == 'min') {
this.minimize = true;
this.$refs.chatSetting.doClose();
} else {
this.firstClick && this.$nextTick(() => {
this.userRole == 'AUDIENCE' && this.isAudienceInitData();
if (this.$refs.tree) {
this.$refs.tree.filter(this.queryMember);
}
this.firstClick = false;
});
this.minimize = false;
}
},
setSetting(data) {
this.form = data;
},
setCurrentCoversition(coversition) {
if (coversition && coversition.id) {
this.currentCoversition = coversition;
this.headerTitle = coversition.name;
} else {
this.headerTitle = '';
}
if (this.recordSending) {
this.cancleRecording();
}
this.$refs.chatContent.scrollTop();
},
setHeadTitle(headerTitle) {
this.headerTitle = headerTitle;
},
hideAddCoversition() {
this.isHasCoversition = true;
},
createCoversition() {
this.createLoading = true;
startConversition(this.group, this.memberIdList).then(resp => {
this.conversitionId = resp.data.id;
this.conversitionMemberList = resp.data.memberList;
this.messageList = resp.data.messageList;
this.userString = '';
this.isConversitionCreator = true;
this.$message.success('创建会话成功!');
this.createLoading = false;
}).catch((error) => {
this.$message.error(error.code == '3005' ? '创建会话失败:仿真会话成员忙线中!' : '创建仿真失败!');
this.createLoading = false;
});
},
addCoversition({data, headerTitle}) {
this.$refs.chatCoversitionList.addCoversition(data);
this.isHasCoversition = true;
this.currentCoversition = {id:data.id, all:data.all};
this.headerTitle = headerTitle;
},
//
startRecording() {
const that = this;
if (!this.recordSending && !this.recorders && !this.microphone) {
this.$refs.chatSetting.doClose();
const StereoAudioRecorder = RecordRTC.StereoAudioRecorder;
navigator.getUserMedia(
{ audio: true } //
, function (stream) {
that.microphone = stream;
that.recorders = new RecordRTC(that.microphone, {
type: 'audio',
recorderType: StereoAudioRecorder,
numberOfAudioChannels: 1,
bitsPerSecond:256000,
desiredSampRate: 16000
});
that.recorders.startRecording();
that.recordSending = true;
that.inter = setInterval(() => {
if (that.seconds < 60) {
that.seconds++;
} else {
clearInterval(that.inter);
}
}, 1000);
}, function (error) {
switch (error.code || error.name) {
case 'PERMISSION_DENIED':
case 'PermissionDeniedError':
that.$message({
showClose: true,
message: '用户拒绝提供信息',
type: 'error'
});
break;
case 'NOT_SUPPORTED_ERROR':
case 'NotSupportedError':
that.$message({
showClose: true,
message: '浏览器不支持硬件设备',
type: 'error'
});
break;
case 'MANDATORY_UNSATISFIED_ERROR':
case 'MandatoryUnsatisfiedError':
that.$message({
showClose: true,
message: '无法发现指定的硬件设备',
type: 'error'
});
break;
default:
that.$message({
showClose: true,
message: '无法打开麦克风',
type: 'error'
});
break;
}
}
);
}
},
cancleRecording() {
if (this.microphone) {
clearInterval(this.inter);
this.seconds = 0;
this.microphone.stop();
this.microphone = null;
this.recordSending = false;
this.recorders = null;
}
},
//
stopRecording() {
const that = this;
this.recorders.stopRecording(function(blobURL) {
clearInterval(that.inter);
that.seconds = 0;
const blob = that.recorders.getBlob();
const fd = new FormData();
fd.append('file', blob);
sendSimulationConversition(that.group, that.conversitionId, fd)
.then((data) => {
})
.catch(error => {
console.log(error);
});
if (that.microphone) {
that.microphone.stop();
that.microphone = null;
that.recordSending = false;
that.recorders = null;
}
});
},
handleSetting() {
this.$refs.chatSetting.doShow();
},
handleCreateGroup() {
this.$refs.createGroup.doShow();
},
handleNodeClick() {
},
handleCheckChange() {
const memberList = this.$refs.tree.getCheckedKeys();
this.userString = '';
this.memberIdList = [];
if (memberList && memberList.length) {
memberList.forEach(memberId => {
const member = this.memberData[memberId];
if (member && member.userId) {
this.memberIdList.push(member.id);
this.userString += ((this.userString ? ',' : '') + member.label + '(' + this.simulationUsers[member.userId].nickName + ')');
} else if (member) {
this.userString += ((this.userString ? ',' : '') + member.label);
this.memberIdList.push(member.id);
}
});
}
},
filterNode(value, data) {
let flag = false;
if (this.memberData[data.id] && this.memberData[data.id].nickName) {
flag = this.memberData[data.id].nickName.indexOf(value) !== -1;
}
let driverNoShow = true;
if (data.role && data.role === 'DRIVER' && !this.activeTrains.includes(data.deviceCode)) {
driverNoShow = false;
}
return (data.label.indexOf(value) !== -1 || flag) && driverNoShow;
},
quitConversition() {
this.quitLoading = true;
overSimulationConversition(this.group, this.conversitionId).then(resp => {
this.conversitionId = '';
this.conversitionMemberList = [];
this.messageList = [];
this.quitLoading = false;
}).catch(() => {
this.$message.error('退出会话失败!');
this.quitLoading = false;
});
},
acceptInvite(data) {
this.userString = '';
this.conversitionId = data.id;
this.conversitionMemberList = data.memberList;
this.isConversitionCreator = false;
this.messageList = data.messageList;
},
connectMember(val) {
this.conversitionMemberList.forEach(member => {
if (member.memberId == val.memberId) {
member.connect = true;
}
});
},
isAudienceInitData() {
getAllConversition(this.group).then(resp => {
if (resp.data && resp.data.length) {
let messageList = [];
resp.data.forEach(conversation => {
messageList = [...messageList, ...conversation.messageList];
});
}
});
this.conversitionMemberList = [];
this.$store.state.training.memberList.forEach(item =>{
this.conversitionMemberList.push({memberId: item.id, connect:true });
});
}
}
};
</script>
<style lang="scss" scoped>
.chatBox{
width: 503px;
height: 400px;
position: absolute;
padding-left:5px;
left: 0;
bottom:28px;
z-index:9;
}
.chat-box{
width: 100%;
height: 100%;
}
.chat-box-header{
width: 100%;
height: 40px;
border-bottom: 1px #dedede solid;
}
.chat-box-header-title{
font-size: 15px;
margin-left: 15px;
display: inline-block;
margin-top: 5px;
width: 70%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.chat-box-content{
width: 100%;
height: 300px;
border-bottom: 1px #dedede solid;
position: relative;
}
.chat-box-contentTip{
}
.chat-box-footer{
display: inline-block;
width: 100%;
height: 50px;
overflow-y: auto;
}
.chat-window{
display: inline-block;
width: 100%;
}
.chat-setting{
float: right;
line-height: 40px;
margin-right: 10px;
cursor: pointer;
font-size: 16px;
}
.chat-createGroup{
float: right;
line-height: 40px;
margin-right: 10px;
cursor: pointer;
font-size: 16px;
position: relative;
}
.chat-box-footer-tool{
width: 100%;
height: 17px;
}
.chat-box-footer-send{
background: #36a2fd;
width: 65px;
font-size: 12px;
padding: 5px 0px 4px 0px;
text-align: center;
border-radius: 3px;
color: #fff;
float: right;
margin-right: 10px;
margin-bottom: 10px;
cursor: pointer;
}
.chat-box-footer-quit{
width: 65px;
font-size: 12px;
padding: 5px 0px 4px 0px;
text-align: center;
border-radius: 3px;
color: #fff;
margin-left: 10px;
margin-bottom: 10px;
cursor: pointer;
}
.minimality {
float: right;
line-height: 40px;
margin-right: 10px;
cursor: pointer;
font-size:16px;
}
.chat-box-main{
position: absolute;
width: 100%;
left: 0;
height: 100%;
top: 0;
border-right: 1px #dedede solid;
z-index: 4;
background: #fff;
border-radius: 5px;
left:5px;
font-size:0;
}
.chat-coversition{
}
.coversition-list{
}
.chat-box-footer-create{
width: 65px;
font-size: 12px;
padding: 5px 0px 4px 0px;
text-align: center;
border-radius: 3px;
color: #fff;
position: absolute;
right: 5px;
bottom: 5px;
margin-right: 10px;
margin-top: 10px;
cursor: pointer;
}
.showMembers{
float: right;
line-height: 40px;
margin-right: 10px;
cursor: pointer;
font-size: 17px;
}
#record_progress_bar{
height: 100%;
position: absolute;
background: #bbe5f5;
}
.chat_record_tip{
height: 28px;
display: inline-block;
background: #dfe6ee;
width: 370px;
font-size: 13px;
border-top: 1px #d8dce5 solid;
position: absolute;
bottom: 0;
left: 0;
}
.record_icon{
display: inline-block;
width: 8px;
height: 8px;
background: #25d825;
border-radius: 10px;
left: 7px;
margin-right: 0px;
box-shadow: -1px 0px 3px #6d6d6d;
border: 1px #28d228 solid;
position: absolute;
top: 10px;
}
.record_tip_text{
display: inline-block;
font-size: 12px;
margin-left: 3px;
// padding: 8px 0px 6px 0px;
position: absolute;
top: 8px;
left:20px
}
.record_tip_confirm{
position: absolute;
right: 63px;
padding: 3px 0px 2px 0px;
border: 1px #a2a5aa solid;
border-radius: 5px;
width: 45px;
text-align: center;
font-size: 12px;
top: 4px;
background: #eeeeee;
cursor: pointer;
}
.record_tip_cancle{
position: absolute;
right: 10px;
padding: 3px 0px 2px 0px;
border: 1px #a2a5aa solid;
border-radius: 5px;
width: 45px;
text-align: center;
font-size: 12px;
top: 4px;
background: #eeeeee;
cursor: pointer;
}
.chat-box-footer-send.disbled{
cursor: no-drop;
}
.minimize-box {
width: 97.5%;
height: 40px;
position: absolute;
left: 5px;
bottom: 0;
z-index: 222;
background: #fff;
border-radius: 5px;
.chat-title {
float: left;
font-size: 15px;
margin-left: 10px;
line-height: 40px;
}
.minimality {
float: right;
height: 40px;
line-height: 40px;
margin-right: 10px;
cursor: pointer;
}
}
</style>

View File

@ -0,0 +1,258 @@
<template>
<div class="chatcontentIn">
<div class="chatcontentInner">
<div v-for="(chatContent,index) in messageList" :key="index" class="chatContentInClass">
<div :class="chatContent.self?'rightUser':'leftUser'">
<div class="userHeader">
<!-- chatContent.all&& -->
<div v-if="!chatContent.self" class="userName">{{ covertName(chatContent.member,false) }}</div>
<div :class="chatContent.self?'userChatTime textRight':'userChatTime'">{{ formatTime(chatContent.chatTime) }}</div>
</div>
<div class="userBubble" @click="playAudio(baseUrl+chatContent.src)">
<div class="userMessage">
<!-- chatContent.all&& -->
<span v-if="!chatContent.member.robot&&chatContent.all">{{ covertName(chatContent.targetUser,true) }}</span>
<span class="el-icon-video-play playicon" />
<span class="messageText">{{ chatContent.message }}</span>
</div>
</div>
<audio id="audioPlay" style="display:none" />
</div>
</div>
</div>
</div>
</template>
<script>
import ConstConfig from '@/scripts/ConstConfig';
import Cookies from 'js-cookie';
export default {
props:{
messageList:{
type:Array,
required:true
},
isAnswering:{
type:Boolean,
required:true
},
conversitionId: {
type: String,
required: true
}
},
data() {
return {
chatContentList:[],
coversition:{},
currentAudioList:[],
currentAudioIndex:0,
isPlay:false,
baseUrl:process.env.VUE_APP_VOICE_API
};
},
watch:{
'$store.state.socket.conversationInfo':function (val, old) { // 仿
const conversationInfo = this.$store.state.socket.conversationInfo;
if (this.conversitionId == val.id) {
this.chatContentList.push(conversationInfo);
if (simulationText.userId != this.$store.state.user.id) {
this.currentAudioList.push(this.baseUrl + conversationInfo.src);
if (!this.isPlay) {
this.isPlay = true;
this.playAllAudio();
}
}
this.scrollTop();
} else if (this.userRole === 'AUDIENCE') {
this.messageList.push(conversationInfo.data);
if (simulationText.userId != this.$store.state.user.id) {
this.currentAudioList.push(this.baseUrl + conversationInfo.src);
if (!this.isPlay) {
this.isPlay = true;
this.playAllAudio();
}
}
}
}
},
mounted() {
// this.coversition = this.currentCoversition;
// this.inintData();
},
methods:{
inintData() {
// if (this.coversition.id) {
// getSimulationContextListNew(this.$route.query.group, this.coversition.id).then(res=>{
// const userId = this.$store.state.user.id;
// const coversitionList = res.data.map(coversition=>{
// coversition.self = false;
// if (coversition.member.userId == userId) {
// coversition.self = true;
// }
// coversition.src = coversition.isAudio ? `/audio/${coversition.audioPath}` : '';
// coversition.targetUser = coversition.targetMember ? coversition.targetMember : 'All';
// return coversition;
// });
// this.chatContentList = coversitionList;
// this.scrollTop();
// });
// }
// const coversitionListAll = Object.assign({}, this.$store.state.socket.coversitionList);
// const coversitionList = coversitionListAll[this.coversition.id] || [];
// // console.log('inintData---coversitionList' + JSON.stringify(this.$store.state.socket.coversitionList[this.coversition.id]));
// this.chatContentList = coversitionList;
},
scrollTop() {
this.$nextTick(function() {
const scrollTop = document.querySelector('.chatcontentInner').offsetHeight - document.querySelector('.chatcontentIn').offsetHeight + 30;
document.querySelector('.chatcontentIn').scrollTop = scrollTop;
});
},
formatTime(time) {
return /\d{2}:\d{2}:\d{2}/.exec(time)[0] || time;
},
playAllAudio() {
this.playEachAudio(this.currentAudioList[this.currentAudioIndex]);
},
playEachAudio(audioUrl) {
this.$nextTick(function() {
document.querySelector('#audioPlay').src = audioUrl;
document.querySelector('#audioPlay').play();
const that = this;
document.querySelector('#audioPlay').onended = function() {
that.currentAudioList.shift();
console.log(that.currentAudioList.length);
if (that.currentAudioList.length > 0) {
that.playEachAudio(that.currentAudioList[that.currentAudioIndex]);
} else {
that.isPlay = false;
}
};
});
},
covertName(data, status) {
if (data != 'All') {
if (data instanceof Array) {
let result = '';
data.forEach(each=>{
result += this.covertEachName(each, status);
});
return result;
} else {
return this.covertEachName(data, status);
}
} else {
return '@All';
}
},
covertEachName(data, status) {
const roleTypeList = ConstConfig.ConstSelect.roleTypeNew;
roleTypeList.forEach(function(element) {
const rolename = element.value;
if (Cookies.get('user_lang') == 'en') {
if (rolename == data.role) {
data.role = element.enLabel;
}
} else {
if (rolename == data.role) {
data.role = element.label;
}
}
});
const deviceName = data.deviceName ? '-' + data.deviceName : '';
const memberName = data.name ? '-' + data.name : '';
if (status) {
return '@' + data.role + deviceName + memberName;
} else {
return data.role + deviceName + memberName;
}
},
playAudio(audioUrl) {
document.querySelector('#audioPlay').src = audioUrl;
document.querySelector('#audioPlay').play();
}
}
};
</script>
<style lang="scss" scoped>
.chatcontentIn{
height: 100%;
width: 380px;
display: inline-block;
overflow: auto;
padding-bottom: 20px;
cursor:auto;
}
.leftUser{
float: left;
margin-left: 10px;
margin-top: 10px;
display: inline-block;
}
.rightUser{
float: right;
margin-right: 10px;
margin-top: 10px;
display: inline-block;
}
.userHeader{margin-bottom: 2px;}
.userName{font-size: 12px;display:inline-block;}
.userChatTime{font-size: 12px;display:inline-block;}
.userBubble{
max-width: 200px;
font-size: 12px;
padding: 10px;
background: #ccc;
border-radius: 5px;
cursor: pointer;
}
.playicon{
font-size: 20px;
vertical-align: top;
}
.textRight{text-align: right;width: 100%;}
.userMessage{}
.messageText{line-height: 20px;}
.chatContentInClass{
display: inline-block;
width: 100%;
}
// safariqq360
//
.chatcontentIn::-webkit-scrollbar {
width: 6px;
height: 6px;
// height: 110px;
background-color: #FFFFFF;
}
/*定义滚动条轨道 内阴影+圆角*/
.chatcontentIn::-webkit-scrollbar-track {
// box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
background-color: #FFFFFF;;
}
/*定义滑块 内阴影+圆角*/
.chatcontentIn::-webkit-scrollbar-thumb {
border-radius: 10px;
// box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #cacaca;
}
/*滑块效果*/
.chatcontentIn::-webkit-scrollbar-thumb:hover {
border-radius: 5px;
// box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: rgba(0,0,0,0.4);
}
/*IE滚动条颜色*/
html {
scrollbar-face-color:#bfbfbf;/*滚动条颜色*/
scrollbar-highlight-color:#000;
scrollbar-3dlight-color:#000;
scrollbar-darkshadow-color:#000;
scrollbar-Shadow-color:#adadad;/*滑块边色*/
scrollbar-arrow-color:rgba(0,0,0,0.4);/*箭头颜色*/
scrollbar-track-color:#eeeeee;/*背景颜色*/
}
</style>

View File

@ -0,0 +1,136 @@
<template>
<div class="chat-box-members">
<div class="chat-member-title">成员列表</div>
<div class="chat-member-list">
<div
v-for="member in conversitionMemberList"
:key="member.memberId"
class="each-chat-member"
:style="computedStyle(member)"
:title="memberData[member.memberId].label + (memberData[member.memberId].userId? '(' + simulationUsers[memberData[member.memberId].userId].nickName + ')': '')"
>{{ memberData[member.memberId].label + (memberData[member.memberId].userId? '(' + simulationUsers[memberData[member.memberId].userId].nickName + ')': '') }}</div>
<!-- :class="member.online?'each-chat-member':'each-chat-member each-chat-member-outline'" -->
</div>
</div>
</template>
<script>
export default {
name: 'ChatMemberList',
props: {
conversitionMemberList:{
type: Array,
required: true
},
simulationUsers: {
type: Object,
required: true
}
},
data() {
return {
showMembers:true,
memberList:[]
};
},
computed:{
userId() {
return this.$store.state.user.id;
},
memberData() {
return this.$store.state.training.memberData;
}
},
watch:{
'$store.state.socket.acceptConversionInvite':function(val) {
this.$emit('connectMember', val);
}
},
mounted() {
},
methods:{
computedStyle(member) {
const userId = this.memberData[member.memberId].userId;
if (userId && userId == this.userId) {
return {color: 'red'};
} else {
return {color: member.connect ? 'green' : 'gray'};
}
}
}
};
</script>
<style lang="scss" scoped>
.chat-box-members{
position: absolute;
width: 140px;
right: 0;
height: 100%;
background: #fff;
border-right: 1px #dedede solid;
border-radius: 0px 5px 5px 0px;
z-index: 2;
transition: transform 1s;
padding: 12px 2px 10px 16px;
font-size: 14px;
display: inline-block;
border-left: 1px #dedede solid;
}
.chat-member-title{
}
.chat-member-list{
margin-top: 13px;
font-size: 12px;
margin-left: 2px;
height: 250px;
overflow-y: auto;
}
.each-chat-member{
margin-bottom: 10px;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.each-chat-member-outline{
color: #ccc;
}
// safariqq360
//
.chat-member-list::-webkit-scrollbar {
width: 6px;
height: 6px;
// height: 110px;
background-color: #FFFFFF;
}
/*定义滚动条轨道 内阴影+圆角*/
.chat-member-list::-webkit-scrollbar-track {
// box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
background-color: #FFFFFF;;
}
/*定义滑块 内阴影+圆角*/
.chat-member-list::-webkit-scrollbar-thumb {
border-radius: 10px;
// box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #cacaca;
}
/*滑块效果*/
.chat-member-list::-webkit-scrollbar-thumb:hover {
border-radius: 5px;
// box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: rgba(0,0,0,0.4);
}
/*IE滚动条颜色*/
html {
scrollbar-face-color:#bfbfbf;/*滚动条颜色*/
scrollbar-highlight-color:#000;
scrollbar-3dlight-color:#000;
scrollbar-darkshadow-color:#000;
scrollbar-Shadow-color:#adadad;/*滑块边色*/
scrollbar-arrow-color:rgba(0,0,0,0.4);/*箭头颜色*/
scrollbar-track-color:#eeeeee;/*背景颜色*/
}
</style>

View File

@ -0,0 +1,126 @@
<template>
<div v-show="dialogVisible" class="chat-popup">
<div class="chat-setting-header">
<div class="chat-setting-title">设置</div>
<div class="chat-setting-close">
<i class="el-icon-close" @click="dialogVisible=false" />
</div>
</div>
<div class="chat-setting-content">
<div class="chat-setting-language">
<div class="setting-language-title">语言: </div>
<el-switch
v-model="form.language"
class="setting-language-select"
active-color="#409EFF"
inactive-color="#ff4949"
active-text="中"
inactive-text="En"
active-value="zh"
inactive-value="en"
@change="changeLanguage()"
/>
</div>
<div class="chat-setting-sex">
<div class="setting-sex-title">性别: </div>
<el-switch
v-model="form.sex"
class="setting-sex-select"
active-color="#409EFF"
inactive-color="#ff4949"
active-icon-class="el-icon-male"
inactive-icon-class="el-icon-female"
active-value="1"
inactive-value="0"
@change="changeSex()"
/>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ChatSetting',
props:{
form:{
type:Object,
required:true
}
},
data() {
return {
dialogVisible: false,
loading:false
};
},
methods:{
doShow() {
this.dialogVisible = true;
},
doClose() {
this.dialogVisible = false;
},
changeLanguage() {
this.$emit('setSetting', this.form);
},
changeSex() {
this.$emit('setSetting', this.form);
}
}
};
</script>
<style lang="scss" scoped>
.chat-popup{
position: absolute;
width: 54%;
height: 143px;
border: 1px #dedede solid;
left: 33%;
top: 24%;
z-index: 7;
border-radius: 4px;
-webkit-box-shadow: 3px 3px 3px #dedede;
box-shadow: 3px 3px 3px #dedede;
background: #fff;
}
.chat-setting-header{
padding-left: 10px;
padding-top: 6px;
font-size: 14px;
border-bottom: 1px #dedede solid;
padding-bottom: 6px;
}
.chat-setting-title{
display: inline-block;
}
.chat-setting-close{
float: right;
display: inline-block;
margin-right: 5px;
font-size: 16px;
cursor: pointer;
}
.chat-setting-content{
}
.chat-setting-language,.chat-setting-sex{
display: inline-block;
margin-top: 20px;
}
.setting-language-title,.setting-sex-title{
display: inline-block;
font-size: 14px;
margin-left: 20px;
vertical-align: top;
margin-top: 3px;
}
.setting-language-select,.setting-sex-select{
display: inline-block;
vertical-align: top;
}
</style>
<style lang="scss">
.setting-sex-select .el-icon-male,.setting-sex-select .el-icon-female{
font-size:18px !important;
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<div v-show="dialogVisible" class="chatTooltipAll">
<div class="chatTooltip">
<div class="chatTooltipHeader">
{{ userName }} 邀请您加入会话
</div>
<div class="chatTooltipBootom">
<div class="create-group-bottom">
<el-button :loading="loading" size="small" type="primary" @click="doCreate">接受</el-button>
<el-button size="small" @click="doClose">拒绝</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import {acceptConversitionInvite} from '@/api/chat';
export default {
name:'ChatTooltip',
props: {
group: {
type: String,
required: true
},
simulationUsers: {
type: Object,
required: true
}
},
data() {
return {
userName:'',
dialogVisible:false,
loading:false,
conversationId:''
};
},
watch:{
'$store.state.socket.inviteSimulationConversition':function(val) {
this.userName = this.coverName(val);
this.dialogVisible = true;
this.conversationId = val.id;
}
},
methods:{
coverName(inviteUser) {
const member = this.$store.state.training.memberData[inviteUser.creatorId];
if (member.userId) {
const user = this.simulationUsers[member.userId];
return member.label + '(' + user.nickName + ')';
} else {
return member.label;
}
},
doCreate() {
this.loading = true;
acceptConversitionInvite(this.group, this.conversationId).then(res=>{
this.loading = false;
this.dialogVisible = false;
this.$emit('acceptInvite', res.data);
}).catch(error=>{
this.$messageBox('接受邀请失败: ' + error.message);
});
},
doClose() {
this.dialogVisible = false;
}
}
};
</script>
<style lang="scss" scoped>
.chatTooltip{
position: absolute;
width: 290px;
left: 32%;
top: 42%;
z-index: 5;
background: #fff;
padding: 15px;
box-shadow: #969090 0px 0px 10px;
border-radius: 4px;
line-height: 20px;
transform: translateY(-50%);
}
.chatTooltipHeader{
margin-top:10px;
font-size:14px;
}
.chatTooltipBootom{
margin-top:10px;
text-align: center;
margin-bottom:10px;
}
.chatTooltipAll{
position:absolute;
width:100%;
height:100%;
left:0;
top:0;
z-index: 10;
}
</style>

View File

@ -81,7 +81,6 @@ export default {
async simulationError() {
await this.$store.dispatch('map/clearJlmapTrainView');
await this.$store.dispatch('map/setTrainWindowShow', false);
await this.$store.dispatch('socket/setSimulationError');
await this.$store.dispatch('training/setMapDefaultState');
this.clearSubscribe();
this.$confirm(this.$t('tip.getMapStateDataException'), this.$t('tip.hint'), {

View File

@ -34,7 +34,10 @@ export default {
{label: '信号机', value:'SIGNAL'},
{label: '屏蔽门', value: 'PSD'},
{label: 'IBP盘', value: 'IBP'},
{label: '车站', value: 'LW'}
{label: '车站', value: 'LW'},
{label: '教员机', value: 'IM'},
{label: '行调工作站', value: 'CW'},
{label: '综合监控', value: 'ISCS'}
],
projectList: [{label:'西铁院', value: 'XTY'}, {label: '贵州装备', value:'GZB'}],
gatewayList: []

View File

@ -11,12 +11,10 @@
/>
</el-select>
</el-form-item>
</el-form>
<el-form v-show="data.type === 'LW'" ref="formLw" :model="formLw" label-width="100px" :rules="rulesLw">
<el-form-item label="下辖IBP:" prop="ibpCodeList">
<el-select v-model="formLw.ibpCodeList" placeholder="请选择" multiple size="small">
<el-form-item label="现地工作站:" prop="lwCode" size="small">
<el-select v-model="formIbp.lwCode" placeholder="请选择" size="small">
<el-option
v-for="item in ibpList"
v-for="item in lwList"
:key="item.code"
:label="item.code"
:value="item.code"
@ -24,6 +22,28 @@
</el-select>
</el-form-item>
</el-form>
<el-form v-show="data.type === 'LW'" ref="formLw" :model="formLw" label-width="100px" :rules="rulesLw">
<el-form-item label="关联地图:" prop="mapId">
<el-select v-model="formLw.mapId" placeholder="请选择" size="small" @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="formLw.stationCode" placeholder="请选择" size="small">
<el-option
v-for="item in stationList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
@ -34,6 +54,7 @@
<script>
import { getDeviceDetail, setIbpConfig, setLwConfig, getDevicesByType } from '@/api/project';
import { getAllMapOnline, getStationListNeedAttendant } from '@/api/jmap/map';
export default {
name: 'EditConfig',
@ -47,24 +68,31 @@ export default {
return {
dialogVisible: false,
data: {},
ibpList: [],
mapList: [],
lwList: [],
formIbp: {
part: ''
part: '',
lwCode: ''
},
formLw: {
ibpCodeList: []
mapId: '',
stationCode: ''
},
rulesIbp: {
part: [
{ required: true, message: '请选择显示位置', trigger: 'change' }
],
lwCode: [
{ required: true, message: '请选择归属车站', trigger: 'change'}
]
},
rulesLw: {
ibpCodeList: [
{ required: true, message: '请选择下辖ibp设备', trigger: 'change'}
stationCode: [
{ required: true, message: '请选择关联车站', trigger: 'change'}
]
},
partList: [{label: '左', value: 'LEFT'}, {label: '右', value: 'RIGHT'}, {label: '全部', value: 'WHOLE'}]
partList: [{label: '左', value: 'LEFT'}, {label: '右', value: 'RIGHT'}, {label: '全部', value: 'WHOLE'}],
stationList: []
};
},
computed: {
@ -80,7 +108,6 @@ export default {
} else if (resp.data.config && resp.data.type === 'LW') {
this.formLw = JSON.parse(resp.data.config);
}
console.log(this.formIbp, this.formLw);
}).catch(()=> {
this.$message.error('获取项目设备详情失败!');
});
@ -89,21 +116,36 @@ export default {
this.initData(row);
this.dialogVisible = true;
this.data = row;
if (row.type === 'LW') {
getDevicesByType('IBP').then(res => {
this.mapList = [];
this.stationList = [];
if (this.data.type === 'IBP') {
getDevicesByType('LW').then(res => {
if (res.data && res.data.length) {
this.ibpList = res.data;
this.lwList = res.data;
}
}).catch(() => {
this.$message.error('获取设备列表失败!');
});
} else {
getAllMapOnline().then(res => {
if (res.data && res.data.length) {
this.mapList = res.data;
this.formLw.mapId = this.mapList[0].id;
this.formIbp.mapId = this.mapList[0].id;
this.mapIdChange(this.mapList[0].id);
}
}).catch(() => {
this.$message.error('获取地图列表失败!');
});
}
},
doSave() {
const self = this;
console.log(this.data.type);
if (this.data.type === 'IBP') {
this.$refs.formIbp.validate(() => {
setIbpConfig(this.data.id, this.formIbp).then(response => {
self.$message.success('设置设备网关映射配置成功');
self.$message.success('设置IBP设备配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {
@ -113,7 +155,7 @@ export default {
} else if (this.data.type === 'LW') {
this.$refs.formLw.validate(() => {
setLwConfig(this.data.id, this.formLw).then(response => {
self.$message.success('设置设备网关映射配置成功');
self.$message.success('设置现地工作站配置成功');
self.handleClose();
self.$emit('reloadTable');
}).catch(error => {
@ -122,15 +164,24 @@ export default {
});
}
},
handleClose(done) {
handleClose() {
this.dialogVisible = false;
this.data = {};
this.formIbp = {
part: ''
};
this.formLw = {
ibpCodeList: []
};
this.$refs.formIbp.resetFields();
this.$refs.formLw.resetFields();
},
mapIdChange(mapId) {
if (mapId) {
getStationListNeedAttendant(mapId).then(resp => {
if (resp.data && resp.data.length) {
this.stationList = resp.data;
}
}).catch(() => {
this.$message.error('获取车站列表失败');
});
} else {
this.stationList = [];
}
}
}
};

View File

@ -34,7 +34,10 @@ export default {
{label: '信号机', value:'SIGNAL'},
{label: '屏蔽门', value: 'PSD'},
{label: 'IBP盘', value: 'IBP'},
{label: '车站', value: 'LW'}
{label: '现地工作站', value: 'LW'},
{label: '教员机', value: 'IM'},
{label: '行调工作站', value: 'CW'},
{label: '综合监控', value: 'ISCS'}
],
projectList: [{label:'西铁院', value: 'XTY'}, {label: '贵州装备', value:'GZB'}],
projectMap: {
@ -113,7 +116,7 @@ export default {
{
name: '登录路径',
handleClick: this.getPath,
showControl: (row) => { return row.type === 'LW' || row.type === 'IBP'; }
showControl: (row) => { return row.type !== 'SWITCH' && row.type !== 'SIGNAL' && row.type !== 'PSD'; }
}
]
}
@ -184,8 +187,10 @@ export default {
editConfig(index, row) {
if (row.type === 'LW' || row.type === 'IBP') {
this.$refs.editConfig.doShow(row);
} else {
} else if (row.type === 'SWITCH' || row.type === 'SIGNAL' || row.type === 'PSD') {
this.$refs.editConfigGateway.doShow(row);
} else {
this.$messageBox('暂无配置内容');
}
},
reloadTable() {

View File

@ -7,8 +7,7 @@
<script>
import PopMenu from '@/components/PopMenu';
import { DeviceMenu } from '@/scripts/ConstDic';
import { putJointTrainingUserkicked } from '@/api/chat';
import { putJointTrainingUserkickedNew} from '@/api/jointTraining';
import { kickOutMember } from '@/api/jointSimulation';
export default {
components: {
@ -18,14 +17,18 @@ export default {
clickUserId: {
type: String,
default: ''
},
menuDisabled: {
type: Boolean,
default: false
}
},
data() {
return {
menu: [{
label: this.$t('trainRoom.kickOutTheRoom'),
handler: this.kicked
}]
// menu: [{
// label: this.$t('trainRoom.kickOutTheRoom'),
// handler: this.kicked
// }]
};
},
computed: {
@ -37,6 +40,13 @@ export default {
},
drawWay() {
return this.$route.query.drawWay + '';
},
menu() {
return [{
label: this.$t('trainRoom.kickOutTheRoom'),
handler: this.kicked,
disabled: this.menuDisabled
}];
}
},
watch: {
@ -73,11 +83,7 @@ export default {
},
async kicked() {
try {
if (this.drawWay === 'true' ) {
await putJointTrainingUserkickedNew(this.clickUserId, this.$route.query.group);
} else {
await putJointTrainingUserkicked(this.clickUserId, this.$route.query.group);
}
await kickOutMember(this.$route.query.group, this.clickUserId);
} catch (error) {
console.error(error);
}

View File

@ -16,13 +16,13 @@
@node-contextmenu="handleShowContextMenu"
>
<span slot-scope="{ node, data }">
<span v-if="node.data.inRoom" style="color: green;">{{ data.nickName }}</span>
<span v-else style="color: #ccc;">{{ data.nickName }}</span>
<span v-if="node.data.online" style="color: green;">{{ data.nickName + (data.admin? '管理员':'') + (data.referee? '裁判员':'') + (data.deviceVO? ` -- (${data.deviceVO.code})`:'') }}</span>
<span v-else style="color: #ccc;">{{ data.nickName + (data.admin? '【管理员】':'') + (data.referee? '【裁判员】':'') + (data.deviceVO? ` -- (${data.deviceVO.code})`:'') }}</span>
</span>
</el-tree>
</el-scrollbar>
</div>
<content-menu ref="menu" :click-user-id="clickUserId" />
<content-menu ref="menu" :click-user-id="clickUserId" :menu-disabled="menuDisabled" />
</div>
</template>
@ -46,12 +46,19 @@ export default {
height: {
type: Number,
required: true
},
isAdmin: {
type: Boolean,
default() {
return false;
}
}
},
data() {
return {
filterText: '',
clickUserId: ''
clickUserId: '',
menuDisabled: false
};
},
computed: {
@ -79,9 +86,9 @@ export default {
x: e.clientX,
y: e.clientY
};
if (this.userId == this.room.creatorId) {
this.clickUserId = `${obj.id || ''}`;
if (this.isAdmin) {
this.clickUserId = `${obj.userId || ''}`;
this.menuDisabled = !!obj.deviceVO;
this.$store.dispatch('menuOperation/setPopMenu', { position, menu: DeviceMenu.JointRoom });
}
}