| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- import { Injectable } from '@angular/core';
- import { FmodeParse, FmodeObject } from 'fmode-ng/parse';
- 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 {
-
- /**
- * 获取阶段预设话术
- */
- getStageTemplates(stage: string): string[] {
- return MESSAGE_TEMPLATES[stage as keyof typeof MESSAGE_TEMPLATES] || [];
- }
-
- /**
- * 创建文本消息
- */
- async createTextMessage(
- projectId: string,
- stage: string,
- content: string,
- currentUser: FmodeObject
- ): Promise<DeliveryMessage> {
- 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<DeliveryMessage> {
- 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<void> {
- 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<DeliveryMessage[]> {
- 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<DeliveryMessage[]> {
- const allMessages = await this.getProjectMessages(projectId);
- return allMessages.filter(msg => msg.stage === stage);
- }
-
- /**
- * 🔥 发送消息到企业微信当前窗口
- */
- private async sendToWxwork(text: string, imageUrls: string[] = []): Promise<void> {
- try {
- // 检查是否在企业微信环境中
- const isWxwork = window.location.href.includes('/wxwork/');
- if (!isWxwork) {
- console.log('⚠️ 非企业微信环境,跳过发送');
- return;
- }
- // 动态导入企业微信 JSSDK
- const ww = await import('@wecom/jssdk');
-
- console.log('📧 准备发送消息到企业微信...');
- console.log(' 文本:', text);
- console.log(' 图片数量:', imageUrls.length);
-
- // 🔥 发送文本消息
- if (text) {
- await ww.sendChatMessage({
- msgtype: 'text',
- text: {
- content: text
- }
- });
- console.log('✅ 文本消息已发送');
- }
-
- // 🔥 发送图片消息(使用news图文消息类型)
- for (let i = 0; i < imageUrls.length; i++) {
- const imageUrl = imageUrls[i];
- try {
- // 使用news类型发送图文消息,可以显示图片预览
- await ww.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 ww.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);
- // 发送失败不影响主流程,只记录错误
- }
- }
- }
|