generated from VLADIMIR/template_frontend
up
This commit is contained in:
@@ -685,6 +685,36 @@ service EveningDetectiveServer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc GetScreenPlan(GetScreenPlanReq) returns (GetScreenPlanRsp) {
|
||||||
|
option (google.api.http) = { get: "/api/games/{gameID}/screen-plan" };
|
||||||
|
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||||
|
tags: "Экраны";
|
||||||
|
summary: "Получить план экранов";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc SaveScreenPlan(SaveScreenPlanReq) returns (SaveScreenPlanRsp) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
put: "/api/games/{gameID}/screen-plan"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||||
|
tags: "Экраны";
|
||||||
|
summary: "Сохранить план экранов";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc SetScreenPlanStep(SetScreenPlanStepReq) returns (SetScreenPlanStepRsp) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/api/games/{gameID}/screen-plan/step"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||||
|
tags: "Экраны";
|
||||||
|
summary: "Перейти на шаг плана экранов";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
rpc GetScreenResults(GetScreenResultsReq) returns (GetScreenResultsRsp) {
|
rpc GetScreenResults(GetScreenResultsReq) returns (GetScreenResultsRsp) {
|
||||||
option (google.api.http) = { post: "/api/screens/results" body: "*" };
|
option (google.api.http) = { post: "/api/screens/results" body: "*" };
|
||||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||||
@@ -1410,6 +1440,7 @@ enum ScreenMode {
|
|||||||
SCREEN_MODE_CONCLUSION_DONE = 5;
|
SCREEN_MODE_CONCLUSION_DONE = 5;
|
||||||
SCREEN_MODE_RESULTS = 6;
|
SCREEN_MODE_RESULTS = 6;
|
||||||
SCREEN_MODE_TIMER = 7;
|
SCREEN_MODE_TIMER = 7;
|
||||||
|
SCREEN_MODE_TEXT = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ScreenTimerState {
|
enum ScreenTimerState {
|
||||||
@@ -1455,6 +1486,7 @@ message ScreenState {
|
|||||||
int64 timer_duration_seconds = 17;
|
int64 timer_duration_seconds = 17;
|
||||||
int64 timer_remaining_seconds = 18;
|
int64 timer_remaining_seconds = 18;
|
||||||
ScreenTimerState timer_state = 19;
|
ScreenTimerState timer_state = 19;
|
||||||
|
string text = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateScreenSessionReq {}
|
message CreateScreenSessionReq {}
|
||||||
@@ -1563,6 +1595,45 @@ message SendScreenCommandReq {
|
|||||||
message SendScreenCommandRsp {
|
message SendScreenCommandRsp {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ScreenPlanStep {
|
||||||
|
ScreenMode mode = 1;
|
||||||
|
string text = 2;
|
||||||
|
string timer_label = 3;
|
||||||
|
int64 timer_duration_seconds = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ScreenPlan {
|
||||||
|
repeated ScreenPlanStep steps = 1;
|
||||||
|
int32 current_step = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetScreenPlanReq {
|
||||||
|
int32 gameID = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetScreenPlanRsp {
|
||||||
|
ScreenPlan plan = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SaveScreenPlanReq {
|
||||||
|
int32 gameID = 1;
|
||||||
|
repeated ScreenPlanStep steps = 2;
|
||||||
|
int32 current_step = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SaveScreenPlanRsp {
|
||||||
|
ScreenPlan plan = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetScreenPlanStepReq {
|
||||||
|
int32 gameID = 1;
|
||||||
|
int32 current_step = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetScreenPlanStepRsp {
|
||||||
|
ScreenPlan plan = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message GetScreenResultsReq {
|
message GetScreenResultsReq {
|
||||||
string screenID = 1;
|
string screenID = 1;
|
||||||
string accessToken = 2;
|
string accessToken = 2;
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ export type ScreenMode =
|
|||||||
| "SCREEN_MODE_CONCLUSION"
|
| "SCREEN_MODE_CONCLUSION"
|
||||||
| "SCREEN_MODE_CONCLUSION_DONE"
|
| "SCREEN_MODE_CONCLUSION_DONE"
|
||||||
| "SCREEN_MODE_RESULTS"
|
| "SCREEN_MODE_RESULTS"
|
||||||
| "SCREEN_MODE_TIMER";
|
| "SCREEN_MODE_TIMER"
|
||||||
|
| "SCREEN_MODE_TEXT";
|
||||||
export type ScreenTimerState =
|
export type ScreenTimerState =
|
||||||
| "SCREEN_TIMER_STATE_UNSPECIFIED"
|
| "SCREEN_TIMER_STATE_UNSPECIFIED"
|
||||||
| "SCREEN_TIMER_STATE_STOPPED"
|
| "SCREEN_TIMER_STATE_STOPPED"
|
||||||
@@ -502,6 +503,7 @@ export type ScreenState = {
|
|||||||
timerDurationSeconds: number | undefined;
|
timerDurationSeconds: number | undefined;
|
||||||
timerRemainingSeconds: number | undefined;
|
timerRemainingSeconds: number | undefined;
|
||||||
timerState: ScreenTimerState | undefined;
|
timerState: ScreenTimerState | undefined;
|
||||||
|
text: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateScreenSessionReq = {
|
export type CreateScreenSessionReq = {
|
||||||
@@ -612,6 +614,45 @@ export type SendScreenCommandReq = {
|
|||||||
export type SendScreenCommandRsp = {
|
export type SendScreenCommandRsp = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ScreenPlanStep = {
|
||||||
|
mode: ScreenMode | undefined;
|
||||||
|
text: string | undefined;
|
||||||
|
timerLabel: string | undefined;
|
||||||
|
timerDurationSeconds: number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ScreenPlan = {
|
||||||
|
steps: ScreenPlanStep[] | undefined;
|
||||||
|
currentStep: number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GetScreenPlanReq = {
|
||||||
|
gameID: number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GetScreenPlanRsp = {
|
||||||
|
plan: ScreenPlan | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SaveScreenPlanReq = {
|
||||||
|
gameID: number | undefined;
|
||||||
|
steps: ScreenPlanStep[] | undefined;
|
||||||
|
currentStep: number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SaveScreenPlanRsp = {
|
||||||
|
plan: ScreenPlan | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetScreenPlanStepReq = {
|
||||||
|
gameID: number | undefined;
|
||||||
|
currentStep: number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetScreenPlanStepRsp = {
|
||||||
|
plan: ScreenPlan | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export type GetScreenResultsReq = {
|
export type GetScreenResultsReq = {
|
||||||
screenID: string | undefined;
|
screenID: string | undefined;
|
||||||
accessToken: string | undefined;
|
accessToken: string | undefined;
|
||||||
@@ -1017,6 +1058,9 @@ export interface EveningDetectiveServer {
|
|||||||
SetScreenTimer(request: SetScreenTimerReq): Promise<SetScreenTimerRsp>;
|
SetScreenTimer(request: SetScreenTimerReq): Promise<SetScreenTimerRsp>;
|
||||||
// Отправить общую команду экранам игры.
|
// Отправить общую команду экранам игры.
|
||||||
SendScreenCommand(request: SendScreenCommandReq): Promise<SendScreenCommandRsp>;
|
SendScreenCommand(request: SendScreenCommandReq): Promise<SendScreenCommandRsp>;
|
||||||
|
GetScreenPlan(request: GetScreenPlanReq): Promise<GetScreenPlanRsp>;
|
||||||
|
SaveScreenPlan(request: SaveScreenPlanReq): Promise<SaveScreenPlanRsp>;
|
||||||
|
SetScreenPlanStep(request: SetScreenPlanStepReq): Promise<SetScreenPlanStepRsp>;
|
||||||
GetScreenResults(request: GetScreenResultsReq): Promise<GetScreenResultsRsp>;
|
GetScreenResults(request: GetScreenResultsReq): Promise<GetScreenResultsRsp>;
|
||||||
DownloadTeamQR(request: GetGameReq): Promise<googleapi_HttpBody>;
|
DownloadTeamQR(request: GetGameReq): Promise<googleapi_HttpBody>;
|
||||||
GetGameAnswers(request: GetGameAnswersReq): Promise<GetGameAnswersRsp>;
|
GetGameAnswers(request: GetGameAnswersReq): Promise<GetGameAnswersRsp>;
|
||||||
@@ -2167,6 +2211,66 @@ export function createEveningDetectiveServerClient(
|
|||||||
method: "SendScreenCommand",
|
method: "SendScreenCommand",
|
||||||
}) as Promise<SendScreenCommandRsp>;
|
}) as Promise<SendScreenCommandRsp>;
|
||||||
},
|
},
|
||||||
|
GetScreenPlan(request) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
|
if (!request.gameID) {
|
||||||
|
throw new Error("missing required field request.gameID");
|
||||||
|
}
|
||||||
|
const path = `api/games/${request.gameID}/screen-plan`; // eslint-disable-line quotes
|
||||||
|
const body = null;
|
||||||
|
const queryParams: string[] = [];
|
||||||
|
let uri = path;
|
||||||
|
if (queryParams.length > 0) {
|
||||||
|
uri += `?${queryParams.join("&")}`
|
||||||
|
}
|
||||||
|
return handler({
|
||||||
|
path: uri,
|
||||||
|
method: "GET",
|
||||||
|
body,
|
||||||
|
}, {
|
||||||
|
service: "EveningDetectiveServer",
|
||||||
|
method: "GetScreenPlan",
|
||||||
|
}) as Promise<GetScreenPlanRsp>;
|
||||||
|
},
|
||||||
|
SaveScreenPlan(request) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
|
if (!request.gameID) {
|
||||||
|
throw new Error("missing required field request.gameID");
|
||||||
|
}
|
||||||
|
const path = `api/games/${request.gameID}/screen-plan`; // eslint-disable-line quotes
|
||||||
|
const body = JSON.stringify(request);
|
||||||
|
const queryParams: string[] = [];
|
||||||
|
let uri = path;
|
||||||
|
if (queryParams.length > 0) {
|
||||||
|
uri += `?${queryParams.join("&")}`
|
||||||
|
}
|
||||||
|
return handler({
|
||||||
|
path: uri,
|
||||||
|
method: "PUT",
|
||||||
|
body,
|
||||||
|
}, {
|
||||||
|
service: "EveningDetectiveServer",
|
||||||
|
method: "SaveScreenPlan",
|
||||||
|
}) as Promise<SaveScreenPlanRsp>;
|
||||||
|
},
|
||||||
|
SetScreenPlanStep(request) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
|
if (!request.gameID) {
|
||||||
|
throw new Error("missing required field request.gameID");
|
||||||
|
}
|
||||||
|
const path = `api/games/${request.gameID}/screen-plan/step`; // eslint-disable-line quotes
|
||||||
|
const body = JSON.stringify(request);
|
||||||
|
const queryParams: string[] = [];
|
||||||
|
let uri = path;
|
||||||
|
if (queryParams.length > 0) {
|
||||||
|
uri += `?${queryParams.join("&")}`
|
||||||
|
}
|
||||||
|
return handler({
|
||||||
|
path: uri,
|
||||||
|
method: "POST",
|
||||||
|
body,
|
||||||
|
}, {
|
||||||
|
service: "EveningDetectiveServer",
|
||||||
|
method: "SetScreenPlanStep",
|
||||||
|
}) as Promise<SetScreenPlanStepRsp>;
|
||||||
|
},
|
||||||
GetScreenResults(request) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
GetScreenResults(request) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
const path = `api/screens/results`; // eslint-disable-line quotes
|
const path = `api/screens/results`; // eslint-disable-line quotes
|
||||||
const body = JSON.stringify(request);
|
const body = JSON.stringify(request);
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import type {
|
|||||||
ResultsQuestion,
|
ResultsQuestion,
|
||||||
ScreenCommand,
|
ScreenCommand,
|
||||||
ScreenMode,
|
ScreenMode,
|
||||||
|
ScreenPlan,
|
||||||
|
ScreenPlanStep,
|
||||||
ScreenState,
|
ScreenState,
|
||||||
Team,
|
Team,
|
||||||
TeamAnswers,
|
TeamAnswers,
|
||||||
@@ -106,6 +108,10 @@ const teamsNeedingApplications = computed(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
const screens = ref<ScreenState[]>([])
|
const screens = ref<ScreenState[]>([])
|
||||||
|
const screenPlan = ref<ScreenPlan>()
|
||||||
|
const screenPlanDraft = ref<ScreenPlanStep[]>([])
|
||||||
|
const screenPlanDirty = ref(false)
|
||||||
|
const screenPlanSaving = ref(false)
|
||||||
const previewQuestions = ref<ResultsQuestion[]>([])
|
const previewQuestions = ref<ResultsQuestion[]>([])
|
||||||
const previewTeams = ref<TeamResult[]>([])
|
const previewTeams = ref<TeamResult[]>([])
|
||||||
const mapItems = ref<MapItem[]>([])
|
const mapItems = ref<MapItem[]>([])
|
||||||
@@ -123,6 +129,16 @@ const currentScreenMode = computed<ScreenMode | undefined>(() => {
|
|||||||
const timerScreen = computed(() => screens.value[0])
|
const timerScreen = computed(() => screens.value[0])
|
||||||
const previewScreen = computed(() => screens.value.find((screen) => screen.status === 'connected') || screens.value[0])
|
const previewScreen = computed(() => screens.value.find((screen) => screen.status === 'connected') || screens.value[0])
|
||||||
const hasDisconnectedScreen = computed(() => screens.value.some((screen) => screen.status === 'disconnected'))
|
const hasDisconnectedScreen = computed(() => screens.value.some((screen) => screen.status === 'disconnected'))
|
||||||
|
const screenPlanModeOptions = [
|
||||||
|
{ label: 'Обложка', value: 'SCREEN_MODE_COVER' },
|
||||||
|
{ label: 'Введение', value: 'SCREEN_MODE_INTRO' },
|
||||||
|
{ label: 'Успехов', value: 'SCREEN_MODE_INTRO_DONE' },
|
||||||
|
{ label: 'Закрывашка', value: 'SCREEN_MODE_CONCLUSION' },
|
||||||
|
{ label: 'Спасибо за игру', value: 'SCREEN_MODE_CONCLUSION_DONE' },
|
||||||
|
{ label: 'Результаты', value: 'SCREEN_MODE_RESULTS' },
|
||||||
|
{ label: 'Таймер', value: 'SCREEN_MODE_TIMER' },
|
||||||
|
{ label: 'Текст', value: 'SCREEN_MODE_TEXT' },
|
||||||
|
]
|
||||||
const timerStateLabel = computed(() => {
|
const timerStateLabel = computed(() => {
|
||||||
switch (timerScreen.value?.timerState) {
|
switch (timerScreen.value?.timerState) {
|
||||||
case 'SCREEN_TIMER_STATE_RUNNING':
|
case 'SCREEN_TIMER_STATE_RUNNING':
|
||||||
@@ -196,6 +212,77 @@ async function getGameScreens() {
|
|||||||
}
|
}
|
||||||
getGameScreens()
|
getGameScreens()
|
||||||
|
|
||||||
|
async function getScreenPlan() {
|
||||||
|
if (screenPlanDirty.value) return
|
||||||
|
const res = await client.GetScreenPlan({ gameID: Number(gameId) })
|
||||||
|
screenPlan.value = res.plan
|
||||||
|
screenPlanDraft.value = res.plan?.steps?.map((step) => ({ ...step })) || []
|
||||||
|
}
|
||||||
|
getScreenPlan()
|
||||||
|
|
||||||
|
function addScreenPlanStep() {
|
||||||
|
screenPlanDraft.value.push({
|
||||||
|
mode: 'SCREEN_MODE_TEXT',
|
||||||
|
text: 'Новый экран',
|
||||||
|
timerLabel: 'Перерыв',
|
||||||
|
timerDurationSeconds: 600,
|
||||||
|
})
|
||||||
|
screenPlanDirty.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeScreenPlanStep(index: number) {
|
||||||
|
screenPlanDraft.value.splice(index, 1)
|
||||||
|
screenPlanDirty.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveScreenPlanStep(index: number, offset: number) {
|
||||||
|
const target = index + offset
|
||||||
|
if (target < 0 || target >= screenPlanDraft.value.length) return
|
||||||
|
const [step] = screenPlanDraft.value.splice(index, 1)
|
||||||
|
screenPlanDraft.value.splice(target, 0, step)
|
||||||
|
screenPlanDirty.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function markScreenPlanDirty() {
|
||||||
|
screenPlanDirty.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveScreenPlan() {
|
||||||
|
if (screenPlanSaving.value) return
|
||||||
|
screenPlanSaving.value = true
|
||||||
|
try {
|
||||||
|
const currentStep = Math.min(
|
||||||
|
screenPlan.value?.currentStep || 0,
|
||||||
|
Math.max(0, screenPlanDraft.value.length - 1),
|
||||||
|
)
|
||||||
|
const res = await client.SaveScreenPlan({
|
||||||
|
gameID: Number(gameId),
|
||||||
|
steps: screenPlanDraft.value,
|
||||||
|
currentStep,
|
||||||
|
})
|
||||||
|
screenPlan.value = res.plan
|
||||||
|
screenPlanDraft.value = res.plan?.steps?.map((step) => ({ ...step })) || []
|
||||||
|
screenPlanDirty.value = false
|
||||||
|
await getGameScreens()
|
||||||
|
message.success(res.plan ? 'План экранов сохранён' : 'План экранов удалён')
|
||||||
|
} catch (err) {
|
||||||
|
message.error(err instanceof Error ? err.message : 'Не удалось сохранить план экранов')
|
||||||
|
} finally {
|
||||||
|
screenPlanSaving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setScreenPlanStep(index: number) {
|
||||||
|
if (screenPlanDirty.value || !screenPlan.value) return
|
||||||
|
try {
|
||||||
|
const res = await client.SetScreenPlanStep({ gameID: Number(gameId), currentStep: index })
|
||||||
|
screenPlan.value = res.plan
|
||||||
|
await getGameScreens()
|
||||||
|
} catch (err) {
|
||||||
|
message.error(err instanceof Error ? err.message : 'Не удалось перейти на шаг плана')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function stopScreenScanner() {
|
function stopScreenScanner() {
|
||||||
cancelAnimationFrame(screenScannerFrame)
|
cancelAnimationFrame(screenScannerFrame)
|
||||||
screenScannerStream?.getTracks().forEach((track) => track.stop())
|
screenScannerStream?.getTracks().forEach((track) => track.stop())
|
||||||
@@ -607,6 +694,7 @@ async function issueTickets() {
|
|||||||
useSimplePolling(() => {
|
useSimplePolling(() => {
|
||||||
getGame(Number(gameId))
|
getGame(Number(gameId))
|
||||||
getGameScreens()
|
getGameScreens()
|
||||||
|
getScreenPlan()
|
||||||
getGameMap()
|
getGameMap()
|
||||||
}, 2000)
|
}, 2000)
|
||||||
|
|
||||||
@@ -952,6 +1040,86 @@ useSimplePolling(() => {
|
|||||||
>Перемотать</n-button
|
>Перемотать</n-button
|
||||||
>
|
>
|
||||||
</n-space>
|
</n-space>
|
||||||
|
<div class="screen-plan">
|
||||||
|
<n-flex align="center" justify="space-between">
|
||||||
|
<p class="screens-title">План экранов</p>
|
||||||
|
<n-space>
|
||||||
|
<n-button v-if="!screenPlan && !screenPlanDirty" size="small" @click="addScreenPlanStep">
|
||||||
|
Создать план
|
||||||
|
</n-button>
|
||||||
|
<n-button
|
||||||
|
v-if="screenPlan || screenPlanDirty"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:loading="screenPlanSaving"
|
||||||
|
@click="saveScreenPlan"
|
||||||
|
>
|
||||||
|
Сохранить план
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
|
</n-flex>
|
||||||
|
<template v-if="screenPlan || screenPlanDirty">
|
||||||
|
<n-space v-for="(step, index) in screenPlanDraft" :key="index" align="center" wrap>
|
||||||
|
<n-text>{{ index + 1 }}</n-text>
|
||||||
|
<n-select
|
||||||
|
v-model:value="step.mode"
|
||||||
|
:options="screenPlanModeOptions"
|
||||||
|
size="small"
|
||||||
|
style="width: 180px"
|
||||||
|
@update:value="markScreenPlanDirty"
|
||||||
|
/>
|
||||||
|
<n-input
|
||||||
|
v-if="step.mode === 'SCREEN_MODE_TEXT'"
|
||||||
|
v-model:value="step.text"
|
||||||
|
size="small"
|
||||||
|
placeholder="Текст экрана"
|
||||||
|
style="min-width: 240px"
|
||||||
|
@update:value="markScreenPlanDirty"
|
||||||
|
/>
|
||||||
|
<template v-if="step.mode === 'SCREEN_MODE_TIMER'">
|
||||||
|
<n-input
|
||||||
|
v-model:value="step.timerLabel"
|
||||||
|
size="small"
|
||||||
|
placeholder="Надпись таймера"
|
||||||
|
@update:value="markScreenPlanDirty"
|
||||||
|
/>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="step.timerDurationSeconds"
|
||||||
|
:min="1"
|
||||||
|
:max="86400"
|
||||||
|
size="small"
|
||||||
|
placeholder="Секунды"
|
||||||
|
@update:value="markScreenPlanDirty"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<n-button size="small" :disabled="index === 0" @click="moveScreenPlanStep(index, -1)">↑</n-button>
|
||||||
|
<n-button
|
||||||
|
size="small"
|
||||||
|
:disabled="index === screenPlanDraft.length - 1"
|
||||||
|
@click="moveScreenPlanStep(index, 1)"
|
||||||
|
>
|
||||||
|
↓
|
||||||
|
</n-button>
|
||||||
|
<n-button size="small" type="error" ghost @click="removeScreenPlanStep(index)">
|
||||||
|
Удалить
|
||||||
|
</n-button>
|
||||||
|
<n-button
|
||||||
|
size="small"
|
||||||
|
:type="screenPlan?.currentStep === index ? 'primary' : 'default'"
|
||||||
|
:disabled="screenPlanDirty || screenPlan?.currentStep === index"
|
||||||
|
@click="setScreenPlanStep(index)"
|
||||||
|
>
|
||||||
|
Показать
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
|
<n-space>
|
||||||
|
<n-button size="small" @click="addScreenPlanStep">Добавить шаг</n-button>
|
||||||
|
<n-button v-if="screenPlanDraft.length" size="small" @click="screenPlanDraft = []; markScreenPlanDirty()">
|
||||||
|
Удалить план
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ onUnmounted(() => {
|
|||||||
<div v-else-if="screenMode === 'SCREEN_MODE_CONCLUSION'" class="screen-message">Видео закрывашки не задано</div>
|
<div v-else-if="screenMode === 'SCREEN_MODE_CONCLUSION'" class="screen-message">Видео закрывашки не задано</div>
|
||||||
<div v-else-if="screenMode === 'SCREEN_MODE_INTRO_DONE'" class="screen-message">Успехов</div>
|
<div v-else-if="screenMode === 'SCREEN_MODE_INTRO_DONE'" class="screen-message">Успехов</div>
|
||||||
<div v-else-if="screenMode === 'SCREEN_MODE_CONCLUSION_DONE'" class="screen-message">Спасибо за игру!</div>
|
<div v-else-if="screenMode === 'SCREEN_MODE_CONCLUSION_DONE'" class="screen-message">Спасибо за игру!</div>
|
||||||
|
<div v-else-if="screenMode === 'SCREEN_MODE_TEXT'" class="screen-message">{{ state.text }}</div>
|
||||||
<div v-else-if="screenMode === 'SCREEN_MODE_TIMER'" class="timer-screen">
|
<div v-else-if="screenMode === 'SCREEN_MODE_TIMER'" class="timer-screen">
|
||||||
<h1 class="timer-label">{{ state.timerLabel || 'Перерыв' }}</h1>
|
<h1 class="timer-label">{{ state.timerLabel || 'Перерыв' }}</h1>
|
||||||
<div class="timer-value">{{ timerDisplay }}</div>
|
<div class="timer-value">{{ timerDisplay }}</div>
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ onUnmounted(() => {
|
|||||||
<div v-else-if="state.mode === 'SCREEN_MODE_CONCLUSION_DONE'" class="preview-message">
|
<div v-else-if="state.mode === 'SCREEN_MODE_CONCLUSION_DONE'" class="preview-message">
|
||||||
Спасибо за игру!
|
Спасибо за игру!
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="state.mode === 'SCREEN_MODE_TEXT'" class="preview-message">{{ state.text }}</div>
|
||||||
<div v-else-if="state.mode === 'SCREEN_MODE_RESULTS'" class="preview-results">
|
<div v-else-if="state.mode === 'SCREEN_MODE_RESULTS'" class="preview-results">
|
||||||
<h2>Результаты</h2>
|
<h2>Результаты</h2>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
Reference in New Issue
Block a user