generated from VLADIMIR/template_frontend
up
This commit is contained in:
@@ -100,10 +100,13 @@ function getTextForCounter(count: number): string[] {
|
||||
<button
|
||||
class="game-button-run"
|
||||
type="submit"
|
||||
:aria-busy="isSubmitting"
|
||||
:disabled="props.gameStatus != 'run' || code.length == 0 || isSubmitting"
|
||||
v-on:click="addClickButton"
|
||||
>
|
||||
<HeaderText v-if="props.gameStatus == 'run'">Поехали</HeaderText>
|
||||
<HeaderText v-if="props.gameStatus == 'run'">{{
|
||||
isSubmitting ? 'Отправляем…' : 'Поехали'
|
||||
}}</HeaderText>
|
||||
<HeaderText v-if="props.gameStatus == 'pause' || props.gameStatus == 'draft'"
|
||||
>Ждём</HeaderText
|
||||
>
|
||||
|
||||
@@ -32,6 +32,9 @@ useDeviceContext(() => ({ teamID: teamId, password: typeof password === 'string'
|
||||
const newPlacesCount = ref(0)
|
||||
const actions = ref<TeamAction[]>([])
|
||||
const storyError = ref('')
|
||||
let storyRequestId = 0
|
||||
let pendingStoryRequests = 0
|
||||
let isSubmittingAction = false
|
||||
|
||||
const scrollContainer = ref<HTMLDivElement | null>()
|
||||
|
||||
@@ -73,8 +76,9 @@ const isAtBottom = () => {
|
||||
return container.scrollHeight - container.scrollTop - container.clientHeight < 1
|
||||
}
|
||||
|
||||
async function getStory() {
|
||||
const oldStory = story.value
|
||||
async function getStory(showLastPlace = false): Promise<boolean> {
|
||||
const requestId = ++storyRequestId
|
||||
pendingStoryRequests++
|
||||
|
||||
let res
|
||||
try {
|
||||
@@ -83,10 +87,15 @@ async function getStory() {
|
||||
password: password as string,
|
||||
})
|
||||
} catch (err) {
|
||||
if (requestId !== storyRequestId) return false
|
||||
storyError.value = 'Не удалось загрузить дело. Попробуйте обновить страницу.'
|
||||
console.error('Failed to load team story:', err)
|
||||
return
|
||||
return false
|
||||
} finally {
|
||||
pendingStoryRequests--
|
||||
}
|
||||
if (requestId !== storyRequestId) return false
|
||||
const oldStory = story.value
|
||||
storyError.value = ''
|
||||
game.value = res.game
|
||||
|
||||
@@ -103,7 +112,6 @@ async function getStory() {
|
||||
introduction: res.story!.introduction,
|
||||
places:
|
||||
res.story!.places?.map((item, i) => {
|
||||
console.log(oldStory?.places[i]?.mode)
|
||||
return {
|
||||
place: item,
|
||||
mode: oldStory?.places[i]?.mode || 'show',
|
||||
@@ -120,30 +128,51 @@ async function getStory() {
|
||||
}
|
||||
|
||||
await nextTick()
|
||||
if (wasAtBottom && oldCount != 0) {
|
||||
if (showLastPlace) {
|
||||
const container = scrollContainer.value
|
||||
const places = container?.querySelectorAll('.story-place')
|
||||
const lastPlace = places?.item(places.length - 1)
|
||||
if (container && lastPlace) {
|
||||
container.scrollTo({
|
||||
top:
|
||||
container.scrollTop +
|
||||
lastPlace.getBoundingClientRect().top -
|
||||
container.getBoundingClientRect().top,
|
||||
behavior: 'instant',
|
||||
})
|
||||
}
|
||||
newPlacesCount.value = 0
|
||||
} else if (wasAtBottom && oldCount != 0) {
|
||||
const container = scrollContainer.value
|
||||
if (!container) return false
|
||||
container.scrollTop = container.scrollHeight
|
||||
}
|
||||
return true
|
||||
}
|
||||
getStory()
|
||||
getAnswers()
|
||||
|
||||
async function addAction(newCode: string): Promise<boolean> {
|
||||
if (isSubmittingAction) return false
|
||||
isSubmittingAction = true
|
||||
// Ответ поллинга, начатого до хода, больше не должен обновлять дело.
|
||||
storyRequestId++
|
||||
try {
|
||||
await client.AddTeamAction({
|
||||
ID: teamId,
|
||||
password: password as string,
|
||||
code: newCode,
|
||||
})
|
||||
await getStory()
|
||||
code.value = ''
|
||||
await nextTick()
|
||||
newPlacesCount.value = 0
|
||||
if (!(await getStory(true))) {
|
||||
message.error('Ход сохранён, но не удалось обновить дело. Обновите страницу.')
|
||||
}
|
||||
return true
|
||||
} catch (err) {
|
||||
message.error(err instanceof Error ? err.message : 'Не удалось сделать ход')
|
||||
return false
|
||||
} finally {
|
||||
isSubmittingAction = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +292,7 @@ async function deleteLast() {
|
||||
}
|
||||
|
||||
useSimplePolling(() => {
|
||||
getStory()
|
||||
if (!isSubmittingAction && pendingStoryRequests === 0) void getStory()
|
||||
}, 2000)
|
||||
</script>
|
||||
|
||||
@@ -356,15 +385,18 @@ useSimplePolling(() => {
|
||||
</n-config-provider>
|
||||
</MessagePaper>
|
||||
|
||||
<PlaceBlock
|
||||
:place="advancedPlace.place"
|
||||
v-model:mode="advancedPlace.mode"
|
||||
<div
|
||||
v-for="(advancedPlace, index) in story.places"
|
||||
v-bind:key="`${game?.format}:${advancedPlace.place.code}`"
|
||||
:mcp="authStore.hasRole('author') && actions[index]?.mcp"
|
||||
:addAction="addAction"
|
||||
:key="`${game?.format}:${advancedPlace.place.code}`"
|
||||
class="story-place"
|
||||
>
|
||||
</PlaceBlock>
|
||||
<PlaceBlock
|
||||
:place="advancedPlace.place"
|
||||
v-model:mode="advancedPlace.mode"
|
||||
:mcp="authStore.hasRole('author') && actions[index]?.mcp"
|
||||
:addAction="addAction"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<MessagePaper
|
||||
class="qr-main-block"
|
||||
|
||||
Reference in New Issue
Block a user