This commit is contained in:
2025-05-16 17:50:08 +02:00
parent 573aa5cda7
commit 10e727f375
3 changed files with 65 additions and 24 deletions
+1
View File
@@ -39,6 +39,7 @@ declare module 'vue' {
LinkShareButton: typeof import('./src/components/link/LinkShareButton.vue')['default']
LinkShareTelegramButton: typeof import('./src/components/link/LinkShareTelegramButton.vue')['default']
ManagePlacementInstructions: typeof import('./src/components/manage/ManagePlacementInstructions.vue')['default']
MapCoors: typeof import('./src/components/MapCoors.vue')['default']
ProgressSpinner: typeof import('primevue/progressspinner')['default']
QRCodeCard: typeof import('./src/components/manage/QRCodeCard.vue')['default']
QRCodePlacementIcon: typeof import('./src/components/manage/QRCodePlacementIcon.vue')['default']
+16
View File
@@ -0,0 +1,16 @@
<template>
<iframe v-if="src" :src allowfullscreen class="w-full h-auto aspect-square" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps<{
coords: Omit<GeolocationPosition['coords'], 'toJSON'>
}>()
const src = computed(
() =>
`https://yandex.ru/map-widget/v1/?ll=${encodeURIComponent(props.coords.longitude + ',' + props.coords.latitude)}&mode=routes&rtext=~${encodeURIComponent(props.coords.latitude + ',' + props.coords.longitude)}&rtt=auto&ruri=~&z=18`,
)
</script>
@@ -1,42 +1,52 @@
<template>
<div class="place-self-stretch flex flex-col">
<div
v-for="message in messages"
:key="message._id"
:id="`msg-${message.created_at}`"
class="mb-4 max-w-md"
v-for="doc in docs"
:key="doc._id"
:id="`msg-${doc.created_at}`"
class="mb-4"
:class="{
'ml-auto text-right': message.from === userRole,
'mr-auto text-left': message.from !== userRole,
'max-w-md': doc.type === 'message',
'ml-auto text-right': doc.type === 'message' && doc.from === userRole,
'mr-auto text-left': doc.type === 'message' && doc.from !== userRole,
}"
>
<Card
class="p-card-sm"
:class="{
'bg-blue-50 dark:bg-blue-900 border-blue-300 dark:border-blue-700 text-blue-500 dark:text-blue-200':
message.from === userRole,
doc.from === userRole,
'bg-gray-50 dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300':
message.from !== userRole,
doc.from !== userRole,
}"
>
<template #content>
{{ message.body }}
<template v-if="doc.type === 'message'">
{{ doc.body }}
</template>
<template v-if="doc.type === 'geolocation'">
<MapCoors :coords="doc.coords" />
</template>
</template>
</Card>
</div>
<slot
name="endOfMessages"
:count="messages.length"
:lastMessage="messages.length > 0 ? messages[messages.length - 1] : null"
:count="docs.length"
:lastMessage="docs.length > 0 ? docs[docs.length - 1] : null"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { messagesDbLocal as db, messagesDbRemote as remoteDb } from '@/api/dbs'
import { type MessageDocument } from '@hereconnect/types'
import {
messagesDbLocal as db,
messagesDbRemote as remoteDb,
geolocationsDbRemote,
} from '@/api/dbs'
import { type MessageDocument, type GeolocationDocument } from '@hereconnect/types'
const { qr_code_uri, chat, userRole } = defineProps<{
qr_code_uri: MessageDocument['qr_code_uri']
@@ -45,7 +55,7 @@ const { qr_code_uri, chat, userRole } = defineProps<{
}>()
// Локальные состояния
const messages = ref<MessageDocument[]>([])
const docs = ref<(MessageDocument | GeolocationDocument)[]>([])
let changesSubscription: PouchDB.Core.Changes<MessageDocument> | null = null
let syncMessages: PouchDB.Replication.Sync<MessageDocument> | null = null
@@ -60,11 +70,25 @@ const messageSelector = {
// Загрузка сообщений
async function loadMessages() {
try {
const result = await db.find({
selector: messageSelector,
limit: Number.MAX_SAFE_INTEGER,
})
messages.value = result.docs as MessageDocument[]
const result = await Promise.all([
db.find({
selector: messageSelector,
limit: Number.MAX_SAFE_INTEGER,
}),
geolocationsDbRemote.find({
selector: {
type: 'geolocation',
qr_code_uri,
chat,
},
}),
])
docs.value = [
...(result[0].docs as MessageDocument[]),
...(result[1].docs as GeolocationDocument[]),
].sort((a, b) => (a.created_at > b.created_at ? 1 : -1))
} catch (error) {
console.error('Ошибка загрузки сообщений:', error)
}
@@ -81,16 +105,16 @@ function watchChanges() {
})
.on('change', (change: { doc?: MessageDocument }) => {
if (change.doc) {
const index = messages.value.findIndex((m) => m._id === change.doc!._id)
const index = docs.value.findIndex((m) => m._id === change.doc!._id)
if (index === -1) {
// Если сообщения нет, добавляем его
messages.value.push(change.doc)
docs.value.push(change.doc)
} else {
// Если сообщение существует, обновляем его
messages.value[index] = change.doc
docs.value[index] = change.doc
}
// Сортируем массив сообщений
messages.value.sort((a, b) => (a.created_at > b.created_at ? 1 : -1))
docs.value.sort((a, b) => (a.created_at > b.created_at ? 1 : -1))
}
})
.on('error', (err) => {
@@ -138,7 +162,7 @@ const emit = defineEmits<{
}>()
watch(
() => messages.value?.length,
() => docs.value?.length,
async () => {
await nextTick()
emit('scrollToBottom')