import { Injectable } from '@angular/core'; import { FmodeParse, FmodeObject } from 'fmode-ng/parse'; import { WxworkSDKService } from '../../../modules/project/services/wxwork-sdk.service'; const Parse = FmodeParse.with('nova'); /** * 消息类型 */ export type MessageType = 'text' | 'image' | 'text_with_image'; /** * 交付消息接口 */ export interface DeliveryMessage { id?: string; project: string; // 项目ID stage: string; // 阶段 (white_model/soft_decor/rendering/post_process) messageType: MessageType; // 消息类型 content: string; // 文本内容 images?: string[]; // 图片URL数组 sentBy: string; // 发送人ID sentByName?: string; // 发送人姓名 sentAt: Date; // 发送时间 } /** * 预设话术模板 */ export const MESSAGE_TEMPLATES = { white_model: [ '老师我这里硬装模型做好了,看下是否有问题,如果没有,我去做渲染', '老师,白模阶段完成,请查看确认', '硬装结构已完成,请审阅' ], soft_decor: [ '软装好了,准备渲染,有问题可以留言', '老师,软装设计已完成,请查看', '家具配置完成,准备进入渲染阶段' ], rendering: [ '老师,渲染图已完成,请查看效果', '效果图已出,请审阅', '渲染完成,请查看是否需要调整' ], post_process: [ '老师,后期处理完成,请验收', '最终成品已完成,请查看', '所有修图完成,请确认' ] }; /** * 交付消息服务 */ @Injectable({ providedIn: 'root' }) export class DeliveryMessageService { constructor(private wxworkService: WxworkSDKService) {} /** * 获取阶段预设话术 */ getStageTemplates(stage: string): string[] { return MESSAGE_TEMPLATES[stage as keyof typeof MESSAGE_TEMPLATES] || []; } /** * 创建文本消息 */ async createTextMessage( projectId: string, stage: string, content: string, currentUser: FmodeObject ): Promise { const message: DeliveryMessage = { project: projectId, stage, messageType: 'text', content, sentBy: currentUser.id!, sentByName: currentUser.get('name') || '未知用户', sentAt: new Date() }; // 🔥 保存到数据库 await this.saveMessageToProject(projectId, message); // 🔥 发送到企业微信 await this.sendToWxwork(content, []); return message; } /** * 创建图片消息 */ async createImageMessage( projectId: string, stage: string, imageUrls: string[], content: string = '', currentUser: FmodeObject ): Promise { const message: DeliveryMessage = { project: projectId, stage, messageType: content ? 'text_with_image' : 'image', content, images: imageUrls, sentBy: currentUser.id!, sentByName: currentUser.get('name') || '未知用户', sentAt: new Date() }; // 🔥 保存到数据库 await this.saveMessageToProject(projectId, message); // 🔥 发送到企业微信 await this.sendToWxwork(content, imageUrls); return message; } /** * 保存消息到项目data字段 */ private async saveMessageToProject(projectId: string, message: DeliveryMessage): Promise { try { const query = new Parse.Query('Project'); const project = await query.get(projectId); const data = project.get('data') || {}; const messages = data.deliveryMessages || []; // 生成消息ID message.id = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; messages.push(message); data.deliveryMessages = messages; project.set('data', data); await project.save(); console.log('✅ 消息已保存到项目:', message.id); } catch (error) { console.error('❌ 保存消息失败:', error); throw error; } } /** * 获取项目的所有消息 */ async getProjectMessages(projectId: string): Promise { try { const query = new Parse.Query('Project'); const project = await query.get(projectId); const data = project.get('data') || {}; return data.deliveryMessages || []; } catch (error) { console.error('❌ 获取消息失败:', error); return []; } } /** * 获取特定阶段的消息 */ async getStageMessages(projectId: string, stage: string): Promise { const allMessages = await this.getProjectMessages(projectId); return allMessages.filter(msg => msg.stage === stage); } /** * 🔥 发送消息到企业微信当前窗口 */ private async sendToWxwork(text: string, imageUrls: string[] = []): Promise { try { console.log('🔍 [sendToWxwork] ========== 开始发送流程 =========='); console.log('🔍 [sendToWxwork] 当前URL:', window.location.href); // 检查是否在企业微信环境中 const isWxwork = window.location.href.includes('/wxwork/'); console.log('🔍 [sendToWxwork] 企业微信环境检测:', isWxwork); if (!isWxwork) { console.warn('⚠️ 非企业微信环境,跳过发送'); console.warn('⚠️ 请从企业微信客户端的侧边栏打开应用'); console.warn('⚠️ URL应该包含 /wxwork/ 路径'); return; } // 从URL获取cid和appId const urlParts = window.location.pathname.split('/'); console.log('🔍 [sendToWxwork] URL路径分段:', urlParts); const wxworkIndex = urlParts.indexOf('wxwork'); console.log('🔍 [sendToWxwork] wxwork位置索引:', wxworkIndex); const cid = urlParts[wxworkIndex + 1]; const appId = urlParts[wxworkIndex + 2] || 'crm'; console.log('🔍 [sendToWxwork] 提取的CID:', cid); console.log('🔍 [sendToWxwork] 提取的AppID:', appId); if (!cid || cid === 'undefined') { throw new Error('❌ 无法从URL获取CID,请检查URL格式'); } // 初始化WxworkSDKService console.log('🔍 [sendToWxwork] 开始初始化企业微信SDK...'); await this.wxworkService.initialize(cid, appId); console.log('✅ [sendToWxwork] SDK初始化完成'); console.log('📧 准备发送消息到企业微信...'); console.log(' CID:', cid); console.log(' AppID:', appId); console.log(' 文本内容:', text || '(无文本)'); console.log(' 图片数量:', imageUrls.length); console.log(' 图片URL列表:', imageUrls); // 🔥 发送文本消息 if (text) { await this.wxworkService.sendChatMessage({ msgtype: 'text', text: { content: text } }); console.log('✅ 文本消息已发送'); } // 🔥 发送图片消息(使用news图文消息类型) for (let i = 0; i < imageUrls.length; i++) { const imageUrl = imageUrls[i]; try { // 使用news类型发送图文消息,可以显示图片预览 await this.wxworkService.sendChatMessage({ msgtype: 'news', news: { link: imageUrl, title: `图片 ${i + 1}/${imageUrls.length}`, desc: '点击查看大图', imgUrl: imageUrl } }); console.log(`✅ 图文消息 ${i + 1}/${imageUrls.length} 已发送: ${imageUrl}`); // 避免发送过快,加入小延迟 if (i < imageUrls.length - 1) { await new Promise(resolve => setTimeout(resolve, 300)); } } catch (imgError) { console.error(`❌ 图片 ${i + 1} 发送失败:`, imgError); // 如果news类型失败,降级为纯文本链接 try { await this.wxworkService.sendChatMessage({ msgtype: 'text', text: { content: `📷 图片 ${i + 1}/${imageUrls.length}\n${imageUrl}` } }); console.log(`✅ 已改用文本方式发送图片链接`); } catch (textError) { console.error(`❌ 文本方式也失败:`, textError); } } } console.log('✅ 所有消息已发送到企业微信'); } catch (error) { console.error('❌ 发送消息到企业微信失败:', error); // 🔥 修复:必须抛出错误,让上层知道发送失败 throw error; } } }