|
|
|
@@ -3,7 +3,7 @@ import { NAlert, NButton, NCard, NInput, NSelect, NSpace, useMessage } from 'nai
|
|
|
|
|
import { onMounted, onUnmounted, ref } from 'vue'
|
|
|
|
|
import type { OnlineIntent, OnlineState } from '../types/online'
|
|
|
|
|
|
|
|
|
|
defineProps<{ outputOpen: boolean; selectedKey: string | null }>()
|
|
|
|
|
defineProps<{ outputOpen: boolean; selectedKey: string | null; selectedName: string | null }>()
|
|
|
|
|
const emit = defineEmits<{ packagesChanged: [] }>()
|
|
|
|
|
const bridge = window.screenBridge
|
|
|
|
|
const message = useMessage()
|
|
|
|
@@ -16,6 +16,7 @@ const state = ref<OnlineState>({
|
|
|
|
|
canCancel: false,
|
|
|
|
|
games: [],
|
|
|
|
|
screenId: null,
|
|
|
|
|
soundEnabled: null,
|
|
|
|
|
connection: 'disabled',
|
|
|
|
|
error: '',
|
|
|
|
|
notice: '',
|
|
|
|
@@ -27,6 +28,12 @@ const email = ref('')
|
|
|
|
|
const password = ref('')
|
|
|
|
|
const gameId = ref<number | null>(null)
|
|
|
|
|
const isBusy = ref(false)
|
|
|
|
|
const gameStatusLabels = new Map([
|
|
|
|
|
['draft', 'Черновик'],
|
|
|
|
|
['run', 'Идёт'],
|
|
|
|
|
['pause', 'Пауза'],
|
|
|
|
|
['finish', 'Завершена'],
|
|
|
|
|
])
|
|
|
|
|
const connectionLabels = {
|
|
|
|
|
disabled: 'Управление не подключено',
|
|
|
|
|
waiting: 'Ожидание открытия показа',
|
|
|
|
@@ -134,7 +141,12 @@ onUnmounted(() => clearInterval(timer))
|
|
|
|
|
</n-space>
|
|
|
|
|
<n-select
|
|
|
|
|
v-model:value="gameId"
|
|
|
|
|
:options="state.games.map((g) => ({ label: `${g.name} · ${g.status}`, value: g.id }))"
|
|
|
|
|
:options="
|
|
|
|
|
state.games.map((g) => ({
|
|
|
|
|
label: `${g.name} · ${gameStatusLabels.get(g.status) ?? 'Неизвестный статус'}`,
|
|
|
|
|
value: g.id,
|
|
|
|
|
}))
|
|
|
|
|
"
|
|
|
|
|
:disabled="isBusy || state.busy"
|
|
|
|
|
placeholder="Выберите игру для подготовки"
|
|
|
|
|
:input-props="{ 'aria-label': 'Игра на сервере' }"
|
|
|
|
@@ -156,11 +168,13 @@ onUnmounted(() => clearInterval(timer))
|
|
|
|
|
Выбранную игру можно обновить после закрытия показа. Для обновления файлов по прежним
|
|
|
|
|
адресам загрузите материалы повторно.
|
|
|
|
|
</p>
|
|
|
|
|
<p>Выбор игры выше используется для загрузки материалов.</p>
|
|
|
|
|
<p v-if="selectedKey" data-testid="control-game">Игра для управления: {{ selectedName }}</p>
|
|
|
|
|
<n-button
|
|
|
|
|
v-if="selectedKey"
|
|
|
|
|
:disabled="isBusy || state.busy"
|
|
|
|
|
@click="run({ action: 'connect' })"
|
|
|
|
|
>Подключить управление выбранной игрой</n-button
|
|
|
|
|
>Подключить управление этой игрой</n-button
|
|
|
|
|
>
|
|
|
|
|
</template>
|
|
|
|
|
<p role="status">
|
|
|
|
@@ -168,6 +182,23 @@ onUnmounted(() => clearInterval(timer))
|
|
|
|
|
}}{{ state.screenId ? ` · Экран №${state.screenId}` : '' }}
|
|
|
|
|
</p>
|
|
|
|
|
<p v-if="state.screenId && !outputOpen">Опрос сервера начнётся после открытия показа.</p>
|
|
|
|
|
<template v-if="state.screenId">
|
|
|
|
|
<p role="status" data-testid="sound-assignment">
|
|
|
|
|
{{
|
|
|
|
|
state.soundEnabled === null
|
|
|
|
|
? 'Назначение звука пока неизвестно'
|
|
|
|
|
: state.soundEnabled
|
|
|
|
|
? 'Экран назначен для звука'
|
|
|
|
|
: 'Экран не назначен для звука'
|
|
|
|
|
}}
|
|
|
|
|
<template
|
|
|
|
|
v-if="state.soundEnabled !== null && (!outputOpen || state.connection !== 'connected')"
|
|
|
|
|
>
|
|
|
|
|
· Последнее подтверждённое состояние; сейчас назначение не проверяется.
|
|
|
|
|
</template>
|
|
|
|
|
</p>
|
|
|
|
|
<p>Переключатель «Выключить весь звук» управляет локальным звуком отдельно.</p>
|
|
|
|
|
</template>
|
|
|
|
|
<n-space v-if="state.screenId">
|
|
|
|
|
<n-button
|
|
|
|
|
:disabled="isBusy || state.busy || !state.authenticated"
|
|
|
|
@@ -181,6 +212,10 @@ onUnmounted(() => clearInterval(timer))
|
|
|
|
|
>Отключить управление</n-button
|
|
|
|
|
>
|
|
|
|
|
</n-space>
|
|
|
|
|
<p v-if="state.screenId">
|
|
|
|
|
«Отключить управление» прекращает управление приложением; привязка экрана на сервере
|
|
|
|
|
сохраняется.
|
|
|
|
|
</p>
|
|
|
|
|
<n-alert v-if="state.error" type="error">{{ state.error }}</n-alert>
|
|
|
|
|
<n-alert v-if="state.notice" type="info">{{ state.notice }}</n-alert>
|
|
|
|
|
<template v-if="state.busy">
|
|
|
|
|