Files
IM-web-new/src/components/sidebar/ContactList.vue
T
2026-06-30 10:13:48 +07:00

104 lines
3.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<aside class="conversation-list">
<header class="list-header">
<div>
<h2>联系人</h2>
<p>{{ contacts.contacts.length }} 位好友</p>
</div>
<div class="header-actions">
<button class="icon-button" title="添加联系人" @click="openAddContact">+</button>
<button class="icon-button" title="刷新" @click="contacts.refreshContacts({ force: true })">↻</button>
</div>
</header>
<div class="search-box">
<input v-model.trim="keyword" placeholder="搜索联系人">
</div>
<div class="sidebar-scroll">
<button
v-for="item in filteredContacts"
:key="item.id"
class="conversation-item"
:class="{ active: item.id === contacts.activeId }"
@click="contacts.setActiveContact(item.id)"
>
<img v-if="item.portrait" class="conversation-avatar image-avatar" :src="item.portrait" alt="">
<span v-else class="conversation-avatar">{{ item.avatarText }}</span>
<span class="conversation-copy">
<strong>{{ item.title }}</strong>
<small>{{ item.subtitle }}</small>
</span>
</button>
<div v-if="!filteredContacts.length" class="empty-list">
<strong>{{ contacts.loading ? '正在加载' : '暂无联系人' }}</strong>
<span>{{ contacts.loading ? '请稍候' : '好友同步完成后会显示在这里' }}</span>
</div>
</div>
<div v-if="addingContact" class="modal-backdrop" @click.self="closeAddContact">
<form class="modal-panel" @submit.prevent="submitAddContact">
<header>
<strong>添加联系人</strong>
<button type="button" class="icon-button" title="关闭" @click="closeAddContact">×</button>
</header>
<label>
<span>用户ID / 手机号 / 用户名</span>
<input v-model.trim="addKeyword" autocomplete="off" placeholder="请输入要添加的联系人">
</label>
<p v-if="contacts.actionError" class="form-error">{{ contacts.actionError }}</p>
<p v-if="contacts.actionInfo" class="form-info">{{ contacts.actionInfo }}</p>
<div class="modal-actions">
<button type="button" class="ghost-inline-action" @click="closeAddContact">取消</button>
<button class="primary-inline-action" :disabled="contacts.loading || !addKeyword">
{{ contacts.loading ? '添加中...' : '添加' }}
</button>
</div>
</form>
</div>
</aside>
</template>
<script setup>
import { computed, ref } from 'vue';
import { useContactStore } from '@/stores/contacts';
const contacts = useContactStore();
const keyword = ref('');
const addingContact = ref(false);
const addKeyword = ref('');
const filteredContacts = computed(() => {
const value = keyword.value.toLowerCase();
if (!value) {
return contacts.contacts;
}
return contacts.contacts.filter(item => {
return item.title.toLowerCase().includes(value)
|| item.subtitle.toLowerCase().includes(value)
|| item.uid.toLowerCase().includes(value);
});
});
function openAddContact() {
contacts.actionError = '';
contacts.actionInfo = '';
addKeyword.value = '';
addingContact.value = true;
}
function closeAddContact() {
addingContact.value = false;
}
async function submitAddContact() {
const added = await contacts.addContact(addKeyword.value);
if (added) {
window.setTimeout(() => {
addingContact.value = false;
}, 500);
}
}
</script>