This commit is contained in:
2026-10-23 00:46:06 +07:00
parent 4e4e5c66df
commit 0ca8bc70d2
4 changed files with 81 additions and 12 deletions
+4
View File
@@ -1739,6 +1739,8 @@ message Game {
string format = 10;
string location = 11;
GameExport export = 12;
string wifi_name = 13; // Management settings only.
string wifi_password = 14;
}
// Download ready ZIP through the authenticated streaming HTTP route:
@@ -2190,6 +2192,8 @@ message UpdateGameReq {
int32 scenarioID = 5;
string format = 6;
string location = 7;
optional string wifi_name = 8;
optional string wifi_password = 9;
}
message UpdateGameRsp {
@@ -568,6 +568,8 @@ export type Game = {
format: string | undefined;
location: string | undefined;
export: GameExport | undefined;
wifiName: string | undefined;
wifiPassword: string | undefined;
};
// Download ready ZIP through the authenticated streaming HTTP route:
@@ -968,6 +970,8 @@ export type UpdateGameReq = {
scenarioID: number | undefined;
format: string | undefined;
location: string | undefined;
wifiName?: string;
wifiPassword?: string;
};
export type UpdateGameRsp = {
+71 -12
View File
@@ -100,7 +100,15 @@ function onStateTabKeydown(event: KeyboardEvent) {
const message = useMessage()
const settingsDraft = ref({ name: '', description: '', format: 'online', location: '' })
const settingsDraft = ref({
name: '',
description: '',
format: 'online',
location: '',
wifiName: '',
wifiPassword: '',
})
const isSavingSettings = ref(false)
const settingsDraftInitialized = ref(false)
const showGiveApplicationModal = ref(false)
const showAddTeamModal = ref(false)
@@ -139,6 +147,8 @@ const game = ref<Game>({
scenario: undefined,
teams: undefined,
export: undefined,
wifiName: undefined,
wifiPassword: undefined,
})
const authStore = useAuthStore()
const uiStore = useUIStore()
@@ -191,6 +201,8 @@ watch(
scenario: undefined,
teams: undefined,
export: undefined,
wifiName: undefined,
wifiPassword: undefined,
}
void getGame(Number(gameId))
}
@@ -351,6 +363,8 @@ async function getGame(id: number) {
description: game.value.description || '',
format: game.value.format || 'online',
location: game.value.location || '',
wifiName: game.value.wifiName || '',
wifiPassword: game.value.wifiPassword || '',
}
settingsDraftInitialized.value = true
}
@@ -943,16 +957,38 @@ function toResults() {
}
async function updateGame() {
await client.UpdateGame({
ID: game.value.ID,
name: settingsDraft.value.name,
description: settingsDraft.value.description,
format: settingsDraft.value.format,
location: settingsDraft.value.location.trim(),
startAt: game.value.startAt,
scenarioID: game.value.scenario?.ID,
})
await getGame(game.value.ID!)
if (isSavingSettings.value) return
if (
new TextEncoder().encode(settingsDraft.value.wifiName).length > 32 ||
/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(settingsDraft.value.wifiName)
) {
message.error('Название Wi-Fi — до 32 байт UTF-8, без управляющих символов')
return
}
if (!/^[\x20-\x7e]{0,64}$/.test(settingsDraft.value.wifiPassword)) {
message.error('Пароль Wi-Fi — до 64 печатных ASCII-символов')
return
}
isSavingSettings.value = true
try {
await client.UpdateGame({
ID: game.value.ID,
name: settingsDraft.value.name,
description: settingsDraft.value.description,
format: settingsDraft.value.format,
location: settingsDraft.value.location.trim(),
wifiName: settingsDraft.value.wifiName,
wifiPassword: settingsDraft.value.wifiPassword,
startAt: game.value.startAt,
scenarioID: game.value.scenario?.ID,
})
await getGame(game.value.ID!)
message.success('Настройки игры сохранены')
} catch (err) {
message.error(err instanceof Error ? err.message : 'Не удалось сохранить настройки игры')
} finally {
isSavingSettings.value = false
}
}
const giveApplicationTeam = ref<Team>({
@@ -1394,9 +1430,32 @@ useSimplePolling(() => {
type="text"
placeholder="Оставьте пустым для онлайн-игры"
/>
<p class="settings-header">Wi-Fi для игроков</p>
<n-input
v-model:value="settingsDraft.wifiName"
aria-label="Название сети Wi-Fi"
placeholder="Название сети Wi-Fi"
/>
<n-input
v-model:value="settingsDraft.wifiPassword"
aria-label="Пароль Wi-Fi"
type="password"
show-password-on="click"
placeholder="Без пароля — оставьте пустым"
:maxlength="64"
/>
<p>
Название сети и пароль будут напечатаны рядом с QR-кодом команды в PDF и чеках.
Оставьте название сети пустым, чтобы убрать инструкцию.
</p>
</n-space>
<n-flex justify="end" class="settings-actions">
<n-button @click="updateGame()">Сохранить изменения</n-button>
<n-button
:loading="isSavingSettings"
:disabled="isSavingSettings"
@click="updateGame()"
>Сохранить изменения</n-button
>
</n-flex>
</UiBlock>
<UiBlock v-if="canDownloadResults">
+2
View File
@@ -57,6 +57,8 @@ const game = ref<Game | undefined>({
scenario: undefined,
teams: undefined,
export: undefined,
wifiName: undefined,
wifiPassword: undefined,
})
const code = ref('')