generated from VLADIMIR/template_frontend
format
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
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 } from 'naive-ui'
|
||||
import { ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { NButton, type UploadFileInfo, useMessage } from 'naive-ui'
|
||||
import { NCard, NFlex, NInput, NModal, NSpace, NText, NUpload, NUploadDragger } from 'naive-ui'
|
||||
import { ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { getAuthClient } from '@/api/auth_client';
|
||||
import type { Place, Scenario } from '@/api/generated/crabs/evening_detective_server';
|
||||
import { getAuthClient } from '@/api/auth_client'
|
||||
import type { Place, Scenario } from '@/api/generated/crabs/evening_detective_server'
|
||||
import HeaderMenu from '@/components/HeaderMenu.vue'
|
||||
import PlaceBlock from '@/components/PlaceBlock.vue';
|
||||
import router from '@/router';
|
||||
import PlaceBlock from '@/components/PlaceBlock.vue'
|
||||
import router from '@/router'
|
||||
|
||||
const client = getAuthClient();
|
||||
const client = getAuthClient()
|
||||
const route = useRoute()
|
||||
const scenarioId = route.params.id
|
||||
|
||||
@@ -24,16 +24,100 @@ const message = useMessage()
|
||||
const fileList = ref<UploadFileInfo[]>([])
|
||||
|
||||
const scenario = ref<Scenario>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
story: undefined,
|
||||
author: undefined,
|
||||
updatedAt: undefined,
|
||||
createdAt: undefined,
|
||||
publishedAt: undefined
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
story: undefined,
|
||||
author: undefined,
|
||||
updatedAt: undefined,
|
||||
createdAt: undefined,
|
||||
publishedAt: undefined,
|
||||
})
|
||||
|
||||
const newPlace = ref<Place>({
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
text: undefined,
|
||||
image: undefined,
|
||||
hidden: undefined,
|
||||
applications: undefined,
|
||||
doors: undefined,
|
||||
keys: undefined,
|
||||
mode: 'mini-add',
|
||||
})
|
||||
|
||||
async function getScenario(id: number) {
|
||||
const res = await client.GetScenario({ id: id })
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
scenario.value = res.scenario!
|
||||
scenario.value.story?.places?.forEach((item) => {
|
||||
item.oldCode = item.code
|
||||
item.mode = 'show-editor'
|
||||
})
|
||||
}
|
||||
getScenario(Number(scenarioId))
|
||||
|
||||
async function deleteScenario(id: number) {
|
||||
const res = await client.DeleteScenario({ id: id })
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
router.push('/scenarios')
|
||||
}
|
||||
|
||||
async function updateScenario() {
|
||||
const file = fileList.value[0].file
|
||||
if (!file) return
|
||||
|
||||
// Читаем как ArrayBuffer
|
||||
const arrayBuffer = await file.arrayBuffer()
|
||||
const bytes = new Uint8Array(arrayBuffer)
|
||||
|
||||
const resUploadFile = await client.UploadFile({
|
||||
filename: 'scenarios_' + scenario.value.id + '_' + file.name,
|
||||
data: uint8ToBase64(bytes),
|
||||
})
|
||||
if (resUploadFile.error != '') {
|
||||
message.error(resUploadFile.error!)
|
||||
return
|
||||
}
|
||||
|
||||
const res = await client.UpdateScenario({
|
||||
id: scenario.value.id,
|
||||
name: scenario.value.name,
|
||||
description: scenario.value.description,
|
||||
image: resUploadFile.filename,
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
showSettingsScenarioModal.value = false
|
||||
}
|
||||
|
||||
function uint8ToBase64(uint8Array: Uint8Array) {
|
||||
// Преобразуем Uint8Array в двоичную строку
|
||||
const binaryString = String.fromCharCode(...uint8Array)
|
||||
// Кодируем в Base64
|
||||
return btoa(binaryString)
|
||||
}
|
||||
|
||||
async function addPlace() {
|
||||
const res = await client.AddScenarioPlace({
|
||||
id: scenario.value.id,
|
||||
place: newPlace.value,
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
|
||||
newPlace.value = {
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
text: undefined,
|
||||
@@ -42,262 +126,196 @@ const newPlace = ref<Place>({
|
||||
applications: undefined,
|
||||
doors: undefined,
|
||||
keys: undefined,
|
||||
mode: 'mini-add'
|
||||
})
|
||||
|
||||
async function getScenario(id: number) {
|
||||
const res = await client.GetScenario({ id: id })
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
scenario.value = res.scenario!
|
||||
scenario.value.story?.places?.forEach((item) => {
|
||||
item.oldCode = item.code
|
||||
item.mode = 'show-editor'
|
||||
})
|
||||
}
|
||||
getScenario(Number(scenarioId))
|
||||
|
||||
async function deleteScenario(id: number) {
|
||||
const res = await client.DeleteScenario({ id: id })
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
router.push('/scenarios')
|
||||
}
|
||||
|
||||
async function updateScenario() {
|
||||
const file = fileList.value[0].file
|
||||
if (!file) return
|
||||
|
||||
// Читаем как ArrayBuffer
|
||||
const arrayBuffer = await file.arrayBuffer()
|
||||
const bytes = new Uint8Array(arrayBuffer)
|
||||
|
||||
const resUploadFile = await client.UploadFile({
|
||||
filename: 'scenarios_' + scenario.value.id + '_' + file.name,
|
||||
data: uint8ToBase64(bytes)
|
||||
})
|
||||
if (resUploadFile.error != '') {
|
||||
message.error(resUploadFile.error!)
|
||||
return
|
||||
}
|
||||
|
||||
const res = await client.UpdateScenario({
|
||||
id: scenario.value.id,
|
||||
name: scenario.value.name,
|
||||
description: scenario.value.description,
|
||||
image: resUploadFile.filename,
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
showSettingsScenarioModal.value = false
|
||||
}
|
||||
|
||||
function uint8ToBase64(uint8Array: Uint8Array) {
|
||||
// Преобразуем Uint8Array в двоичную строку
|
||||
const binaryString = String.fromCharCode(...uint8Array);
|
||||
// Кодируем в Base64
|
||||
return btoa(binaryString);
|
||||
}
|
||||
|
||||
async function addPlace() {
|
||||
const res = await client.AddScenarioPlace({
|
||||
id: scenario.value.id,
|
||||
place: newPlace.value
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
|
||||
newPlace.value = {
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
text: undefined,
|
||||
image: undefined,
|
||||
hidden: undefined,
|
||||
applications: undefined,
|
||||
doors: undefined,
|
||||
keys: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function collapseAddPlace(place: Place) {
|
||||
place.mode = 'mini-add'
|
||||
place.mode = 'mini-add'
|
||||
}
|
||||
|
||||
async function cancelUpdatePlace(place: Place) {
|
||||
await getScenario(Number(scenarioId))
|
||||
await getScenario(Number(scenarioId))
|
||||
|
||||
place.mode = 'show-editor'
|
||||
place.mode = 'show-editor'
|
||||
}
|
||||
|
||||
async function updatePlace(place: Place) {
|
||||
const res = await client.UpdateScenarioPlace({
|
||||
id: scenario.value.id,
|
||||
code: place.oldCode,
|
||||
place: place
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
const res = await client.UpdateScenarioPlace({
|
||||
id: scenario.value.id,
|
||||
code: place.oldCode,
|
||||
place: place,
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
|
||||
place.mode = 'show-editor'
|
||||
place.mode = 'show-editor'
|
||||
}
|
||||
|
||||
async function deletePlace(place: Place) {
|
||||
const res = await client.DeleteScenarioPlace({
|
||||
id: scenario.value.id,
|
||||
code: place.oldCode,
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
const res = await client.DeleteScenarioPlace({
|
||||
id: scenario.value.id,
|
||||
code: place.oldCode,
|
||||
})
|
||||
if (res.error != '') {
|
||||
message.error(res.error!)
|
||||
return
|
||||
}
|
||||
await getScenario(Number(scenarioId))
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<HeaderMenu :add-logout="true" active="scenarios" />
|
||||
<HeaderMenu :add-logout="true" active="scenarios" />
|
||||
|
||||
<div class="center-block-custom-big content-block">
|
||||
<div class="places-container">
|
||||
<div class="settings-block">
|
||||
<n-button quaternary @click="showSettingsScenarioModal = true" class="settings-button">
|
||||
<Icon class="settings-icon">
|
||||
<Settings />
|
||||
</Icon>
|
||||
Настройки
|
||||
</n-button>
|
||||
</div>
|
||||
<div class="center-block-custom-big content-block">
|
||||
<div class="places-container">
|
||||
<div class="settings-block">
|
||||
<n-button quaternary @click="showSettingsScenarioModal = true" class="settings-button">
|
||||
<Icon class="settings-icon">
|
||||
<Settings />
|
||||
</Icon>
|
||||
Настройки
|
||||
</n-button>
|
||||
</div>
|
||||
|
||||
<PlaceBlock :place="newPlace" v-model:mode="newPlace.mode">
|
||||
<n-flex justify="end">
|
||||
<n-button @click="collapseAddPlace(newPlace)">Отмена</n-button>
|
||||
<n-button @click="addPlace()" :disabled="!newPlace.code">Добавить точку</n-button>
|
||||
</n-flex>
|
||||
</PlaceBlock>
|
||||
<PlaceBlock :place="newPlace" v-model:mode="newPlace.mode">
|
||||
<n-flex justify="end">
|
||||
<n-button @click="collapseAddPlace(newPlace)">Отмена</n-button>
|
||||
<n-button @click="addPlace()" :disabled="!newPlace.code">Добавить точку</n-button>
|
||||
</n-flex>
|
||||
</PlaceBlock>
|
||||
|
||||
<PlaceBlock :place="place" v-model:mode="place.mode" v-for="place in scenario.story?.places" v-bind:key="place.code">
|
||||
<n-flex justify="end">
|
||||
<n-button @click="deletePlace(place)" type="error" ghost>Удалить</n-button>
|
||||
<n-button @click="cancelUpdatePlace(place)">Отмена</n-button>
|
||||
<n-button @click="updatePlace(place)">Сохранить</n-button>
|
||||
</n-flex>
|
||||
</PlaceBlock>
|
||||
</div>
|
||||
<PlaceBlock
|
||||
:place="place"
|
||||
v-model:mode="place.mode"
|
||||
v-for="place in scenario.story?.places"
|
||||
v-bind:key="place.code"
|
||||
>
|
||||
<n-flex justify="end">
|
||||
<n-button @click="deletePlace(place)" type="error" ghost>Удалить</n-button>
|
||||
<n-button @click="cancelUpdatePlace(place)">Отмена</n-button>
|
||||
<n-button @click="updatePlace(place)">Сохранить</n-button>
|
||||
</n-flex>
|
||||
</PlaceBlock>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Окно настроек сценария -->
|
||||
<n-modal v-model:show="showSettingsScenarioModal">
|
||||
<n-card style="width: 600px" title="Настройки сценария" :bordered="false" size="huge" role="dialog"
|
||||
aria-modal="true">
|
||||
<template #header-extra>
|
||||
<n-button @click="showSettingsScenarioModal = false">
|
||||
x
|
||||
</n-button>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<p>
|
||||
Название
|
||||
</p>
|
||||
<n-input v-model:value="scenario.name" type="text" placeholder='Дело №0 "Следствие ведут овечки"' />
|
||||
<!-- Окно настроек сценария -->
|
||||
<n-modal v-model:show="showSettingsScenarioModal">
|
||||
<n-card
|
||||
style="width: 600px"
|
||||
title="Настройки сценария"
|
||||
:bordered="false"
|
||||
size="huge"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-button @click="showSettingsScenarioModal = false"> x </n-button>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<p>Название</p>
|
||||
<n-input
|
||||
v-model:value="scenario.name"
|
||||
type="text"
|
||||
placeholder='Дело №0 "Следствие ведут овечки"'
|
||||
/>
|
||||
|
||||
<p class="settings-header">
|
||||
Описание
|
||||
</p>
|
||||
<n-input v-model:value="scenario.description" type="textarea" placeholder='Убийство пастуха...' />
|
||||
<p class="settings-header">Описание</p>
|
||||
<n-input
|
||||
v-model:value="scenario.description"
|
||||
type="textarea"
|
||||
placeholder="Убийство пастуха..."
|
||||
/>
|
||||
|
||||
<p class="settings-header">
|
||||
Картинка
|
||||
</p>
|
||||
<n-input v-model:value="scenario.image" type="text" placeholder='default_scenario.png' disabled />
|
||||
<n-upload multiple directory-dnd :max="1" v-model:file-list="fileList">
|
||||
<n-upload-dragger>
|
||||
<n-text style="font-size: 16px">
|
||||
Щелкните или перетащите файл в эту область для загрузки
|
||||
</n-text>
|
||||
</n-upload-dragger>
|
||||
</n-upload>
|
||||
<p class="settings-header">Картинка</p>
|
||||
<n-input
|
||||
v-model:value="scenario.image"
|
||||
type="text"
|
||||
placeholder="default_scenario.png"
|
||||
disabled
|
||||
/>
|
||||
<n-upload multiple directory-dnd :max="1" v-model:file-list="fileList">
|
||||
<n-upload-dragger>
|
||||
<n-text style="font-size: 16px">
|
||||
Щелкните или перетащите файл в эту область для загрузки
|
||||
</n-text>
|
||||
</n-upload-dragger>
|
||||
</n-upload>
|
||||
|
||||
<n-button @click="updateScenario()" ghost>
|
||||
Сохранить изменения
|
||||
</n-button>
|
||||
<n-button @click="updateScenario()" ghost> Сохранить изменения </n-button>
|
||||
|
||||
<hr class="settings-hr">
|
||||
<hr class="settings-hr" />
|
||||
|
||||
<p>
|
||||
Введите название сценария <n-text class="name-text" strong>{{ scenario.name }}</n-text> чтобы
|
||||
удалить
|
||||
его
|
||||
</p>
|
||||
<n-input v-model:value="deletedScenarioName" type="text"
|
||||
placeholder='Дело №0 "Следствие ведут овечки"' />
|
||||
<n-button @click="deleteScenario(scenario.id!)" type="error" ghost
|
||||
:disabled="deletedScenarioName != scenario.name">
|
||||
Удалить сценарий
|
||||
</n-button>
|
||||
</n-space>
|
||||
<template #footer>
|
||||
</template>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
<p>
|
||||
Введите название сценария
|
||||
<n-text class="name-text" strong>{{ scenario.name }}</n-text> чтобы удалить его
|
||||
</p>
|
||||
<n-input
|
||||
v-model:value="deletedScenarioName"
|
||||
type="text"
|
||||
placeholder='Дело №0 "Следствие ведут овечки"'
|
||||
/>
|
||||
<n-button
|
||||
@click="deleteScenario(scenario.id!)"
|
||||
type="error"
|
||||
ghost
|
||||
:disabled="deletedScenarioName != scenario.name"
|
||||
>
|
||||
Удалить сценарий
|
||||
</n-button>
|
||||
</n-space>
|
||||
<template #footer> </template>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.settings-block {
|
||||
height: 40px;
|
||||
height: 40px;
|
||||
|
||||
/* background-color: brown; */
|
||||
/* background-color: brown; */
|
||||
}
|
||||
|
||||
.settings-button {
|
||||
float: right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.settings-icon {
|
||||
width: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.name-text {
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
background-color: rgb(255 255 255 / 10%);
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
background-color: rgb(255 255 255 / 10%);
|
||||
}
|
||||
|
||||
.settings-header {
|
||||
margin-top: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.settings-hr {
|
||||
margin: 20px 0;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.places-container {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
overflow-y: auto;
|
||||
padding: 20px 0;
|
||||
height: calc(100vh - 150px);
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
overflow-y: auto;
|
||||
padding: 20px 0;
|
||||
height: calc(100vh - 150px);
|
||||
|
||||
/* border: 1px solid red; */
|
||||
/* border: 1px solid red; */
|
||||
}
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.places-container {
|
||||
padding: 20px 250px;
|
||||
height: calc(100vh - 70px);
|
||||
}
|
||||
.places-container {
|
||||
padding: 20px 250px;
|
||||
height: calc(100vh - 70px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user