add story

This commit is contained in:
2026-07-29 01:00:48 +07:00
parent c04ae2868c
commit 9b3f43da98
14 changed files with 2601 additions and 2398 deletions
-2384
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2384
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -5,8 +5,8 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Вечерний детектив</title>
<script type="module" crossorigin src="/assets/index-8fDlsCH5.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Dq4E0b3K.css">
<script type="module" crossorigin src="/assets/index-CvnTtoPk.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CIDamrrf.css">
</head>
<body>
<div id="app"></div>
+3 -1
View File
@@ -789,7 +789,9 @@ message AddTeamReq {
}
message AddTeamRsp {
string error = 1;
string error = 1;
int32 id = 2;
string password = 3;
}
message UpdateTeamReq {
@@ -348,6 +348,8 @@ export type AddTeamReq = {
export type AddTeamRsp = {
error: string | undefined;
id: number | undefined;
password: string | undefined;
};
export type UpdateTeamReq = {
+70
View File
@@ -0,0 +1,70 @@
<script setup lang="ts">
import { getAuthClient } from '@/api/auth_client';
import type { Game } from '@/api/generated/crabs/evening_detective_server';
import HeaderMenu from '@/components/HeaderMenu.vue'
import { useMessage } from 'naive-ui';
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const client = getAuthClient()
const router = useRouter()
const route = useRoute()
const gameId = route.params.id
const message = useMessage()
const game = ref<Game>({
id: undefined,
name: undefined,
description: undefined,
startAt: undefined,
status: undefined,
scenario: undefined,
teams: undefined,
})
async function getGame(id: number) {
const res = await client.GetGame({ id: id })
if (res.error != '') {
message.error(res.error!)
return
}
game.value = res.game!
}
getGame(Number(gameId))
async function toTeamStory(id: number, password: string) {
router.push('/team-story/' + id + '?password=' + password)
}
</script>
<template>
<div class="center-block-custom content-block">
<div v-for="team in game.teams" class="team-block" @click="toTeamStory(team.id!, team.password!)">
<div class="team-title">
{{ team.name }}
</div>
</div>
</div>
<HeaderMenu active="games" />
</template>
<style scoped>
.team-block {
margin: 10px 0;
padding: 20px;
border-radius: 10px;
border: 1px solid #444;
}
.team-block:hover {
cursor: pointer;
color: #63e2b7;
}
.team-title {
font-size: 24px;
margin-bottom: 10px;
}
</style>
+59 -2
View File
@@ -1,11 +1,68 @@
<script setup lang="ts">
import { getAuthClient } from '@/api/auth_client';
import type { Game } from '@/api/generated/crabs/evening_detective_server';
import HeaderMenu from '@/components/HeaderMenu.vue'
import { useMessage } from 'naive-ui';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
const client = getAuthClient()
const message = useMessage()
const router = useRouter()
const games = ref<Game[]>([])
async function getGames() {
games.value = []
const res = await client.GetGames({})
if (res.error != '') {
message.error(res.error!)
return
}
games.value = res.games || []
}
getGames()
async function toGame(id: number) {
router.push('/games/' + id)
}
</script>
<template>
<div class="center-block-custom content-block">Игры</div>
<div class="center-block-custom content-block">
<div v-for="game in games" class="game-block" @click="toGame(game.id!)">
<div class="game-title">
{{ game.name }}
</div>
<div class="game-description">
{{ game.description }}
</div>
</div>
</div>
<HeaderMenu active="games" />
</template>
<style scoped></style>
<style scoped>
.game-block {
margin: 10px 0;
padding: 20px;
border-radius: 10px;
border: 1px solid #444;
}
.game-block:hover {
cursor: pointer;
color: #63e2b7;
}
.game-title {
font-size: 24px;
margin-bottom: 10px;
}
.game-description {
color: #aaa;
margin-bottom: 10px;
}
</style>
+36 -5
View File
@@ -2,7 +2,7 @@
import { Settings } from '@vicons/carbon'
import { Icon } from '@vicons/utils'
import { NButton, type UploadFileInfo, useMessage } from 'naive-ui'
import { NCard, NFlex, NInput, NModal, NSpace, NText, NUpload, NUploadDragger, NAlert } from 'naive-ui'
import { NCard, NFlex, NInput, NModal, NSpace, NText, NUpload, NUploadDragger, NAlert, NTag } from 'naive-ui'
import { ref } from 'vue'
import { useRoute } from 'vue-router'
@@ -69,7 +69,28 @@ async function publicScenario(id: number) {
showSettingsScenarioModal.value = false
}
async function addGame(name: string, id: number) {
const now = new Date().toISOString()
const resAddGame = await client.AddGame({
name: ('Тестовая игра: ' + name).trim(),
description: 'Тестовая игра',
startAt: now,
scenarioId: id
})
if (resAddGame.error != '') {
message.error(resAddGame.error!)
return
}
const resAddTeam = await client.AddTeam({
name: 'Тестовая команда',
gameId: resAddGame.id!,
})
if (resAddTeam.error != '') {
message.error(resAddTeam.error!)
return
}
router.push("/team-story/" + resAddTeam.id! + '?password=' + resAddTeam.password!)
}
async function draftScenario(id: number) {
const res = await client.DraftScenario({ id: id })
@@ -313,11 +334,21 @@ async function deletePlace(place: Place) {
<n-button @click="updateScenario()" ghost> Сохранить изменения </n-button>
<hr class="settings-hr" />
<p>Создать тестовую игру</p>
<n-button @click="addGame(scenario.name || '', scenario.id!)" ghost>
Создать игру
</n-button>
<hr class="settings-hr" />
<p>Публикация</p>
<p>Статус:
<span v-if="scenario.status == 'public'">опубликовано</span>
<span v-if="scenario.status == 'draft'">в разработке</span>
<p>
<n-tag v-if="scenario.status == 'public'" :bordered="false" type="success" class="status-block">
Опубликовано
</n-tag>
<n-tag v-if="scenario.status == 'draft'" :bordered="false" type="warning" class="status-block">
В разработке
</n-tag>
</p>
<p>
Введите название сценария <n-text class="name-text" strong>{{ scenario.name }}</n-text>
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
<div class="center-block-custom content-block">
История тут!
</div>
</template>
<style scoped></style>
+15 -3
View File
@@ -11,6 +11,8 @@ import UserAgreementView from '../views/UserAgreementView.vue'
import UsersView from '../views/UsersView.vue'
import CatalogView from '../views/CatalogView.vue'
import ScenarioView from '../views/ScenarioView.vue'
import GameView from '../views/GameView.vue'
import TeamStoryView from '../views/TeamStoryView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -45,6 +47,16 @@ const router = createRouter({
name: 'games',
component: GamesView,
},
{
path: '/games/:id',
name: 'game',
component: GameView,
},
{
path: '/team-story/:id',
name: 'team-story',
component: TeamStoryView,
},
{
path: '/scenarios',
name: 'scenarios',
@@ -52,17 +64,17 @@ const router = createRouter({
},
{
path: '/catalog',
name: 'CatalogView',
name: 'catalog',
component: CatalogView,
},
{
path: '/scenarios/:id/editor', // Динамический параметр id
name: 'ScenariosEditorView',
name: 'scenario-editor',
component: ScenariosEditorView,
},
{
path: '/scenarios/:id', // Динамический параметр id
name: 'ScenarioView',
name: 'scenario',
component: ScenarioView,
},
{
+9
View File
@@ -0,0 +1,9 @@
<script setup lang="ts">
import GamePage from '@/components/GamePage.vue'
</script>
<template>
<GamePage />
</template>
<style lang="css"></style>
+9
View File
@@ -0,0 +1,9 @@
<script setup lang="ts">
import TeamStoryPage from '@/components/TeamStoryPage.vue'
</script>
<template>
<TeamStoryPage />
</template>
<style lang="css"></style>