Skip to content

Commit

Permalink
feat: ✨️联调通讯录
Browse files Browse the repository at this point in the history
  • Loading branch information
ZRMYDYCG committed Mar 6, 2025
1 parent b644543 commit 4843f20
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 190 deletions.
Binary file added src/assets/female.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/male.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/view/chat/components/chat-content.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ onMounted(() => {
await loadMore()
nextTick(() => {
await nextTick(() => {
const scrollHeightAfter = container.scrollHeight
// 维持原有滚动位置需要滚动的距离
Expand Down
128 changes: 88 additions & 40 deletions src/view/contacts/components/add-contact-dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
:close-on-click-modal="true"
@closed="handleClosed"
>
<GCColumn ref="gcColumnRef" v-loading="loading" class="!h-[400px]">
<GcColumn ref="gcColumnRef" v-loading="loading" class="!h-[400px]">
<template #header>
<el-form ref="searchFormRef" :model="searchFormMdl" class="search" @submit.prevent="handleSearchFriend">
<el-form-item prop="keywords">
<el-input v-model="searchFormMdl.keywords" placeholder="搜索" clearable>
<el-form-item prop="account">
<el-input v-model="searchFormMdl.account" placeholder="搜索" clearable>
<template #prefix>
<i class="ri-search-line"></i>
</template>
Expand All @@ -20,8 +20,7 @@
</el-form>
</template>

<!-- S 搜素结果 -->
<GCList
<GcList
ref="contactListRef"
:list="contactList"
:options="{
Expand All @@ -45,70 +44,119 @@
</div>
</div>
</template>
</GCList>
<!-- E 搜素结果 -->
</GCColumn>
</GcList>
</GcColumn>
</el-dialog>
</template>

<script setup lang="ts">
import GCColumn from '@/components/Column/index.vue'
import GCList from '@/components/List/index.vue'
import GcColumn from '@/components/Column/index.vue'
import GcList from '@/components/List/index.vue'
import { useCurrentInstance, useLoadMore, usePageList } from '@/hooks'
import type { ElForm } from 'element-plus'
import { nextTick, onMounted, reactive, ref } from 'vue'
import { formatServerFilePath } from '@/utils/helper/common.ts'
import { ElButton, ElForm, ElInput, ElMessage } from 'element-plus'
import { debounce } from 'lodash-es'
import { nextTick, onMounted, ref } from 'vue'
interface ContactItem {
user_id: string | number
avatar: string
interface Contact {
user_id: string
nickname: string
avatar: string
}
const { proxy } = useCurrentInstance()
const $api = proxy.$api
interface SearchForm {
account: string
}
const dialogVisible = ref(false)
const loading = ref(false)
const emit = defineEmits(['create-success'])
const { $api, $HTTP_CODE } = useCurrentInstance()
const dialogVisible = ref(true)
const searchFormRef = ref<InstanceType<typeof ElForm>>()
const searchFormMdl = reactive({
keywords: '',
const searchFormMdl = ref<SearchForm>({
account: '',
})
const {
list: contactList,
loading: listLoading,
loadding,
getPageList,
initData,
handleRefresh,
} = usePageList<ContactItem>({
} = usePageList<any>({
getPageListApi: $api.contact.getContactList,
searchParams: searchFormMdl,
})
const gcColumnRef = ref<InstanceType<typeof GCColumn>>()
const handleSearchFriend = async () => {
loadding.value = true
const params = {
...searchFormMdl.value,
}
const res = await $api.user
.searchUserList({
params,
})
.finally(() => {
loadding.value = false
})
const { code, data, message } = res.data
if (code === $HTTP_CODE.HTTP_SUCCESS_CODE) {
contactList.value = data.rows.map((contact: Contact) => {
contact.avatar = formatServerFilePath(contact.avatar)
return contact
})
}
}
// 加载更多逻辑
const gcColumnRef = ref(null)
onMounted(() => {
nextTick(() => {
const scrollContainer = gcColumnRef.value?.$el?.querySelector('.el-scrollbar__wrap')
if (scrollContainer) {
useLoadMore({
type: 'bottom',
scrollBottomCallback: getPageList,
container: scrollContainer,
distance: 150,
})
}
useLoadMore({
type: 'bottom',
scrollBottomCallback: getPageList,
container: gcColumnRef.value?.elScrollbar.wrapRef,
distance: 150,
})
})
})
const handleSearchFriend = () => {
handleRefresh()
}
const createLoading = ref(false)
const handleAdd = debounce((contact: Contact) => {
createContact(contact)
}, 50)
const createContact = async (contact: Contact) => {
if (createLoading.value) {
return false
}
createLoading.value = true
const { id: reciver_id } = contact
const params = {
reciver_id,
}
const res = await $api.contact.createContact(params).finally(() => {
createLoading.value = false
})
const handleAdd = (contact: ContactItem) => {
// console.log('添加为好友', contact)
const { code, message } = res.data
if (code === $HTTP_CODE.HTTP_SUCCESS_CODE) {
ElMessage.success({
message,
duration: 3000,
})
close()
emit('create-success')
} else {
ElMessage.error({
message,
duration: 3000,
})
}
}
const handleClosed = () => {
Expand Down
105 changes: 70 additions & 35 deletions src/view/contacts/components/contact-detail.vue
Original file line number Diff line number Diff line change
@@ -1,43 +1,12 @@
<script lang="ts" setup>
interface Contact {
remark: string
sex: number | string
desc: string
avatar: string
nickname: string
account: string
[key: string]: any
}
interface Props {
contact?: Contact
}
// 定义 props 和 emits
const emit = defineEmits(['set-contact-info'])
import { withDefaults } from 'vue'
withDefaults(defineProps<Props>(), {
contact: () => ({
remark: '',
sex: '',
desc: '',
avatar: '',
nickname: '',
account: '',
}),
})
</script>

<template>
<div class="contact-detail">
<div class="contact-detail-wrapper">
<div class="base-info flex items-center justify-between">
<div class="left">
<div class="nickname flex items-center">
<span>{{ contact.remark }}</span>
<img v-if="String(contact.sex) === '0'" class="sex" src="~@/assets/default_avatar.png" alt="" />
<img v-if="String(contact.sex) === '1'" class="sex" src="~@/assets/default_avatar.png" alt="" />
<img v-if="String(contact.sex) === '0'" class="sex" src="@/assets/female.png" alt="" />
<img v-if="String(contact.sex) === '1'" class="sex" src="@/assets/male.png" alt="" />
<el-button circle size="small" class="ml-[5px]" title="资料设置" @click="$emit('set-contact-info')">
<template #icon>
<i class="ri-edit-box-line"></i>
Expand All @@ -49,7 +18,7 @@ withDefaults(defineProps<Props>(), {

<div class="right">
<div class="avater">
<img :src="contact.avater" alt="" />
<img :src="contact.avatar" alt="" />
</div>
</div>
</div>
Expand All @@ -66,12 +35,78 @@ withDefaults(defineProps<Props>(), {
</div>

<div class="oprate">
<el-button type="primary" class="mx-auto !block w-[140px]">发消息</el-button>
<el-button type="primary" class="mx-auto !block w-[140px]" @click="handleGoSendMessage">发消息</el-button>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { useCurrentInstance } from '@/hooks'
import useChatStore from '@/store/modules/chat'
import { ElMessage } from 'element-plus'
import { debounce } from 'lodash-es'
import { defineEmits, defineProps } from 'vue'
import { useRouter } from 'vue-router'
interface Contact {
remark: string
sex: string
desc: string
avatar: string
nickname: string
account: string
reciver_id: string
}
const props = defineProps<{
contact: Contact
}>()
const emit = defineEmits<{
(event: 'set-contact-info'): void
}>()
const chatStore = useChatStore()
const router = useRouter()
const { $api, $HTTP_CODE } = useCurrentInstance()
const handleGoSendMessage = debounce(() => {
const hasChat = chatStore.chatList.some((chat) => {
return chat.reciver_id === props.contact.reciver_id
})
if (!hasChat) {
createChat(props.contact)
} else {
router.push({ path: '/chat/main' })
}
}, 50)
const createChat = async (contact: Contact) => {
const { reciver_id } = contact
const params = {
reciver_id,
type: '0',
}
const res = await $api.chat.createChat(params)
const { code, message } = res.data
if (code === $HTTP_CODE.HTTP_SUCCESS_CODE) {
await router.push({ path: '/chat/main' })
} else {
if (code === 400001002) {
await router.push({ path: '/chat/main' })
} else {
ElMessage.error({
message,
duration: 3000,
})
}
}
}
</script>

<style scoped>
@import './contact-detail.css';
</style>
Loading

0 comments on commit 4843f20

Please sign in to comment.