feat: add group management - create, join, member panel with owner controls

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
congsh
2026-04-17 17:53:58 +08:00
parent 00fdb02d80
commit 6895fd05be
5 changed files with 502 additions and 47 deletions
+3 -47
View File
@@ -5,6 +5,7 @@ import { useRoute } from 'vue-router'
import { useGroupStore } from '@/stores/group'
import TeamSessionPanel from '@/components/team/TeamSessionPanel.vue'
import IdleMembersList from '@/components/team/IdleMembersList.vue'
import GroupMembersPanel from '@/components/group/GroupMembersPanel.vue'
const route = useRoute()
const groupStore = useGroupStore()
@@ -133,54 +134,9 @@ async function refreshMembers() {
</section>
</div>
<!-- 右列: 群组信息侧边栏 -->
<!-- 右列: 群组成员管理面板 -->
<aside class="right-col">
<div class="info-card">
<h3 class="info-card-title">群组信息</h3>
<div class="info-list">
<div class="info-row">
<span class="info-label">群组名</span>
<span class="info-value">{{ group?.name || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">群主</span>
<span class="info-value highlight">{{ ownerName }}</span>
</div>
<div class="info-row">
<span class="info-label">成员数</span>
<span class="info-value">{{ members.length }}</span>
</div>
<div class="info-row">
<span class="info-label">最大容量</span>
<span class="info-value">{{ group?.maxMembers || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">创建时间</span>
<span class="info-value">{{ group?.created ? new Date(group.created).toLocaleDateString('zh-CN') : '-' }}</span>
</div>
</div>
</div>
<!-- 成员状态统计 -->
<div class="info-card">
<h3 class="info-card-title">成员状态</h3>
<div class="status-stats">
<div v-for="(list, status) in membersByStatus" :key="status" class="stat-item">
<span class="stat-dot" :style="{ background: statusColors[status] }" />
<span class="stat-label">{{ statusLabels[status] }}</span>
<span class="stat-count">{{ list.length }}</span>
<div class="stat-bar-bg">
<div
class="stat-bar-fill"
:style="{
width: members.length ? (list.length / members.length * 100) + '%' : '0%',
background: statusColors[status]
}"
/>
</div>
</div>
</div>
</div>
<GroupMembersPanel />
</aside>
</div>
</div>
+31
View File
@@ -8,6 +8,8 @@ import { useNotificationStore } from '@/stores/notification'
import StatusToggle from '@/components/team/StatusToggle.vue'
import WorkScheduleModal from '@/components/team/WorkScheduleModal.vue'
import NotificationPanel from '@/components/common/NotificationPanel.vue'
import CreateGroupDialog from '@/components/group/CreateGroupDialog.vue'
import JoinGroupDialog from '@/components/group/JoinGroupDialog.vue'
const router = useRouter()
const route = useRoute()
@@ -17,6 +19,8 @@ const teamStore = useTeamStore()
const notificationStore = useNotificationStore()
const showScheduleModal = ref(false)
const showCreateGroup = ref(false)
const showJoinGroup = ref(false)
onMounted(async () => {
await userStore.initUser()
@@ -67,6 +71,10 @@ function goHome() {
<div class="sidebar-groups">
<div class="section-header">
<span class="section-title">我的群组</span>
<div class="section-actions">
<button class="section-btn" @click="showCreateGroup = true" title="创建群组">+</button>
<button class="section-btn" @click="showJoinGroup = true" title="加入群组">&#x1F517;</button>
</div>
</div>
<div v-if="groupStore.groups.length === 0" class="empty-groups">
暂无群组
@@ -129,6 +137,8 @@ function goHome() {
<!-- 弹窗 -->
<WorkScheduleModal v-model="showScheduleModal" />
<NotificationPanel />
<CreateGroupDialog v-model="showCreateGroup" />
<JoinGroupDialog v-model="showJoinGroup" />
</div>
</template>
@@ -242,6 +252,27 @@ function goHome() {
letter-spacing: 0.5px;
}
.section-actions {
display: flex;
gap: 4px;
}
.section-btn {
background: none;
border: 1px solid var(--gg-border);
border-radius: 6px;
color: var(--gg-text-secondary);
font-size: 14px;
cursor: pointer;
padding: 2px 8px;
transition: all 0.2s;
}
.section-btn:hover {
border-color: var(--gg-primary);
color: var(--gg-primary);
}
.empty-groups {
text-align: center;
color: var(--gg-text-muted);