| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import { Component, OnInit, inject, signal } from '@angular/core';
- import { ActivatedRoute, Router } from '@angular/router';
- import { DatePipe } from '@angular/common';
- import { FaIconComponent } from '@fortawesome/angular-fontawesome';
- import { MockDataService } from '../../../core/services/mock-data.service';
- import { QiweApiService } from '../../../core/services/api/qiwe-api.service';
- import { environment } from '../../../../environments/environment';
- import type { Group, Document, RiskEvent } from '../../../core/models';
- import type { MessageDto } from '../../../core/services/api/qiwe-api.service';
- import { StatCardComponent } from '../../../shared/components/stat-card/stat-card.component';
- import { StatusBadgeComponent } from '../../../shared/components/status-badge/status-badge.component';
- import { MessageStripComponent } from '../../../shared/components/message-strip/message-strip.component';
- import { EmptyStateComponent } from '../../../shared/components/empty-state/empty-state.component';
- import { DataTableComponent } from '../../../shared/components/data-table/data-table.component';
- interface TabDef {
- key: string;
- label: string;
- }
- @Component({
- selector: 'app-group-detail',
- standalone: true,
- imports: [
- DatePipe, FaIconComponent,
- StatCardComponent, StatusBadgeComponent,
- MessageStripComponent, EmptyStateComponent, DataTableComponent,
- ],
- templateUrl: './group-detail.component.html',
- })
- export class GroupDetailComponent implements OnInit {
- private route = inject(ActivatedRoute);
- private router = inject(Router);
- private mockData = inject(MockDataService);
- private qiweApi = inject(QiweApiService);
- loading = true;
- dataSource = signal<'api' | 'mock'>('mock');
- group: Group | null = null;
- activeTab = 'info';
- documents: Document[] = [];
- riskEvents: RiskEvent[] = [];
- messages: MessageDto[] = [];
- messagesTotal = 0;
- chatMessagesTotal = 0;
- messagesLoading = false;
- messagesError = '';
- showSystemMessages = false;
- private static readonly MSG_TYPE_LABELS: Record<number, string> = {
- 0: '文本',
- 2: '文本',
- 13: '链接',
- 14: '图片',
- 31: '应用消息',
- 2063: '撤回',
- };
- readonly tabs: TabDef[] = [
- { key: 'info', label: '基本信息' },
- { key: 'messages', label: '群消息' },
- { key: 'members', label: '群成员' },
- { key: 'documents', label: '沟通记录' },
- { key: 'risk', label: '风控事件' },
- ];
- readonly docColumns = [
- { key: 'title', label: '文档标题' },
- { key: 'createdBy', label: '创建人' },
- { key: 'createdAt', label: '创建时间' },
- { key: 'complianceStatus', label: '状态', template: 'status' as const },
- ];
- get messageRows(): Array<MessageDto & { senderLabel: string; contentLabel: string; msgTypeLabel: string; timeLabel: string }> {
- return this.messages.map((m) => ({
- ...m,
- senderLabel: this.formatSenderLabel(m),
- contentLabel: this.formatMessageContent(m),
- msgTypeLabel: GroupDetailComponent.MSG_TYPE_LABELS[m.msgType] ?? `类型${m.msgType}`,
- timeLabel: new Date(m.timestamp).toLocaleString('zh-CN'),
- }));
- }
- private formatSenderLabel(m: MessageDto): string {
- if (m.senderName && m.senderName !== m.senderId) return m.senderName;
- if (!m.senderId) return '未知';
- return m.senderId;
- }
- private formatMessageContent(m: MessageDto): string {
- if (m.msgType === 2063) return '撤回了一条消息';
- let text = (m.content || '').trim();
- if (text.startsWith('{') || text.startsWith('[')) {
- try {
- const parsed = JSON.parse(text) as Record<string, unknown>;
- if (parsed['revokeMsgUniqueIdentifier']) return '撤回了一条消息';
- text = typeof parsed['content'] === 'string' ? parsed['content'].trim()
- : typeof parsed['title'] === 'string' ? parsed['title'].trim()
- : typeof parsed['linkUrl'] === 'string' ? parsed['linkUrl'].trim()
- : '';
- } catch {
- /* keep raw */
- }
- }
- if (text) return text;
- const labels: Record<number, string> = {
- 14: '[图片]', 16: '[语音]', 15: '[文件]', 22: '[视频]', 13: '[链接]',
- };
- return labels[m.msgType] ?? `(${GroupDetailComponent.MSG_TYPE_LABELS[m.msgType] ?? '无文本内容'})`;
- }
- readonly riskColumns = [
- { key: 'title', label: '事件名称' },
- { key: 'type', label: '类型' },
- { key: 'severity', label: '严重程度', template: 'status' as const },
- { key: 'status', label: '处理状态', template: 'status' as const },
- { key: 'createdAt', label: '发现时间' },
- ];
- ngOnInit(): void {
- this.route.paramMap.subscribe(params => {
- const id = params.get('id');
- if (id) void this.loadGroup(id);
- });
- }
- private async loadGroup(id: string): Promise<void> {
- this.loading = true;
- if (environment.useBackendApi) {
- const result = await this.qiweApi.getGroup(id);
- if (result.ok && result.data?.group) {
- this.group = this.qiweApi.mapToGroup(result.data.group);
- this.dataSource.set('api');
- this.documents = [];
- this.riskEvents = [];
- if (this.group.messageCountTotal > 0) {
- this.activeTab = 'messages';
- }
- await this.loadMessages(id);
- this.loading = false;
- return;
- }
- }
- this.group = this.mockData.getGroups().find(g => g.id === id) ?? null;
- if (this.group) {
- this.dataSource.set('mock');
- this.documents = this.mockData.getDocuments().filter(d => d.groupId === id);
- this.riskEvents = this.mockData.getRiskEvents().filter(e => e.groupId === id);
- }
- this.loading = false;
- }
- goBack(): void {
- this.router.navigate(['/groups']);
- }
- setActiveTab(key: string): void {
- this.activeTab = key;
- if (key === 'messages' && this.group && environment.useBackendApi && this.messages.length === 0) {
- void this.loadMessages(this.group.id);
- }
- }
- private async loadMessages(roomId: string): Promise<void> {
- if (!environment.useBackendApi) return;
- this.messagesLoading = true;
- this.messagesError = '';
- const result = await this.qiweApi.listMessages(roomId, 100, 0, !this.showSystemMessages);
- if (result.ok && result.data) {
- this.messages = result.data.messages;
- this.messagesTotal = result.data.total;
- this.chatMessagesTotal = result.data.chatTotal ?? result.data.messages.length;
- } else {
- this.messages = [];
- this.messagesTotal = 0;
- this.chatMessagesTotal = 0;
- this.messagesError = result.error ?? '加载消息失败';
- }
- this.messagesLoading = false;
- }
- toggleSystemMessages(): void {
- this.showSystemMessages = !this.showSystemMessages;
- if (this.group) void this.loadMessages(this.group.id);
- }
- }
|