update editor buttons

This commit is contained in:
2026-09-09 23:50:27 +07:00
parent 56aabd5b8b
commit 0753e704fc
40 changed files with 145 additions and 53 deletions
+18 -3
View File
@@ -61,6 +61,7 @@ const emit = defineEmits<{
'update:newPlaceName': [value: string]
'update:newPlaceText': [value: string]
'update:mode': [value: string]
navigate: [code: string | undefined]
}>()
const updateCode = (code: string) => {
emit('update:newPlaceCode', code)
@@ -271,7 +272,9 @@ const bottomApplications = computed<Application[]>(() => {
</div>
<div v-for="door in props.place?.doors" v-bind:key="door.code" class="door-block">
{{ door.name }}
<n-button class="door-button" @click.stop="emit('navigate', door.code)">
<span class="door-button-label">{{ door.name || door.code || 'Перейти к точке' }}</span>
</n-button>
<span v-for="key in door.keys" :key="key.name" class="key-block">
<Icon class="lock-icon">
<LockOutlined />
@@ -686,7 +689,7 @@ const bottomApplications = computed<Application[]>(() => {
background-color: #222;
border: 1px solid #222;
border-radius: 10px;
margin: 10px 0;
margin: var(--place-block-margin, 10px 0);
padding: 20px;
}
@@ -850,7 +853,19 @@ const bottomApplications = computed<Application[]>(() => {
color: #eee;
display: inline-block;
margin: 10px 5px 10px 0;
padding: 5px 10px;
max-width: 100%;
}
.door-button {
height: auto;
max-width: 100%;
min-height: 34px;
padding: 6px 12px;
}
.door-button-label {
overflow-wrap: anywhere;
white-space: normal;
}
.door-add-block {
+47 -11
View File
@@ -119,6 +119,26 @@ const editorPlaces = computed<EditablePlace[]>(() => {
return (scenario.value.story?.places || []) as EditablePlace[]
})
const scrollContainer = ref<HTMLElement | null>(null)
const placeCards = new Map<EditablePlace, HTMLElement>()
function navigateToPlace(code: string | undefined) {
const place = code
? editorPlaces.value.find((place) => (place.oldCode ?? place.code) === code)
: undefined
const card = place && placeCards.get(place)
const container = scrollContainer.value
if (!card || !container) {
message.error(code ? `Точка «${code}» не найдена` : 'У действия не указан код точки')
return
}
card.focus({ preventScroll: true })
container.scrollTo({
top: container.scrollTop + card.getBoundingClientRect().top - container.getBoundingClientRect().top - 10,
behavior: 'smooth',
})
}
// Вопросы дела со служебными полями редактора (oldCode, mode)
const editorQuestions = computed<EditableQuestion[]>(() => {
return (scenario.value.story?.questions || []) as EditableQuestion[]
@@ -600,7 +620,7 @@ function getRandomComplimentForNastya() {
</script>
<template>
<div class="center-block-custom">
<div ref="scrollContainer" class="center-block-custom">
<div class="width700">
<div class="places-container">
<n-alert
@@ -764,18 +784,23 @@ function getRandomComplimentForNastya() {
</n-flex>
</PlaceBlock>
<PlaceBlock
:place="place"
v-model:mode="place.mode"
<div
v-for="place in editorPlaces"
v-bind:key="place.oldCode ?? place.code ?? ''"
:key="place.oldCode ?? place.code ?? ''"
:ref="(el) => el ? placeCards.set(place, el as HTMLElement) : placeCards.delete(place)"
class="place-card"
tabindex="-1"
role="group"
:aria-label="`${place.code}: ${place.name}`"
>
<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)" :disabled="place.code == ''">Сохранить</n-button>
</n-flex>
</PlaceBlock>
<PlaceBlock :place="place" v-model:mode="place.mode" @navigate="navigateToPlace">
<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)" :disabled="place.code == ''">Сохранить</n-button>
</n-flex>
</PlaceBlock>
</div>
</div>
</div>
</div>
@@ -919,6 +944,17 @@ function getRandomComplimentForNastya() {
</template>
<style scoped>
.place-card {
--place-block-margin: 0;
border-radius: 10px;
margin: 10px 0;
}
.place-card:focus {
outline: 2px solid #63e2b7;
}
.conclusion-video {
width: 100%;
}