Merge remote-tracking branch 'origin/test'

This commit is contained in:
joylink_fanyuhong 2024-03-12 10:34:45 +08:00
commit fdaf9d81f8
26 changed files with 781 additions and 85 deletions

View File

@ -19,6 +19,8 @@
},
"dependencies": {
"@stomp/stompjs": "^5.4.4",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^1.0.2",
"axios": "^0.18.0",
"dayjs": "^1.11.5",
"echarts": "^4.7.0",
@ -44,6 +46,7 @@
"vue-i18n": "^8.12.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.1.6",
"vue-video-player": "^5.0.1",
"vuedraggable": "^2.24.3",
"vuex": "^3.1.0",
"wangeditor": "^4.6.17",

View File

@ -332,6 +332,31 @@ export function publishContextSence(data) {
});
}
/**
* @param {Object} data
* @param {String} data.name 场景名称
* @param {String} data.type Video=视频
* @param {Object} data.scene 大赛场景
* @param {String} data.scene.url 地址
* @param {String} data.scene.fileName 文件名
*/
export function saveSceneVideo(data) {
return request({
url: `/api/exercise/race/scene/custom/edit`,
method: 'post',
data
});
}
/** 场景视频编辑 */
export function editSceneVideo(sceneId, data) {
return request({
url: `/api/exercise/race/scene/custom/${sceneId}/edit`,
method: 'post',
data
});
}
/**
* @param {String} paperId 试卷id
* @param {String} moduleId 模块id

View File

@ -28,6 +28,11 @@ import '@/directive/verticalDrag/index.js';
import '@/directive/waves/index.js';
import messages from '@/i18n/index';
import VideoPlayer from 'vue-video-player/src';
import 'vue-video-player/src/custom-theme.css';
import 'video.js/dist/video-js.css';
Vue.use(VideoPlayer);
Vue.use(ElementUI);
Vue.use(VueI18n);
Vue.config.devtools = true; // 开发环境显示vue控制台

View File

@ -205,7 +205,8 @@ export default {
{ label: '站台PIS', value: 'PIS_STAND' },
{ label: '列车PIS', value: 'PIS_TRAIN' },
{ label: '乘客PIS', value: 'PIS' },
{ label: 'TMS', value: 'TMS' }
{ label: 'TMS', value: 'TMS' },
{ label: 'PA', value: 'PA' }
],
responderTypeList: [{ name: '固定应答器', value: 'FB' }, { name: '可变应答器', value: 'VB' }, { name: '填充应答器', value: 'IB' }],
loadRuleList: [

View File

@ -407,7 +407,8 @@ export const ClientList = [
{ label: '运行图预览', value: 'diagramPreview' },
{ label: '运行图编制', value: 'diagramEdit' },
{ label: '乘客信息发布系统', value: 'pisScreen' },
{ label: 'TMS', value: 'tms' }
{ label: 'TMS', value: 'tms' },
{ label: 'PA', value: 'paScreen' }
];
/** 实训类型list */
export const TrainingTypeList = [

View File

@ -1,4 +1,4 @@
import { objectIsEqual } from '@/utils/date';
import { objectIsEqualSp } from '@/utils/date';
import Handler from './newHandler.js';
import { ScriptMode } from '@/scripts/ConstDic';
import store from '@/store/index';
@ -50,9 +50,9 @@ class ValidateHandler {
}
}
if (linkDataFlag) {
return objectIsEqual(param1, param2) || objectIsEqual(linkParam, param2);
return objectIsEqualSp(param1, param2) || objectIsEqualSp(linkParam, param2);
} else {
return objectIsEqual(param1, param2);
return objectIsEqualSp(param1, param2);
}
}
// 判断实训操作正确性

View File

@ -882,7 +882,7 @@ const map = {
if (station.ciStation) {
const centrailzedList = [station.code];
state.stationControlMap[station.code] = centrailzedList;
station.relStationCodeList.forEach(relStationCode => {
station.relStationCodeList && station.relStationCodeList.forEach(relStationCode => {
state.stationControlMap[relStationCode] = centrailzedList;
if (state.mapDevice[relStationCode].centralized && !centrailzedList.includes(relStationCode)) {
centrailzedList.push(relStationCode);

View File

@ -59,9 +59,12 @@ export function handlerUrl() {
OSS_URL = 'https://192.168.53.10/oss-rtss';
} else if (process.env.NODE_ENV === 'production') {
// 远程发布分支
BASE_API = 'https://joylink.club/jlcloud';
BASE_SITE = 'https://joylink.club/cbtc';
OSS_URL = 'https://joylink.club/oss-rtss';
// BASE_API = 'https://joylink.club/jlcloud';
// BASE_SITE = 'https://joylink.club/cbtc';
// OSS_URL = 'https://joylink.club/oss-rtss';
BASE_API = 'http://10.30.1.21/rtss-server';
BASE_SITE = 'http://10.30.1.21';
OSS_URL = 'https://10.30.1.21/oss-rtss';
}
// VOICE_API, UPLOAD_API, BASE_SITE, PROD_API
const PROD_API = 'https://joylink.club/jlcloud';

View File

@ -121,3 +121,44 @@ export function objectIsEqual(obj1, obj2) {
}
return true;
}
export function checkUndefinedOrNull(key) {
if (key === '' || key === undefined || key === null) {
return false;
}
return true;
}
export function checkTwo(k1, k2) {
console.log(checkUndefinedOrNull(k1), checkUndefinedOrNull(k2), '----', k1, k2);
return checkUndefinedOrNull(k1) || checkUndefinedOrNull(k2);
}
/* 对象是否相等(undefined和空字符串空对象空数组认为相同) */
export function objectIsEqualSp(obj1, obj2) {
if (!(obj1 instanceof Object)) {
return false;
} else if (!(obj2 instanceof Object)) {
return false;
}
// 仅过滤值为null的项
const arr1 = Object.keys(obj1).filter(key => { return obj1[key] != null; });
const arr2 = Object.keys(obj2).filter(key => { return obj2[key] != null; });
// if (arr1.length !== arr2.length) {
// return false;
// }
for (const key of arr1) {
const index = arr2.findIndex(item => item === key);
arr2.splice(index, 1);
if (obj1[key] instanceof Object && obj2[key] instanceof Object) {
if (!objectIsEqualSp(obj1[key], obj2[key])) {
return false;
}
} else if (obj1[key] !== obj2[key] && checkTwo(obj1[key], obj2[key])) {
return false;
}
}
for (const key of arr2) {
if (obj1[key] !== obj2[key] && checkTwo(obj1[key], obj2[key])) {
return false;
}
}
return true;
}

View File

@ -0,0 +1,123 @@
<template>
<el-dialog v-dialogDrag :title="sceneName" :visible.sync="dialogVisible" width="50%" :before-close="handleClose" center :close-on-click-modal="false">
<div>
<video-player
ref="videoPlayer"
:playsinline="false"
:options="playOptions"
@play="onPlayerPlay($event)"
@timeupdate="onPlayerTimeupdate($event)"
/>
</div>
</el-dialog>
</template>
<script>
import { getContextSenceDetail } from '@/api/contest';
export default {
data() {
return {
dialogVisible: false,
sceneName:'播放视频',
playedTime: '',
currentTime: 0,
maxTime: 0,
playOptions: {
height: '200px',
width: '100%',
playbackRates: [1.0],
autoplay: false,
muted: false,
loop: false,
preload: 'auto',
language: 'zh-CN',
aspectRatio: '16:9',
fluid: true,
sources: [
{
type: 'video/mp4',
src: ''
}
],
poster: '',
notSupportedMessage: '此视频暂无法播放,请稍后再试',
controlBar: {
currentTimeDisplay: true,
progressControl: true,
playbackRateMenuButton: true,
timeDivider: true,
durationDisplay: true,
remainingTimeDisplay: true,
fullscreenToggle: true
}
}
};
},
computed: {
urlPrefix() {
return this.$store.state.user.ossUrl;
}
},
methods: {
doShow(sceneId) {
getContextSenceDetail(sceneId).then((res) => {
this.dialogVisible = true;
this.playOptions.sources[0].src = `${this.urlPrefix}/${res.data.scene.url}`;
this.sceneName = res.data.name;
}).catch(error => {
this.$message.error(error.message);
});
},
handleClose() {
this.dialogVisible = false;
},
onPlayerPlay(player) {
let playTime = 0;
if (
Number(Math.floor(this.playedTime)) ===
Number(Math.floor(player.duration()))
) {
this.playedTime = 0;
playTime = 0;
} else if (
Number(Math.floor(player.currentTime())) !==
Number(Math.floor(this.playedTime))
) {
playTime = this.playedTime;
player.currentTime(playTime);
}
},
onPlayerPause(player) {
this.playedTime = player.currentTime();
},
onPlayerTimeupdate(player) {
const timeDisplay = player.currentTime();
if (timeDisplay - this.currentTime > 1) {
player.currentTime(this.currentTime > this.maxTime ? this.currentTime : this.maxTime);
}
this.currentTime = player.currentTime();
this.maxTime = this.currentTime > this.maxTime ? this.currentTime : this.maxTime;
}
}
};
</script>
<style lang="scss" scoped>
/deep/{
.el-dialog__title {
color:#fff;
}
.el-dialog__header{
background: linear-gradient(to bottom, #01468B, #00172E);
}
.el-dialog__body{
padding: 0 !important;
}
.video-js .vjs-big-play-button {
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%);
background-color: black;
}
}
</style>

View File

@ -44,12 +44,14 @@
</div>
<div style="text-align: center;margin-top: 15px;">
<el-button v-show="nowData.ruleId" v-loading="loading" type="primary" @click="showScoreRule">评分表</el-button>
<el-button v-show="nowData.sceneId" v-loading="loading" type="primary" @click="startTask">开始任务</el-button>
<el-button v-show="nowData.sceneId&&nowData.scenetype!=='Video'" v-loading="loading" type="primary" @click="startTask">开始任务</el-button>
<el-button v-show="nowData.sceneId&&nowData.scenetype=='Video'" type="primary" @click="playSceneVideo">播放视频</el-button>
<el-button v-loading="loading" type="primary" :disabled="nowKey === taskList.length-1" @click="nextTask">下一任务</el-button>
</div>
</el-card>
</el-col>
<score-rule ref="scoreRule" />
<play-Video ref="playVideo" />
</el-row>
</template>
@ -58,10 +60,12 @@ import { getTaskTree, getContextSenceDetail} from '@/api/contest';
import { createSimulationNoFunction } from '@/api/simulation';
import { getPublishMapInfo } from '@/api/jmap/map';
import ScoreRule from './scoreRule';
import PlayVideo from './PlayVideo';
export default {
name: 'ContestDetail',
components: {
ScoreRule
ScoreRule,
PlayVideo
},
data() {
return {
@ -145,6 +149,9 @@ export default {
this.nowKey++;
this.nowData = this.taskList[this.nowKey];
},
playSceneVideo() {
this.$refs.playVideo.doShow(this.nowData.sceneId);
},
startTask() {
this.loading = true;
try {

View File

@ -235,6 +235,14 @@ export default {
border: solid 1px #01468B;
}
/deep/{
table {
border-collapse: collapse;
border: 2px solid #fff;
}
td, th {
border: 1px solid #fff;
padding: 8px;
}
.el-tree-node__content{
background-color: transparent !important;
}

View File

@ -1,13 +1,18 @@
<template>
<div>
<query-list-page ref="user" :card-padding="10" :pager-config="pagerConfig" :query-form="queryForm" :query-list="queryList" />
<upload-Video ref="uploadVideo" @reloadTable="reloadTable" />
</div>
</template>
<script>
import { queryContestSencePaged, deleteContestSence } from '@/api/contest';
import UploadVideo from './UploadVideo';
export default {
name: 'ContestSeasonManage',
components: {
UploadVideo
},
data() {
return {
pagerConfig: {
@ -28,7 +33,7 @@ export default {
type: 'select',
label: '类 型',
config: {
data: [{label: '二维', value: 'Local'}, {label: '三维', value: 'Link'}]
data: [{label: '二维', value: 'Local'}, {label: '三维', value: 'Link'}, {label: '视频', value: 'Video'}]
}
}
}
@ -50,7 +55,15 @@ export default {
title: '类 型',
prop: 'type',
type: 'tag',
columnValue: (row) => { return row.type === 'Local' ? '二维' : '三维'; },
columnValue: (row) => {
if (row.type === 'Local') {
return '二维';
} else if (row.type === 'Link') {
return '三维';
} else {
return '视频';
}
},
tagType: (row) => { return ''; }
},
{
@ -72,10 +85,13 @@ export default {
title: '操 作',
width: '320',
buttons: [
// {
// name: '',
// handleClick: this.doEdit
// },
{
name: '编辑',
handleClick: this.doEdit,
showControl: row => {
return row.type == 'Video';
}
},
{
name: '删 除',
handleClick: this.doDelete,
@ -83,10 +99,10 @@ export default {
}
]
}
],
actions: [
{ text: '上 传', handler: this.doUpload }
]
// actions: [
// { text: ' ', handler: this.doCreate }
// ]
}
};
},
@ -94,11 +110,11 @@ export default {
reloadTable() {
this.queryList.reload();
},
doCreate() {
// this.$refs.addSeason.doShow();
doUpload() {
this.$refs.uploadVideo.doShow();
},
doEdit(row) {
// this.$refs.addSeason.doShow(row);
doEdit(index, row) {
this.$refs.uploadVideo.doShow(row.id);
},
doDelete(index, row) {
this.$confirm('该操作将删除竞赛场景,是否继续?', '提 示', {

View File

@ -0,0 +1,238 @@
<template>
<el-dialog v-dialogDrag :visible="show" width="500px" center :close-on-click-modal="false" title="上传视频" :before-close="doClose" destroy-on-close>
<div v-if="formData.id==''||formData.reUpLoad" class="wrapper">
<label v-show="showUpload" for="file">
<el-card shadow="hover" class="card">
<i class="el-icon-upload" />
</el-card>
</label>
<input id="file" ref="file" style="display: none;" type="file" @change="onUploadChange">
<div v-show="!showUpload" class="preview" @mouseenter="showDelete = true" @mouseleave="showDelete = false">
<el-card shadow="hover" class="card">
<div class="file-type">{{ fileType }}</div>
<div class="file-name">{{ formData.fileName }}</div>
<div v-show="showDelete" class="delete" @click="handleDelete">
<i class="el-icon-delete-solid" />
</div>
</el-card>
</div>
</div>
<el-form ref="form" :model="formData" inline :rules="rules">
<el-form-item label="场景名字" required prop="title">
<el-input v-model="formData.title" />
</el-form-item>
<el-form-item v-if="formData.id" label="是否重新上传" prop="reUpLoad">
<el-checkbox v-model="formData.reUpLoad" />
</el-form-item>
<el-form-item v-if="formData.id==''||formData.reUpLoad" label="文件名" required prop="fileName">
<el-input v-model="formData.fileName" />
</el-form-item>
</el-form>
<div v-if="!showUpload" class="path-display">
<span>文件存储路径: </span>
<code>{{ `${urlPrefix}/${formData.directory}/${formData.fileName}` }}</code>
</div>
<footer>
<el-button v-if="formData.id==''" type="primary" size="small" @click="handleUpload">上传</el-button>
<el-button v-if="formData.id" type="primary" size="small" @click="doSave">确定</el-button>
<el-button size="small" @click="doClose">取消</el-button>
</footer>
</el-dialog>
</template>
<script>
import { getUploadUrl } from '@/api/projectConfig';
import { checkIsExist } from '@/api/management/fileManage';
import { saveSceneVideo, getContextSenceDetail, editSceneVideo } from '@/api/contest';
export default {
name: 'UploadVideo',
data() {
return {
show: false,
showUpload: true,
showDelete: false,
fileType: '',
formData: {
id:'',
reUpLoad:false,
directory: 'Video',
title: '',
fileName: ''
},
rules: {
title: [{ required: true, message: '请输入场景名字', trigger: 'blur' }],
fileName: [{ required: true, message: '请输入文件名', trigger: 'blur' }]
}
};
},
computed: {
urlPrefix() {
return this.$store.state.user.ossUrl;
}
},
methods: {
doShow(sceneId) {
this.show = true;
if (sceneId) {
getContextSenceDetail(sceneId).then((res) => {
this.formData.id = res.data.id;
this.formData.title = res.data.name;
this.formData.fileName = res.data.scene.fileName;
}).catch(error => {
this.$message.error(error.message);
});
}
},
doClose() {
this.show = false;
this.handleDelete();
},
onUploadChange(e) {
const fileList = e.target.files;
if (!fileList.length) return;
this.showUpload = false;
const fileName = fileList[0].name;
this.formData.fileName = fileName;
const devideIndex = fileName.lastIndexOf('.');
this.formData.title = fileName.slice(0, devideIndex);
this.fileType = fileList[0].type.split('/').pop();
},
doSave() {
const data = {name:this.formData.title, type:this.formData.directory,
scene:{url:`${this.formData.directory}/${this.formData.fileName}`, fileName:this.formData.fileName}};
if (!this.formData.reUpLoad) {
editSceneVideo(this.formData.id, data).then((res) => {
this.$message.success('编辑成功');
this.doClose();
this.$emit('reloadTable');
}).catch(error => {
this.$message.error(error.message);
});
} else {
this.handleUpload();
}
},
handleUpload() {
const form = this.$refs.form;
const file = this.$refs.file.files[0];
const params = {
directory: this.formData.directory,
fileName: this.formData.fileName
};
const execUpload = () => {
getUploadUrl({ ...params, method: 'PUT' }).then(res => {
const url = res.data;
const xhr = new XMLHttpRequest();
xhr.open('PUT', url);
xhr.upload.onload = () => {
const data = {name:this.formData.title, type:this.formData.directory,
scene:{url:`${this.formData.directory}/${this.formData.fileName}`, fileName:this.formData.fileName}};
if (!this.formData.id) {
saveSceneVideo(data).then(res => {
this.$message.success('上传成功');
this.doClose();
this.$emit('reloadTable');
});
} else {
editSceneVideo(this.formData.id, data).then((res) => {
this.$message.success('编辑且重新上传成功');
this.doClose();
this.$emit('reloadTable');
}).catch(error => {
this.$message.error(error.message);
});
}
};
xhr.send(file);
});
};
form.validate().then(valid => {
if (valid && file.size > 0) {
checkIsExist(params).then(resp => {
if (!resp.data) {
execUpload();
} else {
this.$confirm('该目录下有同名文件, 是否覆盖?', this.$t('global.tips'), {
confirmButtonText: this.$t('global.confirm'),
cancelButtonText: this.$t('global.cancel'),
type: 'warning'
}).then(execUpload);
}
});
}
});
},
handleDelete() {
if (this.formData.id == '' || this.formData.reUpLoad) {
this.$refs.file.value = '';
}
this.showUpload = true;
this.formData.id = '';
this.formData.reUpLoad = false;
this.formData.title = '';
this.formData.fileName = '';
this.formData.directory = '';
this.fileType = '';
}
}
};
</script>
<style lang="scss" scoped>
footer {
display: flex;
justify-content: space-evenly;
margin-top: 20px;
}
.block {
user-select: none;
padding: 5px;
color: #909399;
}
.wrapper {
display: flex;
justify-content: center;
margin-bottom: 20px;
.card {
display: flex;
justify-content: center;
align-items: center;
position: relative;
color: #909399;
cursor: pointer;
width: 150px;
height: 150px;
.el-icon-upload {
font-size: 4em;
}
.file-type {
text-align: center;
font-size: 4rem;
line-height: 6rem;
}
.file-name {
line-height: 1.2em;
text-align: center;
}
.delete {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0;
left: 0%;
width: 100%;
height: 100%;
background-color: #000000;
opacity: 0.5;
transition-duration: 1s;
transition-property: all;
font-size: 3em;
}
}
}
.path-display {
margin-top: 10px;
}
</style>

View File

@ -1,15 +1,20 @@
<template>
<el-dialog v-dialogDrag v-loading="loading" title="编辑赛季内容" :visible.sync="dialogVisible" width="80%" :before-close="handleClose" center :close-on-click-modal="false">
<quill-editor
:ref="'contentInput'"
v-model="seasonContent"
style="width: 80%;margin-left: 10%;margin-top: 10px;"
:margin-bottom="20"
editor-type="default"
:no-handle-p="true"
:height="450"
placeholder="请输入"
<el-dialog v-dialogDrag v-loading="loading" destroy-on-close title="编辑赛季内容" :visible.sync="dialogVisible" width="80%" :before-close="handleClose" center :close-on-click-modal="false">
<div style="border: 1px solid #ccc;">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:default-config="toolbarConfig"
:mode="mode"
/>
<Editor
v-model="seasonContent"
style="height: 500px; overflow-y: hidden;"
:default-config="editorConfig"
:mode="mode"
@onCreated="onCreated"
/>
</div>
<span slot="footer" class="dialog-footer">
<el-button v-loading="loading" type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
<el-button @click="handleClose">{{ $t('global.cancel') }}</el-button>
@ -18,21 +23,33 @@
</template>
<script>
import { editSeasonContent, getSeasonContent } from '@/api/contest';
import QuillEditor from '@/components/QuillEditor/index';
// import QuillEditor from '@/components/QuillEditor/index';
import '@wangeditor/editor/dist/css/style.css';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
export default {
name: 'EditContent',
components: {
QuillEditor
},
components: { Editor, Toolbar },
data() {
return {
dialogVisible: false,
seasonContent:'',
id: '',
loading: false
loading: false,
editor: null,
toolbarConfig: { },
editorConfig: { placeholder: '请输入内容...' },
mode: 'default' // or 'simple'
};
},
beforeDestroy() {
const editor = this.editor;
if (editor == null) return;
editor.destroy(); //
},
methods:{
onCreated(editor) {
this.editor = Object.seal(editor); // Object.seal()
},
doShow(row) {
this.dialogVisible = true;
if (row) {

View File

@ -305,7 +305,18 @@ export default {
iscsDeviceMap: {},
iscsDeviceList: [],
iscsDeviceState: {},
deviceMap: {},
deviceMap: {
LCD:{},
UP_STAND: {},
DOWN_STAND: {},
ADMINISTRATIVE_AREA: {},
GATE: {},
TRANSFER_CHANNEL: {},
PROPERTY: {},
OVERPASS1: {},
OVERPASS2: {},
LED: {}
},
timedList: []
};
},
@ -336,7 +347,7 @@ export default {
}
const device = this.iscsDeviceMap[item.code];
if (device) {
const oldState = parseInt(this.deviceMap[device.position].state);
const oldState = parseInt(this.deviceMap[device.position] ? this.deviceMap[device.position].state : 0);
const newState = parseInt(item.state);
const div = document.getElementById(device.position);
if (!oldState || oldState > newState) {
@ -479,13 +490,13 @@ export default {
audio.pause();
audio.src = this.$store.state.user.ossUrl + info.url;
audio.play();
const _that = this;
audio.addEventListener('ended', function() {
const device = _that.iscsDeviceMap[info.code];
const div = document.getElementById(device.position);
_that.$set(_that.deviceMap[device.position], 'state', '0');
div.style.background = '#CCCCCC';
}, false);
// const _that = this;
// audio.addEventListener('ended', function() {
// const device = _that.iscsDeviceMap[info.code];
// const div = document.getElementById(device.position);
// _that.$set(_that.deviceMap[device.position], 'state', '0');
// div.style.background = '#CCCCCC';
// }, false);
}
},
setTimerBroadcast() {
@ -601,10 +612,10 @@ export default {
type: 'BGM'
};
sendCommandNew(this.$route.query.group, 'ISCS_PA_Play', params).then(resp => {
// const bgmUrl = this.$store.state.user.resourcesUrl + this.bgmResources[0].url;
// const audio = document.getElementById('voice');
// audio.src = bgmUrl;
// audio.play();
const bgmUrl = this.$store.state.user.ossUrl + this.bgmResources[0].url;
const audio = document.getElementById('voice');
audio.src = bgmUrl;
audio.play();
}).catch(() => {
this.$message.error('背景音乐播放失败!');
});
@ -624,12 +635,12 @@ export default {
return;
}
sendCommandNew(this.$route.query.group, 'ISCS_PA_Stop_Playing', { iscsDeviceCodes: iscsDeviceCodes }).then(resp => {
positionList.forEach(elem => {
const audio = document.getElementById(elem.toLowerCase() + '_voice');
audio.pause();
});
const audio = document.getElementById('voice');
audio.pause();
// positionList.forEach(elem => {
// const audio = document.getElementById(elem.toLowerCase() + '_voice');
// audio.pause();
// });
// const audio = document.getElementById('voice');
// audio.pause();
}).catch(() => {
this.$message.error('背景音乐终止播放失败!');
});
@ -700,7 +711,7 @@ export default {
type: this.videoMode
};
sendCommandNew(this.$route.query.group, 'ISCS_PA_Play', params).then(resp => {
// this.voiceUrl = this.$store.state.user.resourcesUrl + this.resourcesList[this.messageIndex].url;
// this.voiceUrl = this.$store.state.user.ossUrl + this.resourcesList[this.messageIndex].url;
// const audio = document.getElementById('voice');
// audio.src = this.voiceUrl;
// audio.play();

View File

@ -346,6 +346,7 @@ export default {
});
this.selectChildren(this.buttonId);
}
this.$store.dispatch('app/animationsClose');
},
methods:{
changeStation(item) {

View File

@ -99,7 +99,7 @@ export default {
return this.$route.query.type;
},
syncLogin() {
const synchronousLogin = ['VR_IBP', 'LSW', 'CCTV', 'ISCS_LW', 'ISCS_CW', 'VR_PSD', 'SANDBOX', 'ILW', 'PIS_STAND', 'PIS_TRAIN', 'PIS', 'TMS'];
const synchronousLogin = ['VR_IBP', 'LSW', 'CCTV', 'ISCS_LW', 'ISCS_CW', 'VR_PSD', 'SANDBOX', 'ILW', 'PIS_STAND', 'PIS_TRAIN', 'PIS', 'TMS', 'PA'];
return this.type ? synchronousLogin.includes(this.type) : false;
},
bgImg() {
@ -146,7 +146,8 @@ export default {
PIS_STAND:{text:'检测教员机登录中'},
SANDBOX:{Img:bgLswImg, text:'检测教员机登录中'},
PIS:{text:'检测教员机登录中', Img: bgPisImg},
TMS:{text:'检测列车驾驶终端登录中', Img: bgTmsImg}
TMS:{text:'检测列车驾驶终端登录中', Img: bgTmsImg},
PA:{text:'检测现地工作站登录中', Img: bgPisImg}
};
this.loadingText = deviceMap[this.type].text;
this.deviceImg = deviceMap[this.type].Img;

View File

@ -39,7 +39,7 @@
<test-runplan v-if="picture=='testRunplan'" ref="testRunplan" :plan-id="loadPlanId" @pictureChange="pictureChangeAndPlan" />
<driver-ats-work v-if="picture=='driverAtsWork'" ref="driverAtsWork" />
<pis-screen v-if="picture=='pisScreen'" ref="pisScreen" />
<pa-screen v-if="picture =='paScreen'" ref="paScreen" />
<terminal-menu
v-show="menuShow"
ref="terminalMenu"
@ -92,6 +92,7 @@ import NccWork from './nccWork';
import LineMonitor from './lineMonitor';
import PisScreen from './pisScreen';
import TmsPage from '@/views/jlmap3d/drive/sceneview/tmsPage';
import PaScreen from './paScreen';
export default {
name: 'Index',
@ -132,7 +133,8 @@ export default {
NccWork,
LineMonitor,
PisScreen,
TmsPage
TmsPage,
PaScreen
},
data() {
return {

View File

@ -0,0 +1,183 @@
<template>
<div class="content-box-station">
<div class="station-nav-out">
<div class="station-nav">
<div class="stationList">
<div class="station-line" />
<div v-for="(item, index) in stationList" :key="index" class="station-box-out">
<div class="station-box">
<div class="leftRect" />
<div class="rightRect" />
<div class="station-list-box" :class="{'active': selectStation == item.id,'currentStation':tractionList.includes(item.name)}" @click="changeStation(item.id)" />
</div>
<div class="station-name" :class="index==0?'station-name-first':index%2==1?'station-name-up':'station-name-down'">{{ item.name }}</div>
</div>
</div>
</div>
</div>
<station-home ref="stationHome" :station-id="selectStation"/>
</div>
</template>
<script>
import StationHome from '../../../iscs/iscsSystemNew/config/broadcast/stationHome';
import { getByGroupStationList } from '@/api/jmap/map';
export default {
name: 'PaScreen',
components: {
StationHome
},
data() {
return {
selectStation: '',
stationList:[],
tractionList:[]
};
},
async created () {
// 线
const res = await getByGroupStationList(this.$route.query.group);
if (res.code == 200) {
this.stationList = [];
res.data.forEach(station => {
if (!station.depot && station.visible) {
const param = {
name: station.runPlanName.includes('站') ? station.runPlanName : `${station.runPlanName}`,
id: station.code
};
if (station.centralized) {
this.tractionList.push(param.name);
}
this.stationList.push(param);
}
});
this.selectStation = this.$store.state.training.roleDeviceCode;
}
this.$store.dispatch('app/animationsClose');
},
methods: {
changeStation(item) {
this.selectStation = item;
}
}
};
</script>
<style lang="scss" scoped>
.content-box-station{
width: 100%;
height: 100%;
padding: 65px 0 30px 0;
background: #45607B;
}
.station-nav-out{
position: absolute;
left: 0;
top: 0;
width: 100%;
}
.station-nav{
width: 100%;
height: 65px;
background-color: #ACACAC;
position: relative;
padding-left: 5px;
}
.station-line{
height: 12px;
width: 100%;
position: absolute;
background-image: linear-gradient(to bottom , #9c9c9c, #F0F0F0,#9c9c9c);
top: 25px;
border: 1px #505050 solid;
}
.station-list-box{
width: 1vw;
height: 1vw;
border-radius: 1vw;
background: #ccc;
left: 4px;
top: 50%;
position: absolute;
border-left: 1px #fdfdfd solid;
border-right: 1px #262626 solid;
transform: translateY(-50%);
}
.station-list-box.currentStation::before{
content: '';
width: 128%;
height: 124%;
border: 1px #10ff00 solid;
position: absolute;
left: -16%;
top: -10%;
border-radius: 130%;
}
.station-list-box.active,.station-list-button.active{
background:#cdcd37;
}
.station-name{
font-size:12px;
position:absolute;
}
.station-name-first{
transform: translateX(0%);
top: 45px;
white-space: nowrap;
left: 0%;
}
.station-name-up{
top: 5px;
transform: translateX(-50%);
left: 25%;
white-space: nowrap;
}
.station-name-down{
top: 45px;
// transform: translateX(-25%);
transform: translateX(-38%);
white-space: nowrap;
left: 0%;
}
.station-box-out{
height: 100%;
display: inline-block;
position: relative;
}
.station-box{
display: inline-block;
position: relative;
// margin-right: 1.8vw;
width: 1.5vw;
margin-top: 20px;
cursor: pointer;
}
.leftRect{
width: 6px;
height: 19px;
background-image: linear-gradient(to bottom, #686868, #e9e9e9, #686868);
border: 1px #585858 solid;
display: inline-block;
vertical-align: top;
}
.rightRect{
width: 6px;
height: 19px;
position: absolute;
margin-left: 0.8vw;
background-image: linear-gradient(to bottom, #686868, #e9e9e9, #686868);
border: 1px #585858 solid;
display: inline-block;
vertical-align: top;
}
.stationList{
// display: inline-block;
display: flex;
position: relative;
justify-content: space-between;
float: left;
height: 100%;
width: 100%;
}
</style>

View File

@ -69,7 +69,7 @@ export default {
} else {
this.initPictureShow();
}
} else if (!clientIdList || !clientIdList.length) {
} else if (clientIdList && clientIdList.length) {
this.initTerminalList(clientIdList);
if (this.$store.state.trainingNew.trainingDetail && this.$store.state.trainingNew.trainingDetail.client) {
const client = this.findTerminalFromMap(this.$store.state.trainingNew.trainingDetail.client);
@ -83,7 +83,11 @@ export default {
}
} else if (!this.terminalList.length) {
this.initTerminalList([]);
if (this.$route.query.client && !this.nowTerminal.id) {
this.changeQueryClient();
} else {
this.initPictureShow();
}
}
}
},

View File

@ -65,7 +65,8 @@ export default {
{ label: '轨道详览', key: 'troDetailWork' },
{ label: '通号端', key: 'maintainerSelect' },
{ label: '乘客信息发布系统', key: 'pisScreen' },
{ label: 'TMS', key: 'tms' }
{ label: 'TMS', key: 'tms' },
{ label: 'PA', value: 'paScreen' }
]
};
},

View File

@ -287,6 +287,11 @@ export default {
code: 'pisScreen',
isShow: () => type === 'METRO'
},
{
name: 'PA',
code: 'paScreen',
isShow: () => type === 'METRO'
},
{
name: '大屏',
code: 'bigScreen',

View File

@ -79,13 +79,13 @@ export default {
title: this.$t('lesson.trainingName'),
prop: 'name'
},
{
title: this.$t('lesson.prdType'),
prop: 'prdType',
type: 'tag',
columnValue: (row) => { return this.$convertField(row.prdType, this.prdTypeList, ['value', 'label']); },
tagType: (row) => { return 'success'; }
},
// {
// title: this.$t('lesson.prdType'),
// prop: 'prdType',
// type: 'tag',
// columnValue: (row) => { return this.$convertField(row.prdType, this.prdTypeList, ['value', 'label']); },
// tagType: (row) => { return 'success'; }
// },
{
title: this.$t('lesson.trainingType'),
prop: 'type',
@ -132,12 +132,12 @@ export default {
};
},
computed:{
prdTypeList() {
const productTypeList = ConstConfig.ConstSelect.prdType;
return Cookies.get('user_lang') == 'en'
? productTypeList.map(elem => { return { value: elem.value, label: elem.enlabel }; })
: productTypeList.map(elem => { return { value: elem.value, label: elem.label }; });
}
// prdTypeList() {
// const productTypeList = ConstConfig.ConstSelect.prdType;
// return Cookies.get('user_lang') == 'en'
// ? productTypeList.map(elem => { return { value: elem.value, label: elem.enlabel }; })
// : productTypeList.map(elem => { return { value: elem.value, label: elem.label }; });
// }
},
async created() {
await this.loadInitData();

View File

@ -88,7 +88,7 @@
</el-select>
</el-form-item>
</el-form>
<el-form v-show="['TMS', 'PIS'].includes(data.type)" ref="formTms" :model="formTms" label-width="100px" :rules="rulesTms">
<el-form v-show="['TMS', 'PIS', 'PA'].includes(data.type)" ref="formTms" :model="formTms" label-width="100px" :rules="rulesTms">
<el-form-item label="关联设备:" prop="deviceCode" size="small">
<el-select v-model="formTms.deviceCode" placeholder="请选择" size="small">
<el-option
@ -395,7 +395,7 @@ export default {
this.formIscs = {deviceCode: '', picture: '', stationCode: '', roleCode:'', client:'', clientList: []};
const form = JSON.parse(resp.data.config);
this.formIscs = Object.assign(this.formIscs, form);
} else if (resp.data.config && ['PIS', 'TMS'].includes(resp.data.type)) {
} else if (resp.data.config && ['PIS', 'TMS', 'PA'].includes(resp.data.type)) {
this.formTms = {deviceCode: '', roleCode:'', client:'', clientList: []};
const form = JSON.parse(resp.data.config);
this.formTms = Object.assign(this.formTms, form);
@ -408,7 +408,7 @@ export default {
this.initData(row);
this.data = row;
this.stationList = [];
if (['VR_IBP', 'ISCS_LW'].includes(this.data.type)) {
if (['VR_IBP', 'ISCS_LW', 'PA'].includes(this.data.type)) {
getDevicesByType(row.project, 'LW').then(res => {
if (res.data && res.data.length) {
this.lwList = res.data;
@ -511,7 +511,7 @@ export default {
self.$message.error(this.$t('tip.modifyTheFailure') + error.message);
});
});
} else if (this.data.type === 'PIS' || this.data.type === 'TMS') {
} else if (this.data.type === 'PIS' || this.data.type === 'TMS' || this.data.type === 'PA') {
this.$refs.formTms.validate(() => {
const data = {id: this.data.id, project: this.data.project, code: this.data.code, type: this.data.type, config: JSON.stringify(this.formTms) };
setDeviceConfig(data).then(response => {

View File

@ -188,7 +188,7 @@ export default {
},
editConfig(index, row) {
const configGatewayList = ['SWITCH', 'SIGNAL', 'PSD', 'PSL', 'PSC', 'UDP_LOW', 'SECTION', 'TRAIN', 'UDP_CLIENT', 'PIS_STAND', 'PIS_TRAIN', 'PIS'];
if (['LW', 'VR_IBP', 'ISCS_LW', 'ISCS_CW', 'IM', 'CW', 'DRIVE', 'DEPOT', 'TMS', 'PIS'].includes(row.type)) {
if (['LW', 'VR_IBP', 'ISCS_LW', 'ISCS_CW', 'IM', 'CW', 'DRIVE', 'DEPOT', 'TMS', 'PIS', 'PA'].includes(row.type)) {
this.$refs.editConfig.doShow(row);
} else if (configGatewayList.includes(row.type)) {
this.$refs.editConfigGateway.doShow(row);