| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { WxworkCorp } from 'fmode-ng/core';
- import { FmodeObject } from 'fmode-ng/parse';
- // 群聊消息
- interface ChatMessage {
- id: string;
- sender: string;
- senderName: string;
- content: string;
- time: Date;
- isCustomer: boolean;
- needsReply: boolean; // 是否需要回复
- replyTime?: Date; // 回复时间
- }
- /**
- * 群聊信息汇总组件
- *
- * 功能:
- * 1. 展示群聊中客户的历史消息
- * 2. 一键筛选客户消息
- * 3. 未回复消息提示(超过10分钟)
- * 4. 群聊介绍文案自动发送
- */
- @Component({
- selector: 'app-group-chat-summary',
- standalone: true,
- imports: [CommonModule],
- templateUrl: './group-chat-summary.component.html',
- styleUrls: ['./group-chat-summary.component.scss']
- })
- export class GroupChatSummaryComponent implements OnInit, OnChanges {
- @Input() groupChat: FmodeObject | null = null;
- @Input() contact: FmodeObject | null = null;
- @Input() cid: string = '';
- // 群聊消息
- messages: ChatMessage[] = [];
- customerMessages: ChatMessage[] = []; // 客户消息
- unreadMessages: ChatMessage[] = []; // 未回复消息
-
- // UI状态
- loading: boolean = false;
- showOnlyCustomer: boolean = false; // 只看客户消息
- showOnlyUnread: boolean = false; // 只看未回复
- collapsed: boolean = true; // 折叠状态
-
- // 统计
- totalMessages: number = 0;
- customerMessageCount: number = 0;
- unreadCount: number = 0;
-
- // 群聊介绍
- groupIntro: string = '';
- introSent: boolean = false;
- // 企微SDK
- wecorp: WxworkCorp | null = null;
- constructor() {}
- ngOnInit() {
- this.initWxwork();
- this.loadGroupIntro();
- }
- ngOnChanges(changes: SimpleChanges) {
- if (changes['groupChat'] && this.groupChat) {
- this.loadChatMessages();
- }
- }
- /**
- * 初始化企微SDK
- */
- async initWxwork() {
- if (this.cid) {
- try {
- // @ts-ignore
- this.wecorp = new WxworkCorp(this.cid);
- } catch (err) {
- console.error('初始化企微SDK失败:', err);
- }
- }
- }
- /**
- * 加载群介绍文案
- */
- loadGroupIntro() {
- // 默认群介绍文案
- this.groupIntro = `
- 欢迎加入映三色设计服务群!👋
- 我是您的专属设计顾问,很高兴为您服务。
- 📋 服务流程:
- 1️⃣ 需求沟通 - 了解您的设计需求
- 2️⃣ 方案设计 - 提供专业设计方案
- 3️⃣ 方案优化 - 根据您的反馈调整
- 4️⃣ 交付执行 - 完成设计并交付
- ⏰ 服务时间:工作日 9:00-18:00
- 📞 紧急联系:请直接拨打客服电话
- 有任何问题随时在群里@我,我会及时回复您!💙
- `.trim();
-
- // 检查是否已发送
- this.checkIntroSent();
- }
- /**
- * 检查群介绍是否已发送
- */
- async checkIntroSent() {
- if (!this.groupChat) return;
-
- const data = this.groupChat.get('data') || {};
- this.introSent = data.introSent || false;
- }
- /**
- * 发送群介绍
- */
- async sendGroupIntro() {
- if (!this.groupChat || !this.wecorp) {
- window?.fmode?.alert('群聊信息不完整,无法发送');
- return;
- }
- try {
- const chatId = this.groupChat.get('chat_id');
- if (!chatId) {
- window?.fmode?.alert('群聊ID不存在');
- return;
- }
- // 调用企微API发送消息
- await this.wecorp.appchat.send({
- chatid: chatId,
- msgtype: 'text',
- text: {
- content: this.groupIntro
- }
- });
- // 标记已发送
- const data = this.groupChat.get('data') || {};
- data.introSent = true;
- data.introSentAt = new Date();
- this.groupChat.set('data', data);
- await this.groupChat.save();
- this.introSent = true;
- window?.fmode?.alert('群介绍已发送!');
- } catch (err: any) {
- console.error('发送群介绍失败:', err);
- window?.fmode?.alert('发送失败: ' + (err.message || '未知错误'));
- }
- }
- /**
- * 加载群聊消息
- */
- async loadChatMessages() {
- if (!this.groupChat) return;
- this.loading = true;
-
- try {
- // 从 groupChat.data 获取聊天记录
- const data = this.groupChat.get('data') || {};
- const chatHistory = data.chatHistory || [];
-
- // 转换为消息对象
- this.messages = chatHistory.map((msg: any) => ({
- id: msg.msgid || Math.random().toString(36).substr(2, 9),
- sender: msg.from,
- senderName: msg.fromName || msg.from,
- content: this.extractMessageContent(msg),
- time: new Date(msg.msgtime * 1000),
- isCustomer: this.isCustomerMessage(msg.from),
- needsReply: this.checkNeedsReply(msg),
- replyTime: msg.replyTime ? new Date(msg.replyTime) : undefined
- })).filter((msg: ChatMessage) => msg.content); // 过滤空消息
-
- // 统计
- this.totalMessages = this.messages.length;
- this.customerMessages = this.messages.filter(m => m.isCustomer);
- this.customerMessageCount = this.customerMessages.length;
-
- // 检查未回复消息
- this.checkUnreadMessages();
-
- console.log(`✅ 加载了 ${this.totalMessages} 条消息,客户消息 ${this.customerMessageCount} 条`);
- } catch (err) {
- console.error('加载群聊消息失败:', err);
- } finally {
- this.loading = false;
- }
- }
- /**
- * 提取消息内容
- */
- extractMessageContent(msg: any): string {
- if (msg.msgtype === 'text' && msg.text) {
- return msg.text.content || '';
- } else if (msg.msgtype === 'image') {
- return '[图片]';
- } else if (msg.msgtype === 'file') {
- return '[文件]';
- } else if (msg.msgtype === 'voice') {
- return '[语音]';
- } else if (msg.msgtype === 'video') {
- return '[视频]';
- }
- return '';
- }
- /**
- * 判断是否为客户消息
- */
- isCustomerMessage(sender: string): boolean {
- // 企微外部联系人ID通常以 wm 或 wo 开头
- return sender.startsWith('wm') || sender.startsWith('wo');
- }
- /**
- * 检查是否需要回复
- */
- checkNeedsReply(msg: any): boolean {
- // 如果是客户消息且没有回复时间
- if (this.isCustomerMessage(msg.from) && !msg.replyTime) {
- const msgTime = new Date(msg.msgtime * 1000);
- const now = new Date();
- const diff = now.getTime() - msgTime.getTime();
-
- // 超过10分钟未回复
- return diff > 10 * 60 * 1000;
- }
- return false;
- }
- /**
- * 检查未回复消息
- */
- checkUnreadMessages() {
- this.unreadMessages = this.customerMessages.filter(msg => {
- const now = new Date();
- const diff = now.getTime() - msg.time.getTime();
- return diff > 10 * 60 * 1000 && !msg.replyTime;
- });
-
- this.unreadCount = this.unreadMessages.length;
-
- // 如果有超过10分钟未回复的消息,发送通知
- if (this.unreadCount > 0) {
- this.sendUnreadNotification();
- }
- }
- /**
- * 发送未回复通知
- */
- async sendUnreadNotification() {
- // 这里可以调用企微API发送应用消息通知
- console.log(`⚠️ 有 ${this.unreadCount} 条消息超过10分钟未回复`);
-
- // TODO: 实现企微应用消息推送
- // 需要后端配合实现推送到技术人员手机
- }
- /**
- * 切换折叠状态
- */
- toggleCollapse() {
- this.collapsed = !this.collapsed;
- }
- /**
- * 只看客户消息
- */
- toggleCustomerFilter() {
- this.showOnlyCustomer = !this.showOnlyCustomer;
- this.showOnlyUnread = false;
- }
- /**
- * 只看未回复
- */
- toggleUnreadFilter() {
- this.showOnlyUnread = !this.showOnlyUnread;
- this.showOnlyCustomer = false;
- }
- /**
- * 获取显示的消息列表
- */
- getDisplayMessages(): ChatMessage[] {
- if (this.showOnlyUnread) {
- return this.unreadMessages;
- } else if (this.showOnlyCustomer) {
- return this.customerMessages;
- }
- return this.messages;
- }
- /**
- * 打开企微群聊
- */
- async openGroupChat() {
- if (!this.groupChat) return;
-
- try {
- const chatId = this.groupChat.get('chat_id');
- if (chatId && this.wecorp) {
- // 使用企微SDK打开群聊
- // @ts-ignore - WxworkCorp API
- await this.wecorp.openChat?.(chatId);
- } else {
- window?.fmode?.alert('群聊ID不存在');
- }
- } catch (err) {
- console.error('打开群聊失败:', err);
- window?.fmode?.alert('打开群聊失败');
- }
- }
- /**
- * 格式化时间
- */
- formatTime(date: Date): string {
- if (!date) return '';
-
- const now = new Date();
- const diff = now.getTime() - date.getTime();
-
- // 小于1分钟
- if (diff < 60 * 1000) {
- return '刚刚';
- }
-
- // 小于1小时
- if (diff < 60 * 60 * 1000) {
- const minutes = Math.floor(diff / (60 * 1000));
- return `${minutes}分钟前`;
- }
-
- // 小于24小时
- if (diff < 24 * 60 * 60 * 1000) {
- const hours = Math.floor(diff / (60 * 60 * 1000));
- return `${hours}小时前`;
- }
-
- // 超过24小时
- const month = date.getMonth() + 1;
- const day = date.getDate();
- const hour = date.getHours();
- const minute = date.getMinutes();
- return `${month}/${day} ${hour}:${minute.toString().padStart(2, '0')}`;
- }
- /**
- * 获取未回复时长
- */
- getUnreadDuration(date: Date): string {
- const now = new Date();
- const diff = now.getTime() - date.getTime();
- const minutes = Math.floor(diff / (60 * 1000));
-
- if (minutes < 60) {
- return `${minutes}分钟`;
- } else {
- const hours = Math.floor(minutes / 60);
- return `${hours}小时`;
- }
- }
- /**
- * 获取当前时间戳
- */
- getCurrentTime(): number {
- return Date.now();
- }
- }
|