feat: update simulation mode rate and camera views
This commit is contained in:
@@ -37,6 +37,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="simulationRateDialogVisible" class="simulation-rate-mask" @click.self="cancelSimulationRateDialog">
|
||||||
|
<div class="simulation-rate-dialog">
|
||||||
|
<div class="simulation-rate-dialog__head">
|
||||||
|
<strong>选择仿真播放倍率</strong>
|
||||||
|
<span>默认 5 倍</span>
|
||||||
|
</div>
|
||||||
|
<div class="simulation-rate-options">
|
||||||
|
<button
|
||||||
|
v-for="rate in autoPlayRates"
|
||||||
|
:key="rate"
|
||||||
|
type="button"
|
||||||
|
class="simulation-rate-option"
|
||||||
|
:class="{ 'simulation-rate-option--active': pendingAutoPlayRate === rate }"
|
||||||
|
@click="selectSimulationRate(rate)"
|
||||||
|
>
|
||||||
|
{{ rate }}x
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="simulation-rate-dialog__actions">
|
||||||
|
<button type="button" class="simulation-rate-action simulation-rate-action--ghost" @click="cancelSimulationRateDialog">取消</button>
|
||||||
|
<button type="button" class="simulation-rate-action simulation-rate-action--primary" @click="confirmSimulationRate">开始仿真</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="leftLine"></div>
|
<div class="leftLine"></div>
|
||||||
<div class="rightLine"></div>
|
<div class="rightLine"></div>
|
||||||
|
|
||||||
@@ -275,7 +299,12 @@ export default {
|
|||||||
currentMode: 'DT',
|
currentMode: 'DT',
|
||||||
srcDt: 'http://localhost:10056/',
|
srcDt: 'http://localhost:10056/',
|
||||||
srcSm: 'http://localhost:10059/',
|
srcSm: 'http://localhost:10059/',
|
||||||
|
smIframeBase: 'http://localhost:10059/',
|
||||||
autoPlayCraftCode: '',
|
autoPlayCraftCode: '',
|
||||||
|
autoPlayRates: [0.5, 1, 2, 4, 5, 10],
|
||||||
|
selectedAutoPlayRate: 5,
|
||||||
|
pendingAutoPlayRate: 5,
|
||||||
|
simulationRateDialogVisible: false,
|
||||||
modeSwitchTimer: null,
|
modeSwitchTimer: null,
|
||||||
cameraSyncTimer: null,
|
cameraSyncTimer: null,
|
||||||
iframeReadyTimer: null,
|
iframeReadyTimer: null,
|
||||||
@@ -283,38 +312,38 @@ export default {
|
|||||||
clockTimer: null,
|
clockTimer: null,
|
||||||
resizeHandler: null,
|
resizeHandler: null,
|
||||||
alarmPieChart: null,
|
alarmPieChart: null,
|
||||||
activeView: 'longRail',
|
activeView: 'overview',
|
||||||
viewButtons: [
|
viewButtons: [
|
||||||
|
{ label: '全揽视角', value: 'overview' },
|
||||||
{ label: '加工中心单元视角', value: 'longRail' },
|
{ label: '加工中心单元视角', value: 'longRail' },
|
||||||
{ label: '车床加工单元视角', value: 'shortRail' },
|
{ label: '车床加工单元视角', value: 'shortRail' },
|
||||||
{ label: '插齿机单元视角', value: 'joint' },
|
{ label: '插齿机单元视角', value: 'joint' },
|
||||||
{ label: '磨床加工单元视角', value: 'grinder' },
|
{ label: '磨床加工单元视角', value: 'grinder' }
|
||||||
{ label: '全揽视角', value: 'overview' }
|
|
||||||
],
|
],
|
||||||
cameraViews: {
|
cameraViews: {
|
||||||
longRail: {
|
longRail: {
|
||||||
target: { x: -5.725619423653396, y: 1.559219531820475, z: -5.23360272959924 },
|
target: { x: -7.242748313927699, y: 1.365235845234568, z: -6.193333867630938 },
|
||||||
position: { x: -18.7530206850084, y: 1.6376732214652037, z: 15.344064598520557 },
|
position: { x: -20.270149575282687, y: 1.4436895348793037, z: 14.38433346048873 },
|
||||||
zoom0: 1
|
zoom0: 1
|
||||||
},
|
},
|
||||||
shortRail: {
|
shortRail: {
|
||||||
target: { x: -5.814177085428968, y: 16.255194514605996, z: -5.3456965650308055 },
|
target: { x: -7.001588883043185, y: 16.262345352657395, z: -6.097455776264499 },
|
||||||
position: { x: -17.571406723801864, y: 16.32599896951042, z: 13.22564819859711 },
|
position: { x: -18.758818521416032, y: 16.33314980756182, z: 12.473888987363225 },
|
||||||
zoom0: 1
|
zoom0: 1
|
||||||
},
|
},
|
||||||
joint: {
|
joint: {
|
||||||
target: { x: 2.7622940494890424, y: 15.83905572715569, z: 0.08552052688719117 },
|
target: { x: 1.9482734060133915, y: 15.747678960743341, z: -0.429474906955281 },
|
||||||
position: { x: -4.6476929900921515, y: 15.883680193065107, z: 11.790099601955712 },
|
position: { x: -5.461713633567803, y: 15.792303426652754, z: 11.275104168113232 },
|
||||||
zoom0: 1
|
zoom0: 1
|
||||||
},
|
},
|
||||||
grinder: {
|
grinder: {
|
||||||
target: { x: -10.128808700176803, y: -15.480679803858136, z: 1.9651555238025413 },
|
target: { x: -10.691421929972085, y: -15.525894683054275, z: 1.3522782143982923 },
|
||||||
position: { x: -21.43448244172167, y: -15.531783203240701, z: 12.347383997813267 },
|
position: { x: -21.99709567151696, y: -15.576998082436841, z: 11.73450668840891 },
|
||||||
zoom0: 1
|
zoom0: 1
|
||||||
},
|
},
|
||||||
overview: {
|
overview: {
|
||||||
target: { x: -2.4540886878602937, y: -1.7690793306726371, z: -0.104103172990748 },
|
target: { x: -4.793874852627955, y: 6.052339186049304, z: -6.403726952169199 },
|
||||||
position: { x: -44.67609815729721, y: -1.5148097061598855, z: 38.669527626788486 },
|
position: { x: -26.23140973687205, y: 33.78061698752333, z: 24.44556028867285 },
|
||||||
zoom0: 1
|
zoom0: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -570,8 +599,11 @@ export default {
|
|||||||
const config = window.dt_Config || {}
|
const config = window.dt_Config || {}
|
||||||
this.iframeAddress = config.iframeAddress ? config.iframeAddress : ''
|
this.iframeAddress = config.iframeAddress ? config.iframeAddress : ''
|
||||||
this.autoPlayCraftCode = config.autoPlayCraftCode || 'E8077755-9B85-46A1-9B8A-85083C00DF26'
|
this.autoPlayCraftCode = config.autoPlayCraftCode || 'E8077755-9B85-46A1-9B8A-85083C00DF26'
|
||||||
|
this.smIframeBase = config.smIframe || this.srcSm
|
||||||
|
this.selectedAutoPlayRate = this.normalizeAutoPlayRate(config.autoPlayRate || this.getAutoPlayRateFromUrl(this.smIframeBase) || 5)
|
||||||
|
this.pendingAutoPlayRate = this.selectedAutoPlayRate
|
||||||
this.srcDt = this.buildIframeUrl(config.dtIframe || this.srcDt, this.autoPlayCraftCode)
|
this.srcDt = this.buildIframeUrl(config.dtIframe || this.srcDt, this.autoPlayCraftCode)
|
||||||
this.srcSm = this.buildIframeUrl(config.smIframe || this.srcSm, this.autoPlayCraftCode)
|
this.srcSm = this.buildIframeUrl(this.smIframeBase, this.autoPlayCraftCode, this.selectedAutoPlayRate)
|
||||||
this.titleText = config.titleText
|
this.titleText = config.titleText
|
||||||
this.updateTime()
|
this.updateTime()
|
||||||
this.setScale()
|
this.setScale()
|
||||||
@@ -637,17 +669,44 @@ export default {
|
|||||||
this.syncActiveCamera()
|
this.syncActiveCamera()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
buildIframeUrl(baseUrl, craftCode) {
|
buildIframeUrl(baseUrl, craftCode, autoPlayRate) {
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
let nextUrl = baseUrl
|
let nextUrl = baseUrl
|
||||||
|
if (nextUrl.includes('dmtmode=SM')) {
|
||||||
|
nextUrl = this.withAutoPlayRateParam(nextUrl, this.normalizeAutoPlayRate(autoPlayRate))
|
||||||
|
}
|
||||||
if (craftCode && nextUrl.includes('autoPlayCraftCode=') && !nextUrl.includes(craftCode)) {
|
if (craftCode && nextUrl.includes('autoPlayCraftCode=') && !nextUrl.includes(craftCode)) {
|
||||||
const separator = nextUrl.endsWith('=') || nextUrl.endsWith('/') ? '' : '/'
|
const separator = nextUrl.endsWith('=') || nextUrl.endsWith('/') ? '' : '/'
|
||||||
nextUrl = `${nextUrl}${separator}${craftCode}`
|
nextUrl = `${nextUrl}${separator}${craftCode}`
|
||||||
}
|
}
|
||||||
return this.withTransparentParam(nextUrl)
|
return this.withTransparentParam(nextUrl)
|
||||||
},
|
},
|
||||||
|
getAutoPlayRateFromUrl(url) {
|
||||||
|
const match = String(url || '').match(/[?&]autoPlayRate=([^&#]*)/)
|
||||||
|
return match ? decodeURIComponent(match[1]) : ''
|
||||||
|
},
|
||||||
|
normalizeAutoPlayRate(rate) {
|
||||||
|
const numericRate = Number(rate)
|
||||||
|
return this.autoPlayRates.includes(numericRate) ? numericRate : 5
|
||||||
|
},
|
||||||
|
withAutoPlayRateParam(url, rate) {
|
||||||
|
const value = encodeURIComponent(String(rate))
|
||||||
|
if (url.includes('autoPlayRate=')) {
|
||||||
|
return url.replace(/([?&]autoPlayRate=)[^&#]*/, `$1${value}`)
|
||||||
|
}
|
||||||
|
if (url.includes('autoPlayCraftCode=')) {
|
||||||
|
return url.replace(/([?&])autoPlayCraftCode=/, `$1autoPlayRate=${value}&autoPlayCraftCode=`)
|
||||||
|
}
|
||||||
|
const hashIndex = url.indexOf('#')
|
||||||
|
if (hashIndex > -1) {
|
||||||
|
const separator = url.slice(hashIndex).includes('?') ? '&' : '?'
|
||||||
|
return `${url}${separator}autoPlayRate=${value}`
|
||||||
|
}
|
||||||
|
const separator = url.includes('?') ? '&' : '?'
|
||||||
|
return `${url}${separator}autoPlayRate=${value}`
|
||||||
|
},
|
||||||
withTransparentParam(url) {
|
withTransparentParam(url) {
|
||||||
if (!url || url.includes('transparent=true')) {
|
if (!url || url.includes('transparent=true')) {
|
||||||
return url
|
return url
|
||||||
@@ -725,6 +784,22 @@ export default {
|
|||||||
this.switchMode('DT')
|
this.switchMode('DT')
|
||||||
},
|
},
|
||||||
changeSmMode() {
|
changeSmMode() {
|
||||||
|
this.openSimulationRateDialog()
|
||||||
|
},
|
||||||
|
openSimulationRateDialog() {
|
||||||
|
this.pendingAutoPlayRate = this.selectedAutoPlayRate
|
||||||
|
this.simulationRateDialogVisible = true
|
||||||
|
},
|
||||||
|
selectSimulationRate(rate) {
|
||||||
|
this.pendingAutoPlayRate = this.normalizeAutoPlayRate(rate)
|
||||||
|
},
|
||||||
|
cancelSimulationRateDialog() {
|
||||||
|
this.simulationRateDialogVisible = false
|
||||||
|
},
|
||||||
|
confirmSimulationRate() {
|
||||||
|
this.selectedAutoPlayRate = this.normalizeAutoPlayRate(this.pendingAutoPlayRate)
|
||||||
|
this.srcSm = this.buildIframeUrl(this.smIframeBase, this.autoPlayCraftCode, this.selectedAutoPlayRate)
|
||||||
|
this.simulationRateDialogVisible = false
|
||||||
this.switchMode('SM')
|
this.switchMode('SM')
|
||||||
},
|
},
|
||||||
initAlarmPieChart() {
|
initAlarmPieChart() {
|
||||||
@@ -1034,6 +1109,114 @@ body,
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.simulation-rate-mask {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 80;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgba(1, 9, 20, 0.58);
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-dialog {
|
||||||
|
width: 430px;
|
||||||
|
padding: 20px 22px 18px;
|
||||||
|
border: 1px solid rgba(114, 232, 255, 0.48);
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(19, 55, 82, 0.96), rgba(4, 16, 31, 0.96)),
|
||||||
|
rgba(5, 20, 44, 0.96);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.12),
|
||||||
|
inset 0 0 24px rgba(44, 143, 255, 0.18),
|
||||||
|
0 18px 42px rgba(0, 0, 0, 0.48),
|
||||||
|
0 0 28px rgba(114, 232, 255, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-dialog__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-dialog__head strong {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-shadow: 0 0 12px rgba(114, 232, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-dialog__head span {
|
||||||
|
color: #91dfff;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-options {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-option,
|
||||||
|
.simulation-rate-action {
|
||||||
|
height: 36px;
|
||||||
|
border: 1px solid rgba(111, 224, 255, 0.34);
|
||||||
|
color: #d8f6ff;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(24, 52, 82, 0.82), rgba(5, 17, 30, 0.9)),
|
||||||
|
rgba(6, 25, 53, 0.72);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-option--active {
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: rgba(128, 255, 230, 0.95);
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(36, 216, 139, 0.42), rgba(14, 92, 61, 0.7)),
|
||||||
|
rgba(14, 92, 61, 0.52);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.18),
|
||||||
|
0 0 18px rgba(36, 216, 139, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-dialog__actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-action {
|
||||||
|
min-width: 96px;
|
||||||
|
padding: 0 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-action--ghost {
|
||||||
|
color: #b9d8ec;
|
||||||
|
border-color: rgba(160, 180, 194, 0.24);
|
||||||
|
background: rgba(36, 48, 60, 0.48);
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-action--primary {
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: rgba(114, 232, 255, 0.72);
|
||||||
|
background:
|
||||||
|
linear-gradient(90deg, rgba(12, 62, 78, 0.96), rgba(26, 122, 132, 0.88), rgba(12, 62, 78, 0.96)),
|
||||||
|
rgba(4, 20, 35, 0.86);
|
||||||
|
box-shadow: 0 0 18px rgba(75, 245, 209, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
.simulation-rate-option:focus,
|
||||||
|
.simulation-rate-action:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
.brand-logo {
|
.brand-logo {
|
||||||
display: block;
|
display: block;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
|||||||
Reference in New Issue
Block a user