diff --git a/src/views/qingAn.vue b/src/views/qingAn.vue
index c9dcf2b..a3adfb5 100644
--- a/src/views/qingAn.vue
+++ b/src/views/qingAn.vue
@@ -37,6 +37,30 @@
+
+
+
+ 选择仿真播放倍率
+ 默认 5 倍
+
+
+
+
+
+
+
+
+
+
@@ -275,7 +299,12 @@ export default {
currentMode: 'DT',
srcDt: 'http://localhost:10056/',
srcSm: 'http://localhost:10059/',
+ smIframeBase: 'http://localhost:10059/',
autoPlayCraftCode: '',
+ autoPlayRates: [0.5, 1, 2, 4, 5, 10],
+ selectedAutoPlayRate: 5,
+ pendingAutoPlayRate: 5,
+ simulationRateDialogVisible: false,
modeSwitchTimer: null,
cameraSyncTimer: null,
iframeReadyTimer: null,
@@ -283,38 +312,38 @@ export default {
clockTimer: null,
resizeHandler: null,
alarmPieChart: null,
- activeView: 'longRail',
+ activeView: 'overview',
viewButtons: [
+ { label: '全揽视角', value: 'overview' },
{ label: '加工中心单元视角', value: 'longRail' },
{ label: '车床加工单元视角', value: 'shortRail' },
{ label: '插齿机单元视角', value: 'joint' },
- { label: '磨床加工单元视角', value: 'grinder' },
- { label: '全揽视角', value: 'overview' }
+ { label: '磨床加工单元视角', value: 'grinder' }
],
cameraViews: {
longRail: {
- target: { x: -5.725619423653396, y: 1.559219531820475, z: -5.23360272959924 },
- position: { x: -18.7530206850084, y: 1.6376732214652037, z: 15.344064598520557 },
+ target: { x: -7.242748313927699, y: 1.365235845234568, z: -6.193333867630938 },
+ position: { x: -20.270149575282687, y: 1.4436895348793037, z: 14.38433346048873 },
zoom0: 1
},
shortRail: {
- target: { x: -5.814177085428968, y: 16.255194514605996, z: -5.3456965650308055 },
- position: { x: -17.571406723801864, y: 16.32599896951042, z: 13.22564819859711 },
+ target: { x: -7.001588883043185, y: 16.262345352657395, z: -6.097455776264499 },
+ position: { x: -18.758818521416032, y: 16.33314980756182, z: 12.473888987363225 },
zoom0: 1
},
joint: {
- target: { x: 2.7622940494890424, y: 15.83905572715569, z: 0.08552052688719117 },
- position: { x: -4.6476929900921515, y: 15.883680193065107, z: 11.790099601955712 },
+ target: { x: 1.9482734060133915, y: 15.747678960743341, z: -0.429474906955281 },
+ position: { x: -5.461713633567803, y: 15.792303426652754, z: 11.275104168113232 },
zoom0: 1
},
grinder: {
- target: { x: -10.128808700176803, y: -15.480679803858136, z: 1.9651555238025413 },
- position: { x: -21.43448244172167, y: -15.531783203240701, z: 12.347383997813267 },
+ target: { x: -10.691421929972085, y: -15.525894683054275, z: 1.3522782143982923 },
+ position: { x: -21.99709567151696, y: -15.576998082436841, z: 11.73450668840891 },
zoom0: 1
},
overview: {
- target: { x: -2.4540886878602937, y: -1.7690793306726371, z: -0.104103172990748 },
- position: { x: -44.67609815729721, y: -1.5148097061598855, z: 38.669527626788486 },
+ target: { x: -4.793874852627955, y: 6.052339186049304, z: -6.403726952169199 },
+ position: { x: -26.23140973687205, y: 33.78061698752333, z: 24.44556028867285 },
zoom0: 1
}
},
@@ -570,8 +599,11 @@ export default {
const config = window.dt_Config || {}
this.iframeAddress = config.iframeAddress ? config.iframeAddress : ''
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.srcSm = this.buildIframeUrl(config.smIframe || this.srcSm, this.autoPlayCraftCode)
+ this.srcSm = this.buildIframeUrl(this.smIframeBase, this.autoPlayCraftCode, this.selectedAutoPlayRate)
this.titleText = config.titleText
this.updateTime()
this.setScale()
@@ -637,17 +669,44 @@ export default {
this.syncActiveCamera()
}
},
- buildIframeUrl(baseUrl, craftCode) {
+ buildIframeUrl(baseUrl, craftCode, autoPlayRate) {
if (!baseUrl) {
return ''
}
let nextUrl = baseUrl
+ if (nextUrl.includes('dmtmode=SM')) {
+ nextUrl = this.withAutoPlayRateParam(nextUrl, this.normalizeAutoPlayRate(autoPlayRate))
+ }
if (craftCode && nextUrl.includes('autoPlayCraftCode=') && !nextUrl.includes(craftCode)) {
const separator = nextUrl.endsWith('=') || nextUrl.endsWith('/') ? '' : '/'
nextUrl = `${nextUrl}${separator}${craftCode}`
}
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) {
if (!url || url.includes('transparent=true')) {
return url
@@ -725,6 +784,22 @@ export default {
this.switchMode('DT')
},
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')
},
initAlarmPieChart() {
@@ -1034,6 +1109,114 @@ body,
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 {
display: block;
width: 300px;