Последняя версия с сервера прошлого разработчика

This commit is contained in:
2025-07-10 04:35:51 +00:00
commit c731570032
1174 changed files with 134314 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
<template>
<meta-head title="Мессенджер"></meta-head>
<div class="flex sm:grid grid-cols-12 h-full overflow-hidden">
<!-- flex-shrink-0 -->
<div ref="userSidebar" class="h-full sm:h-auto transition-transform z-50 absolute transform-gpu -translate-x-full w-64 sm:relative sm:transform-none sm:w-auto col-span-4 bg-indigo-200 border-l border-r border-indigo-300 py-7">
<div class="mb-7 px-2 xl:px-8">
<div class="relative">
<text-input v-model="inputSearchRoom"
class="pr-12 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light w-full" placeholder="Поиск"
/>
<svg xmlns="http://www.w3.org/2000/svg" width="24"
height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="text-gray-light absolute right-3 top-2"
><circle cx="11" cy="11"
r="8"
></circle><line x1="21" y1="21"
x2="16.65" y2="16.65"
></line></svg>
</div>
<div class="flex flex-col lg:flex-row lg:space-x-6 mt-2">
<div class="flex items-center">
<input id="room-search-1" v-model="typeSearch"
:value="1" type="radio"
class="text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent cursor-pointer"
>
<label for="room-search-1" class="cursor-pointer select-none ml-2 text-gray-light text-sm">по сообщениям</label>
</div>
<div class="flex items-center">
<input id="room-search-2" v-model="typeSearch"
:value="2" type="radio"
class="text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent cursor-pointer"
>
<label for="room-search-2" class="cursor-pointer select-none ml-2 text-gray-light text-sm">по пользователям</label>
</div>
</div>
</div>
<div class="text-right">
<button class="default mb-2 text-orange text-sm mr-1" @click="openFriendList">
открыть список друзей
</button>
</div>
<div data-simplebar class="messsage-height overflow-auto">
<div class="divide-y divide-indigo-300 border-t border-b border-indigo-300">
<board-room-list v-for="room in userRooms" :key="room.id"
class="pt-5 pb-5"
:class="{ 'bg-indigo-300': room.classActive }"
:room="room"
@select-room="changeRoom"
/>
</div>
</div>
</div>
<div class="flex-1 w-full sm:flex-none sm:w-auto col-span-8 bg-indigo-200 overflow-hidden relative">
<button class="default text-center left-2 top-3 absolute z-40 flex sm:hidden items-center text-white text-xs" @click="openSidebar">
<svg xmlns="http://www.w3.org/2000/svg" width="24"
height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-menu"
><line x1="3" y1="12"
x2="21" y2="12"
></line><line x1="3" y1="6"
x2="21" y2="6"
></line><line x1="3" y1="18"
x2="21" y2="18"
></line></svg>
<span class="ml-1">открыть список пользователей</span>
</button>
<board-message :room-id="selectRoom" :user="selectUser"
:frozen="selectFrozenRoom" :search="searchOnlyMessage"
@disable="interactDisable" @last-message="updateRoom"
@change-room="touchRoom" @leave-room="leaveRoom"
/>
</div>
</div>
</template>
<script>
import { ref, toRef, watch } from 'vue'
import { onClickOutside } from '@vueuse/core'
import { usePage } from '@inertiajs/inertia-vue3'
import { Inertia } from '@inertiajs/inertia'
import debounce from 'lodash/debounce'
import pickBy from 'lodash/pickBy'
import Layout from '@/Shared/Layout.vue'
import MetaHead from '@/Shared/MetaHead.vue'
import TextInput from '@/Shared/Form/TextInput.vue'
import BoardRoomList from '@/Shared/Messanger/BoardRoomList.vue'
import BoardMessage from '@/Shared/Messanger/BoardMessage.vue'
export default {
components: {
MetaHead,
TextInput,
BoardRoomList,
BoardMessage,
},
layout: Layout,
props: {
rooms: {
type: Array,
default: () => []
},
roomSearch: {
type: String,
default: ''
}
},
setup(props){
var inputSearchRoom = ref(props.roomSearch)
const typeSearch = ref(1)
const searchOnlyMessage = ref('')
var userRooms = toRef(props, 'rooms')
var selectUser = ref(null)
var selectRoom = ref(0)
var selectFrozenRoom = ref(false)
var userSidebar = ref(null)
var canChangeRoom = ref(true)
watch(inputSearchRoom, debounce((search) => {
selectUser.value = null
selectRoom.value = 0
if(typeSearch.value === 1){
searchOnlyMessage.value = search
}
Inertia.get(route('messenger.index'), pickBy({ search: search, type: search ? typeSearch.value : null }), { preserveState: true })
}, 500))
watch(typeSearch, () => {
inputSearchRoom.value = ''
})
const checkSelectedActiveUser = () => {
const activeRoom = userRooms.value.find(userRoom => userRoom.classActive === true)
if(activeRoom){
selectUser.value = activeRoom.correspond
selectRoom.value = activeRoom.id
selectFrozenRoom.value = activeRoom.is_freeze
}
}
checkSelectedActiveUser()
function openFriendList() {
selectUser.value = null
selectRoom.value = 0
userRooms.value.forEach(item => item.classActive = false)
}
const touchRoom = (id) => {
const activeRoom = userRooms.value.find(userRoom => userRoom.id === id)
if(activeRoom){
activeRoom.classActive = true
selectUser.value = activeRoom.correspond
selectRoom.value = activeRoom.id
selectFrozenRoom.value = activeRoom.is_freeze
}
}
const leaveRoom = () => {
selectRoom.value = 0
selectUser.value = null
selectFrozenRoom.value = false
}
const changeRoom = (room) => {
closeSidebar()
if(canChangeRoom.value){
selectRoom.value = room.id
selectUser.value = room.correspond
selectFrozenRoom.value = room.is_freeze
const lastActiveRoom = userRooms.value.find(userRoom => userRoom.classActive === true)
if(lastActiveRoom){
lastActiveRoom.classActive = false
}
const nowActiveRoom = userRooms.value.find(userRoom => userRoom.id === room.id)
nowActiveRoom.classActive = true
if(!nowActiveRoom.is_my_message && !nowActiveRoom.is_reading){
nowActiveRoom.is_reading = true
usePage().props.value.message_reading_count--
}
}
}
let openSidebar = () => {
if (window.matchMedia('(max-width: 640px)').matches) {
userSidebar.value.classList.remove('-translate-x-full')
userSidebar.value.classList.add('-translate-x-0')
userSidebar.value.classList.add('shadow-classic')
}
}
let closeSidebar = () => {
if (window.matchMedia('(max-width: 640px)').matches) {
userSidebar.value.classList.add('-translate-x-full')
userSidebar.value.classList.remove('-translate-x-0')
userSidebar.value.classList.remove('shadow-classic')
}
}
let interactDisable = (type) => {
if(type === true){
canChangeRoom.value = false
}else{
canChangeRoom.value = true
}
}
let updateRoom = (message) => {
const upRoom = userRooms.value.find(userRoom => userRoom.id === message.chat_room_id)
upRoom.message = message.message
upRoom.is_my_message = true
upRoom.is_reading = false
upRoom.updated_at = message.updated_at_room
upRoom.updated_at_human = message.updated_at_room_human
userRooms.value.sort(function(a, b) {
if (a.updated_at > b.updated_at) {
return -1
}
if (a.updated_at < b.updated_at) {
return 1
}
return 0
})
}
if (window.matchMedia('(max-width: 640px)').matches) {
onClickOutside(userSidebar, () => {
closeSidebar()
})
}
return {
changeRoom,
selectUser,
userRooms,
selectRoom,
openSidebar,
userSidebar,
closeSidebar,
interactDisable,
updateRoom,
inputSearchRoom,
typeSearch,
searchOnlyMessage,
selectFrozenRoom,
touchRoom,
leaveRoom,
openFriendList,
}
},
}
</script>