1.右上角样式修改

2.发起群聊样式修改
3.首页-视讯样式修改
main
ysn 5 days ago
parent 6d3ebd0bb7
commit c80902dab3
  1. 5
      src/layout/components/Navbar.vue
  2. 303
      src/views/message/components/CreateGroupDialog.vue
  3. 19
      src/views/videoCommunication/index.vue

@ -117,10 +117,7 @@
<div class="avatar-container right-menu-item hover-effect"> <div class="avatar-container right-menu-item hover-effect">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<span class="user-nickname" v-if="userInfo.group"> <span class="user-nickname" v-if="userInfo.group">
所属单位 所属单位:{{ userInfo.group }}
<el-link type="primary" :underline="false">
{{ userInfo.group }}
</el-link>
</span> </span>
</div> </div>
</div> </div>

@ -21,11 +21,15 @@
style="margin-bottom: 10px" style="margin-bottom: 10px"
/> />
<!-- 标签页 --> <!-- 无搜索时展示标签页 -->
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tabs v-if="!isSearching" v-model="activeName" @tab-click="handleClick">
<!-- 最近联系人 --> <!-- 最近联系人 -->
<el-tab-pane label="最近联系人" name="recentContacts"> <el-tab-pane label="最近联系人" name="recentContacts">
<div v-loading="loading" class="contact-list"> <div
v-loading="loading"
class="contact-list"
@scroll="handleScroll"
>
<div <div
v-for="member in displayMembers" v-for="member in displayMembers"
:key="member.id" :key="member.id"
@ -60,12 +64,25 @@
v-if="!loading && displayMembers.length === 0" v-if="!loading && displayMembers.length === 0"
description="暂无联系人" description="暂无联系人"
/> />
<div v-if="loadMoreLoading" class="load-more-tip">
加载更多...
</div>
<div
v-if="contactNoMore && displayMembers.length > 0"
class="load-more-tip"
>
没有更多数据了
</div>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- 最近群组 --> <!-- 最近群组 -->
<el-tab-pane label="最近群组" name="recentGroups"> <el-tab-pane label="最近群组" name="recentGroups">
<div v-loading="loading" class="contact-list"> <div
v-loading="loading"
class="contact-list"
@scroll="handleScroll"
>
<div v-for="group in recentGroups" :key="group.id"> <div v-for="group in recentGroups" :key="group.id">
<!-- 群组标题 --> <!-- 群组标题 -->
<div <div
@ -133,6 +150,15 @@
v-if="!loading && recentGroups.length === 0" v-if="!loading && recentGroups.length === 0"
description="暂无群组" description="暂无群组"
/> />
<div v-if="loadMoreLoading" class="load-more-tip">
加载更多...
</div>
<div
v-if="groupNoMore && recentGroups.length > 0"
class="load-more-tip"
>
没有更多数据了
</div>
</div> </div>
</el-tab-pane> </el-tab-pane>
@ -196,6 +222,47 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<!-- 有搜索内容隐藏tab展示搜索结果同事列表 -->
<div v-else class="search-result-wrap">
<div class="search-title">同事</div>
<div v-loading="loading" class="contact-list">
<div
v-for="member in displayMembers"
:key="member.id"
:class="[
'member-item',
{
active: isSelected(member.id),
offline: !member.online,
},
]"
@click="toggleSelect(member)"
>
<el-checkbox
v-model="member.selected"
:disabled="isSelectDisabled && !member.selected"
@change="toggleSelect(member)"
>
<div class="member-item-label">
<el-avatar
:src="
$store.state.user.netConfig.MINIO_ENDPOINT_HTTPS +
member.avatar
"
icon="el-icon-user-solid"
/>
<span class="member-name">{{ member.name }}</span>
<span v-if="member.online" class="online-dot" />
</div>
</el-checkbox>
</div>
<el-empty
v-if="!loading && displayMembers.length === 0"
description="未匹配到同事"
/>
</div>
</div>
</el-col> </el-col>
<!-- 右侧已选人员 --> <!-- 右侧已选人员 -->
@ -299,11 +366,18 @@ export default {
activeName: "recentContacts", activeName: "recentContacts",
searchText: "", searchText: "",
loading: false, loading: false,
loadMoreLoading: false,
confirmLoading: false, confirmLoading: false,
selectedMembers: [], selectedMembers: [],
contactPage: 1,
groupPage: 1,
pageSize: 10,
memberList: [], memberList: [],
recentGroups: [], recentGroups: [],
treeData: [], treeData: [],
contactNoMore: false, //
groupNoMore: false, //
isSearching: false,
}; };
}, },
computed: { computed: {
@ -320,27 +394,45 @@ export default {
methods: { methods: {
show() { show() {
this.visible = true; this.visible = true;
this.resetPage();
this.loadData(); this.loadData();
}, },
//
resetPage() {
this.contactPage = 1;
this.groupPage = 1;
this.contactNoMore = false;
this.groupNoMore = false;
this.memberList = [];
this.recentGroups = [];
},
async loadData() { async loadData() {
await Promise.all([ await Promise.all([
this.fetchRecentContacts(), this.fetchRecentContacts(true),
this.fetchRecentGroups(), this.fetchRecentGroups(true),
this.fetchOrgTree(), this.fetchOrgTree(),
]); ]);
}, },
// /**
async fetchRecentContacts() { * 获取联系人列表
this.loading = true; * @param {Boolean} isReset true=首页刷新false=滚动追加
*/
async fetchRecentContacts(isReset = false) {
// return
if (this.contactNoMore && !isReset) return;
if (isReset) this.loading = true;
else this.loadMoreLoading = true;
try { try {
const res = await getMessagesLatestContacts({ const res = await getMessagesLatestContacts({
scene: 1, scene: 1,
page: 1, page: this.contactPage,
size: 65535, size: this.pageSize,
}); });
const list = res.data?.list || []; const list = res.data?.list || [];
this.memberList = list.map((item) => ({ const formatList = list.map((item) => ({
id: item.id, id: item.id,
name: item.name, name: item.name,
role: item.role, role: item.role,
@ -353,24 +445,47 @@ export default {
online: item.online === 1 || item.online === true, online: item.online === 1 || item.online === true,
selected: this.isSelected(item.id), selected: this.isSelected(item.id),
})); }));
if (isReset) {
this.memberList = formatList;
} else {
this.memberList.push(...formatList);
}
// <
if (list.length < this.pageSize) {
this.contactNoMore = true;
} else {
this.contactNoMore = false;
}
} catch (e) { } catch (e) {
console.error("获取最近联系人失败", e); console.error("获取最近联系人失败", e);
this.memberList = []; if (isReset) this.memberList = [];
} finally { } finally {
this.loading = false; this.loading = false;
this.loadMoreLoading = false;
} }
}, },
// //
async fetchRecentGroups() { loadMoreContacts() {
// /
if (this.loadMoreLoading || this.contactNoMore) return;
this.contactPage++;
this.fetchRecentContacts(false);
},
async fetchRecentGroups(isReset = false) {
if (this.groupNoMore && !isReset) return;
try { try {
const res = await getMessagesLatestContacts({ const res = await getMessagesLatestContacts({
scene: 4, scene: 4,
page: 1, page: this.groupPage,
size: 65535, size: this.pageSize,
}); });
const list = res.data?.list || []; const list = res.data?.list || [];
this.recentGroups = list.map((item) => ({ const formatGroups = list.map((item) => ({
id: item.id, id: item.id,
name: item.name, name: item.name,
avatar: item.avatar, avatar: item.avatar,
@ -378,13 +493,32 @@ export default {
allSelected: false, allSelected: false,
members: [], members: [],
})); }));
if (isReset) {
this.recentGroups = formatGroups;
} else {
this.recentGroups.push(...formatGroups);
}
//
if (list.length < this.pageSize) {
this.groupNoMore = true;
} else {
this.groupNoMore = false;
}
} catch (e) { } catch (e) {
console.error("获取最近群组失败", e); console.error("获取最近群组失败", e);
this.recentGroups = []; if (isReset) this.recentGroups = [];
} }
}, },
// //
loadMoreGroups() {
if (this.loadMoreLoading || this.groupNoMore) return;
this.groupPage++;
this.fetchRecentGroups(false);
},
async fetchOrgTree() { async fetchOrgTree() {
try { try {
const res = await getGroupsList(); const res = await getGroupsList();
@ -396,7 +530,22 @@ export default {
} }
}, },
// //
handleScroll(e) {
const target = e.target;
const scrollTop = target.scrollTop;
const scrollHeight = target.scrollHeight;
const clientHeight = target.clientHeight;
// 50px
if (scrollTop + clientHeight >= scrollHeight - 50) {
if (this.activeName === "recentContacts") {
this.loadMoreContacts();
} else if (this.activeName === "recentGroups") {
this.loadMoreGroups();
}
}
},
buildOrgTree(list) { buildOrgTree(list) {
if (!list || list.length === 0) return []; if (!list || list.length === 0) return [];
return list.map((item) => ({ return list.map((item) => ({
@ -412,7 +561,6 @@ export default {
})); }));
}, },
//
async loadOrgUsers(node) { async loadOrgUsers(node) {
if (node.isLoaded || node.type === "user" || node.type === "all") return; if (node.isLoaded || node.type === "user" || node.type === "all") return;
if (node.hasChildren && node.children && node.children.length > 0) { if (node.hasChildren && node.children && node.children.length > 0) {
@ -450,13 +598,15 @@ export default {
} }
}, },
//
async handleSearch() { async handleSearch() {
const text = this.searchText.trim(); const text = this.searchText.trim();
if (!text) { if (!text) {
await this.fetchRecentContacts(); this.isSearching = false;
this.resetPage();
await this.fetchRecentContacts(true);
return; return;
} }
this.isSearching = true;
this.loading = true; this.loading = true;
try { try {
const res = await searchUsers({ const res = await searchUsers({
@ -479,6 +629,8 @@ export default {
online: item.online === 1 || item.online === true, online: item.online === 1 || item.online === true,
selected: this.isSelected(item.id), selected: this.isSelected(item.id),
})); }));
//
this.contactNoMore = true;
} catch (e) { } catch (e) {
console.error("搜索联系人失败", e); console.error("搜索联系人失败", e);
} finally { } finally {
@ -486,21 +638,16 @@ export default {
} }
}, },
//
handleClearSearch() { handleClearSearch() {
this.searchText = ""; this.searchText = "";
this.fetchRecentContacts(); this.resetPage();
this.fetchRecentContacts(true);
}, },
//
handleClick(tab) { handleClick(tab) {
this.activeName = tab.name; this.activeName = tab.name;
if (tab.name === "recentGroups") {
this.loadGroupMembers();
}
}, },
//
async loadGroupMembers() { async loadGroupMembers() {
for (const group of this.recentGroups) { for (const group of this.recentGroups) {
if (!group.members || group.members.length === 0) { if (!group.members || group.members.length === 0) {
@ -522,17 +669,13 @@ export default {
} }
}, },
//
async toggleGroupExpand(group) { async toggleGroupExpand(group) {
group.expanded = !group.expanded; group.expanded = !group.expanded;
if (group.expanded) { if (group.expanded) {
// getMultiChatInfo
try { try {
const res = await getMultiChatInfo({ multi_chat_id: group.id }); const res = await getMultiChatInfo({ multi_chat_id: group.id });
const data = res.data || {}; const data = res.data || {};
// 使 user_id
const userList = data.user_list || []; const userList = data.user_list || [];
// ID
group.members = userList group.members = userList
.filter((item) => item.id !== data.user_id) .filter((item) => item.id !== data.user_id)
.map((item) => { .map((item) => {
@ -545,23 +688,19 @@ export default {
} }
}, },
//
async handleOrgNodeClick(data) { async handleOrgNodeClick(data) {
if (data.type === "org") { if (data.type === "org") {
this.$refs.orgTree.setCurrentKey(data.id); this.$refs.orgTree.setCurrentKey(data.id);
//
if (!data.isLoaded) { if (!data.isLoaded) {
await this.loadOrgUsers(data); await this.loadOrgUsers(data);
} }
} }
}, },
//
isSelected(userId) { isSelected(userId) {
return this.selectedMembers.some((m) => m.id === userId); return this.selectedMembers.some((m) => m.id === userId);
}, },
//
toggleSelect(member) { toggleSelect(member) {
if (this.isSelectDisabled && !member.selected) { if (this.isSelectDisabled && !member.selected) {
this.$message.warning(`最多只能选择${this.maxSelectCount}个成员`); this.$message.warning(`最多只能选择${this.maxSelectCount}个成员`);
@ -582,13 +721,10 @@ export default {
this.syncSelection(member); this.syncSelection(member);
}, },
//
syncSelection(member) { syncSelection(member) {
//
this.memberList.forEach((m) => { this.memberList.forEach((m) => {
if (m.id === member.id) m.selected = member.selected; if (m.id === member.id) m.selected = member.selected;
}); });
//
this.recentGroups.forEach((group) => { this.recentGroups.forEach((group) => {
if (group.members) { if (group.members) {
const groupMember = group.members.find((m) => m.id === member.id); const groupMember = group.members.find((m) => m.id === member.id);
@ -598,11 +734,9 @@ export default {
} }
} }
}); });
//
this.syncOrgTreeSelection(this.treeData, member); this.syncOrgTreeSelection(this.treeData, member);
}, },
//
syncOrgTreeSelection(nodes, member) { syncOrgTreeSelection(nodes, member) {
nodes.forEach((node) => { nodes.forEach((node) => {
if (node.id === member.id && node.type === "user") { if (node.id === member.id && node.type === "user") {
@ -615,7 +749,6 @@ export default {
}); });
}, },
//
toggleGroupAllSelect(group) { toggleGroupAllSelect(group) {
if (!group.members || group.members.length === 0) return; if (!group.members || group.members.length === 0) return;
if (group.allSelected) { if (group.allSelected) {
@ -624,16 +757,14 @@ export default {
const index = this.selectedMembers.findIndex( const index = this.selectedMembers.findIndex(
(m) => m.id === member.id (m) => m.id === member.id
); );
if (index >= 0) { if (index >= 0) this.selectedMembers.splice(index, 1);
this.selectedMembers.splice(index, 1);
}
}); });
group.allSelected = false; group.allSelected = false;
} else { } else {
const selectedCount = group.members.filter((m) => !m.selected).length; const unselectedCount = group.members.filter((m) => !m.selected).length;
if ( if (
this.maxSelectCount > 0 && this.maxSelectCount > 0 &&
this.selectedMembers.length + selectedCount > this.maxSelectCount this.selectedMembers.length + unselectedCount > this.maxSelectCount
) { ) {
this.$message.warning(`最多只能选择${this.maxSelectCount}个成员`); this.$message.warning(`最多只能选择${this.maxSelectCount}个成员`);
return; return;
@ -653,14 +784,10 @@ export default {
this.syncGroupSelection(group); this.syncGroupSelection(group);
}, },
//
syncGroupSelection(group) { syncGroupSelection(group) {
group.members.forEach((member) => { group.members.forEach((member) => this.syncSelection(member));
this.syncSelection(member);
});
}, },
//
handleOrgCheckAllChange(allNode) { handleOrgCheckAllChange(allNode) {
const parentNode = this.findParentNode(this.treeData, allNode.id); const parentNode = this.findParentNode(this.treeData, allNode.id);
if (!parentNode || !parentNode.children) return; if (!parentNode || !parentNode.children) return;
@ -693,16 +820,13 @@ export default {
users.forEach((user) => { users.forEach((user) => {
user.selected = false; user.selected = false;
const index = this.selectedMembers.findIndex((m) => m.id === user.id); const index = this.selectedMembers.findIndex((m) => m.id === user.id);
if (index >= 0) { if (index >= 0) this.selectedMembers.splice(index, 1);
this.selectedMembers.splice(index, 1);
}
}); });
allNode.indeterminate = false; allNode.indeterminate = false;
} }
users.forEach((user) => this.syncSelection(user)); users.forEach((user) => this.syncSelection(user));
}, },
//
findParentNode(nodes, childId, parent = null) { findParentNode(nodes, childId, parent = null) {
for (const node of nodes) { for (const node of nodes) {
if (node.id === childId) return parent; if (node.id === childId) return parent;
@ -714,7 +838,6 @@ export default {
return null; return null;
}, },
//
updateParentAllSelectStatus(userNode) { updateParentAllSelectStatus(userNode) {
const parentNode = this.findParentNode(this.treeData, userNode.id); const parentNode = this.findParentNode(this.treeData, userNode.id);
if (!parentNode || !parentNode.children) return; if (!parentNode || !parentNode.children) return;
@ -728,17 +851,14 @@ export default {
} }
}, },
//
removeSelected(member) { removeSelected(member) {
const index = this.selectedMembers.findIndex((m) => m.id === member.id); const index = this.selectedMembers.findIndex((m) => m.id === member.id);
if (index >= 0) { if (index >= 0) {
this.selectedMembers.splice(index, 1); this.selectedMembers.splice(index, 1);
member.selected = false;
this.syncSelection({ id: member.id, selected: false }); this.syncSelection({ id: member.id, selected: false });
} }
}, },
//
clearAllSelected() { clearAllSelected() {
this.selectedMembers = []; this.selectedMembers = [];
this.memberList.forEach((m) => (m.selected = false)); this.memberList.forEach((m) => (m.selected = false));
@ -749,7 +869,6 @@ export default {
this.clearOrgTreeSelected(this.treeData); this.clearOrgTreeSelected(this.treeData);
}, },
//
clearOrgTreeSelected(nodes) { clearOrgTreeSelected(nodes) {
nodes.forEach((node) => { nodes.forEach((node) => {
node.selected = false; node.selected = false;
@ -757,14 +876,13 @@ export default {
}); });
}, },
//
handleClose(done) { handleClose(done) {
this.clearAllSelected(); this.clearAllSelected();
this.searchText = ""; this.searchText = "";
this.resetPage();
this.visible = false; this.visible = false;
}, },
//
async confirmCreateGroup() { async confirmCreateGroup() {
if (this.selectedMembers.length < this.minSelectCount) { if (this.selectedMembers.length < this.minSelectCount) {
this.$message.warning(`至少选择${this.minSelectCount}个成员`); this.$message.warning(`至少选择${this.minSelectCount}个成员`);
@ -772,13 +890,10 @@ export default {
} }
this.confirmLoading = true; this.confirmLoading = true;
try { try {
// 1. props
if (typeof this.confirmCallback === "function") { if (typeof this.confirmCallback === "function") {
await this.confirmCallback(this.selectedMembers); await this.confirmCallback(this.selectedMembers);
} }
// 2. confirm
this.$emit("confirm", this.selectedMembers); this.$emit("confirm", this.selectedMembers);
// 3.
this.clearAllSelected(); this.clearAllSelected();
this.searchText = ""; this.searchText = "";
this.visible = false; this.visible = false;
@ -796,10 +911,28 @@ export default {
.body { .body {
height: 450px; height: 450px;
.search-result-wrap {
.search-title {
font-size: 14px;
font-weight: 500;
color: #606266;
padding: 6px 0 8px;
border-bottom: 1px solid #ebeef5;
margin-bottom: 8px;
}
}
.contact-list { .contact-list {
height: 400px; height: 400px;
overflow-y: auto; overflow-y: auto;
.load-more-tip {
text-align: center;
padding: 8px 0;
color: #909399;
font-size: 13px;
}
.member-item { .member-item {
display: flex; display: flex;
align-items: center; align-items: center;
@ -809,6 +942,15 @@ export default {
border-radius: 4px; border-radius: 4px;
transition: background 0.2s; transition: background 0.2s;
// el-checkbox
::v-deep .el-checkbox {
display: flex;
align-items: center;
}
::v-deep .el-checkbox__inner {
margin-top: 0 !important;
}
&:hover { &:hover {
background: #f5f7fa; background: #f5f7fa;
} }
@ -887,6 +1029,21 @@ export default {
padding: 5px; padding: 5px;
} }
//
.userline {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 16px;
::v-deep .el-checkbox {
display: flex;
align-items: center;
}
::v-deep .el-checkbox__inner {
margin-top: 0 !important;
}
}
.org-icon { .org-icon {
font-size: 16px; font-size: 16px;
color: #409eff; color: #409eff;
@ -983,14 +1140,6 @@ export default {
justify-content: center; justify-content: center;
} }
.userline {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 16px;
}
//
.group-detail-info { .group-detail-info {
padding: 12px 16px; padding: 12px 16px;
margin: 8px 0; margin: 8px 0;

@ -59,28 +59,22 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column label="会诊名称" prop="name" align="left">
label="会诊名称"
prop="name"
align="left"
width="490"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text"> <span class="table-column">
{{ scope.row.name }} {{ scope.row.name }}
</el-button> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="会议类型名称" label="会议类型名称"
prop="meet_type_name" prop="meet_type_name"
align="left" align="left"
width="420"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text"> <span class="table-column" style="font-weight: bold">
{{ scope.row.meet_type_name }} {{ scope.row.meet_type_name }}
</el-button> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" prop="create_time" align="left" /> <el-table-column label="创建时间" prop="create_time" align="left" />
@ -342,6 +336,9 @@ export default {
margin-right: 8px; margin-right: 8px;
} }
} }
.table-column {
color: #009696;
}
// //
.join-area { .join-area {

Loading…
Cancel
Save