微爱帮监狱寄信写信小程序工单系统技术方案:智能投诉处理与问题解决平台

一、系统概述与设计理念

1.1 工单系统核心价值

微爱帮作为特殊群体通信服务平台,工单系统不仅是问题处理工具,更是情感连接信任建立的关键环节。系统设计遵循以下原则:

复制代码
┌─────────────────────────────────────────────┐
│          微爱帮工单系统设计理念             │
├─────────────────────────────────────────────┤
│ ❶ 情感优先:识别用户情绪,提供情感支持     │
│ ❷ 高效闭环:快速响应,确保问题彻底解决     │
│ ❸ 隐私保护:敏感信息脱敏,保障用户隐私     │
│ ❹ 智能路由:自动分类,精准分配处理人员     │
│ ❺ 持续改进:数据分析驱动服务优化           │
└─────────────────────────────────────────────┘

1.2 系统架构概览

复制代码
┌─────────────────────────────────────────────────────┐
│                   用户交互层                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐         │
│  │ 微信小程序│  │  网页端  │  │  客服端  │         │
│  └──────────┘  └──────────┘  └──────────┘         │
└─────────────────────┬───────────────────────────────┘
┌─────────────────────▼───────────────────────────────┐
│                API网关层                            │
│         负载均衡 / 鉴权 / 限流 / 监控               │
└─────────────────────┬───────────────────────────────┘
┌─────────────────────▼───────────────────────────────┐
│               业务服务层                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐         │
│  │ 工单核心 │  │ 智能分配 │  │ 消息通知 │         │
│  │  服务    │  │  服务    │  │  服务    │         │
│  └──────────┘  └──────────┘  └──────────┘         │
└─────────────────────┬───────────────────────────────┘
┌─────────────────────▼───────────────────────────────┐
│               数据处理层                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐         │
│  │ 工单存储 │  │ 知识库   │  │ 分析引擎 │         │
│  │ (MySQL)  │  │ (ES)     │  │ (Spark)  │         │
│  └──────────┘  └──────────┘  └──────────┘         │
└─────────────────────────────────────────────────────┘

二、核心功能模块设计

2.1 工单数据结构与状态机

复制代码
# app/models/ticket.py
from datetime import datetime
from enum import Enum
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
import hashlib

class TicketPriority(Enum):
    """工单优先级"""
    LOW = "low"           # 低:一般咨询
    MEDIUM = "medium"     # 中:功能问题
    HIGH = "high"         # 高:投诉建议
    URGENT = "urgent"     # 紧急:服务中断
    CRITICAL = "critical" # 严重:司法/安全相关

class TicketStatus(Enum):
    """工单状态"""
    DRAFT = "draft"              # 草稿
    SUBMITTED = "submitted"      # 已提交
    ACKNOWLEDGED = "acknowledged" # 已确认
    IN_PROGRESS = "in_progress"  # 处理中
    PENDING = "pending"          # 等待回复
    RESOLVED = "resolved"        # 已解决
    CLOSED = "closed"            # 已关闭
    REOPENED = "reopened"        # 重新打开

class TicketCategory(Enum):
    """工单分类"""
    ACCOUNT = "account"          # 账户问题
    PAYMENT = "payment"          # 支付问题
    LETTER = "letter"            # 信件问题
    DELIVERY = "delivery"        # 投递问题
    CONTENT = "content"          # 内容审核
    PRIVACY = "privacy"          # 隐私问题
    COMPLAINT = "complaint"      # 投诉建议
    OTHER = "other"              # 其他

class UserEmotion(Enum):
    """用户情绪分析"""
    CALM = "calm"                # 平静
    ANXIOUS = "anxious"          # 焦虑
    ANGRY = "angry"              # 愤怒
    FRUSTRATED = "frustrated"    # 沮丧
    URGENT = "urgent"            # 急切
    GRATEFUL = "grateful"        # 感激

class TicketBase(BaseModel):
    """工单基础模型"""
    user_id: str = Field(..., description="用户ID")
    category: TicketCategory = Field(..., description="工单分类")
    priority: TicketPriority = Field(default=TicketPriority.MEDIUM)
    title: str = Field(..., min_length=5, max_length=200)
    description: str = Field(..., min_length=10, max_length=5000)
    attachments: List[str] = Field(default_factory=list)
    metadata: Dict[str, Any] = Field(default_factory=dict)

class TicketCreate(TicketBase):
    """创建工单请求"""
    contact_preference: str = Field(default="in_app", description="联系偏好")
    expected_resolution_time: Optional[int] = Field(None, description="期望解决时间(小时)")

class Ticket(TicketBase):
    """工单完整模型"""
    ticket_id: str = Field(..., description="工单唯一ID")
    status: TicketStatus = Field(default=TicketStatus.SUBMITTED)
    emotion_score: Optional[Dict[str, float]] = Field(None, description="情绪分析得分")
    assigned_to: Optional[str] = Field(None, description="分配给")
    assignee_role: Optional[str] = Field(None, description="处理人角色")
    source: str = Field(default="wechat_mini_program", description="来源渠道")
    ip_address: Optional[str] = Field(None, description="用户IP")
    user_agent: Optional[str] = Field(None, description="用户代理")
    
    # 时间戳
    created_at: datetime = Field(default_factory=datetime.now)
    updated_at: datetime = Field(default_factory=datetime.now)
    acknowledged_at: Optional[datetime] = None
    first_response_at: Optional[datetime] = None
    resolved_at: Optional[datetime] = None
    closed_at: Optional[datetime] = None
    
    # 性能指标
    first_response_time: Optional[int] = Field(None, description="首次响应时间(分钟)")
    resolution_time: Optional[int] = Field(None, description="解决时间(分钟)")
    satisfaction_score: Optional[int] = Field(None, ge=1, le=5, description="满意度评分")
    
    # 关联数据
    related_letter_ids: List[str] = Field(default_factory=list)
    related_order_ids: List[str] = Field(default_factory=list)
    
    class Config:
        orm_mode = True

class TicketUpdate(BaseModel):
    """工单更新模型"""
    status: Optional[TicketStatus] = None
    priority: Optional[TicketPriority] = None
    assigned_to: Optional[str] = None
    add_attachments: Optional[List[str]] = None
    metadata: Optional[Dict[str, Any]] = None

class TicketInteraction(BaseModel):
    """工单交互记录"""
    interaction_id: str
    ticket_id: str
    user_id: str
    user_type: str = Field(..., description="user/customer_service/system")
    content: str
    content_type: str = Field(default="text", description="text/image/voice/system_action")
    attachments: List[str] = Field(default_factory=list)
    internal_note: bool = Field(default=False, description="是否为内部备注")
    created_at: datetime = Field(default_factory=datetime.now)
    metadata: Dict[str, Any] = Field(default_factory=dict)

class TicketEscalation(BaseModel):
    """工单升级记录"""
    escalation_id: str
    ticket_id: str
    from_priority: TicketPriority
    to_priority: TicketPriority
    reason: str
    escalated_by: str
    escalated_at: datetime = Field(default_factory=datetime.now)
    notes: Optional[str] = None

2.2 智能工单处理引擎

复制代码
# app/services/ticket_engine.py
import asyncio
import re
from typing import Dict, List, Optional, Tuple, Any
from datetime import datetime, timedelta
import jieba
import jieba.analyse
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
import redis
import json

class IntelligentTicketEngine:
    """智能工单处理引擎"""
    
    def __init__(self):
        self.redis_client = redis.Redis(
            host=config('redis.host'),
            port=config('redis.port'),
            decode_responses=True
        )
        
        # 加载关键词库
        self.keyword_patterns = self._load_keyword_patterns()
        
        # 初始化情感分析模型(简化版)
        self.sentiment_keywords = {
            'positive': ['感谢', '满意', '很好', '帮助', '谢谢', '不错'],
            'negative': ['生气', '愤怒', '失望', '投诉', '垃圾', '骗人', '投诉'],
            'urgent': ['紧急', '马上', '立刻', '赶紧', '快', '急'],
            'legal': ['举报', '法律', '诉讼', '公安局', '司法', '监管']
        }
        
        # 工单路由规则
        self.routing_rules = self._load_routing_rules()
    
    async def process_new_ticket(self, ticket_data: Dict[str, Any]) -> Dict[str, Any]:
        """处理新工单 - 智能分析与路由"""
        
        # 1. 情感分析
        emotion_analysis = await self.analyze_emotion(
            ticket_data['title'] + " " + ticket_data['description']
        )
        
        # 2. 自动分类
        auto_category = await self.auto_categorize(ticket_data)
        
        # 3. 优先级评估
        auto_priority = await self.evaluate_priority(ticket_data, emotion_analysis)
        
        # 4. 检测紧急关键词
        urgent_keywords = self.detect_urgent_keywords(ticket_data)
        
        # 5. 相似工单搜索
        similar_tickets = await self.find_similar_tickets(ticket_data)
        
        # 6. 智能分配处理人
        assignee_recommendation = await self.recommend_assignee(
            auto_category, auto_priority, emotion_analysis
        )
        
        # 7. 生成处理建议
        handling_suggestions = await self.generate_handling_suggestions(
            ticket_data, emotion_analysis, similar_tickets
        )
        
        # 8. 风险评估
        risk_assessment = await self.assess_risk(ticket_data, emotion_analysis)
        
        # 9. 构建增强工单
        enhanced_ticket = {
            **ticket_data,
            'auto_analysis': {
                'emotion': emotion_analysis,
                'category': auto_category.value,
                'priority': auto_priority.value,
                'urgent_keywords': urgent_keywords,
                'similar_ticket_count': len(similar_tickets),
                'assignee_recommendation': assignee_recommendation,
                'handling_suggestions': handling_suggestions,
                'risk_level': risk_assessment['level'],
                'risk_reasons': risk_assessment['reasons'],
                'estimated_resolution_time': self.estimate_resolution_time(
                    auto_category, auto_priority, emotion_analysis
                )
            },
            'metadata': {
                'processed_by_ai': True,
                'ai_processing_time': datetime.now().isoformat(),
                'ai_version': '1.2.0'
            }
        }
        
        # 10. 触发自动化响应
        if auto_priority in [TicketPriority.HIGH, TicketPriority.URGENT]:
            await self.send_immediate_acknowledgment(ticket_data['user_id'], ticket_data['ticket_id'])
        
        # 11. 记录分析结果
        await self.record_analysis_result(ticket_data['ticket_id'], enhanced_ticket['auto_analysis'])
        
        return enhanced_ticket
    
    async def analyze_emotion(self, text: str) -> Dict[str, Any]:
        """分析用户情绪"""
        
        # 使用jieba分词
        words = jieba.lcut(text)
        
        # 情感得分计算
        emotion_scores = {
            'calm': 0.0,
            'anxious': 0.0,
            'angry': 0.0,
            'frustrated': 0.0,
            'urgent': 0.0,
            'grateful': 0.0
        }
        
        # 关键词匹配
        for word in words:
            if word in self.sentiment_keywords['positive']:
                emotion_scores['grateful'] += 0.3
                emotion_scores['calm'] += 0.1
            elif word in self.sentiment_keywords['negative']:
                emotion_scores['angry'] += 0.4
                emotion_scores['frustrated'] += 0.3
            elif word in self.sentiment_keywords['urgent']:
                emotion_scores['urgent'] += 0.5
                emotion_scores['anxious'] += 0.2
            elif word in self.sentiment_keywords['legal']:
                emotion_scores['angry'] += 0.6
                emotion_scores['urgent'] += 0.4
        
        # 标点符号分析
        exclamation_count = text.count('!') + text.count('!')
        question_count = text.count('?') + text.count('?')
        
        if exclamation_count > 3:
            emotion_scores['angry'] += 0.2 * min(exclamation_count, 10)
            emotion_scores['urgent'] += 0.1 * min(exclamation_count, 10)
        
        # 文本长度分析(长文本可能表示沮丧)
        if len(text) > 500:
            emotion_scores['frustrated'] += 0.2
        
        # 归一化得分
        total = sum(emotion_scores.values())
        if total > 0:
            for key in emotion_scores:
                emotion_scores[key] = round(emotion_scores[key] / total, 2)
        
        # 确定主要情绪
        primary_emotion = max(emotion_scores.items(), key=lambda x: x[1])
        
        return {
            'scores': emotion_scores,
            'primary': {
                'emotion': primary_emotion[0],
                'score': primary_emotion[1]
            },
            'indicators': {
                'exclamation_count': exclamation_count,
                'question_count': question_count,
                'text_length': len(text),
                'negative_word_count': sum(1 for w in words if w in self.sentiment_keywords['negative'])
            }
        }
    
    async def auto_categorize(self, ticket_data: Dict[str, Any]) -> TicketCategory:
        """自动分类工单"""
        text = f"{ticket_data['title']} {ticket_data['description']}".lower()
        
        # 关键词匹配
        category_keywords = {
            TicketCategory.ACCOUNT: ['账号', '登录', '密码', '注册', '认证', '实名'],
            TicketCategory.PAYMENT: ['支付', '退款', '扣款', '费用', '钱', '支付宝', '微信支付'],
            TicketCategory.LETTER: ['信件', '写信', '收信', '信纸', '信封', '内容', '字数'],
            TicketCategory.DELIVERY: ['投递', '快递', '邮寄', '物流', '送达', '运输', '时间', '延迟'],
            TicketCategory.CONTENT: ['审核', '敏感', '违禁', '屏蔽', '删除', '内容审核'],
            TicketCategory.PRIVACY: ['隐私', '信息', '泄露', '安全', '数据', '个人'],
            TicketCategory.COMPLAINT: ['投诉', '举报', '不满', '建议', '意见', '差评'],
            TicketCategory.OTHER: []  # 默认分类
        }
        
        # 计算每个分类的匹配度
        category_scores = {}
        for category, keywords in category_keywords.items():
            score = 0
            for keyword in keywords:
                if keyword in text:
                    score += 1
            category_scores[category] = score
        
        # 选择最高分分类
        best_category = max(category_scores.items(), key=lambda x: x[1])
        
        # 如果最高分是0,使用默认分类
        if best_category[1] == 0:
            return TicketCategory.OTHER
        else:
            return best_category[0]
    
    async def evaluate_priority(self, ticket_data: Dict[str, Any], emotion_analysis: Dict[str, Any]) -> TicketPriority:
        """评估工单优先级"""
        
        base_priority = TicketPriority.MEDIUM
        
        # 情感影响
        primary_emotion = emotion_analysis['primary']['emotion']
        emotion_score = emotion_analysis['primary']['score']
        
        if primary_emotion in ['angry', 'urgent'] and emotion_score > 0.6:
            base_priority = TicketPriority.HIGH
        
        # 关键词影响
        urgent_keywords = self.detect_urgent_keywords(ticket_data)
        if urgent_keywords:
            base_priority = TicketPriority.URGENT
        
        # 法律相关关键词
        if any(keyword in ticket_data['description'] for keyword in self.sentiment_keywords['legal']):
            base_priority = TicketPriority.CRITICAL
        
        # 历史用户价值(简化实现)
        user_value = await self.get_user_value_score(ticket_data['user_id'])
        if user_value > 80:  # 高价值用户
            if base_priority.value < TicketPriority.HIGH.value:
                base_priority = TicketPriority.HIGH
        
        return base_priority
    
    async def recommend_assignee(self, category: TicketCategory, priority: TicketPriority, 
                                emotion_analysis: Dict[str, Any]) -> Dict[str, Any]:
        """推荐处理人"""
        
        # 从Redis获取在线客服
        online_agents = self.redis_client.smembers('customer_service:online')
        
        if not online_agents:
            return {
                'type': 'system',
                'assignee_id': 'system',
                'reason': '无在线客服,进入排队队列'
            }
        
        # 获取客服技能标签
        agent_skills = {}
        for agent_id in online_agents:
            skills = self.redis_client.hgetall(f'agent:skills:{agent_id}')
            agent_skills[agent_id] = skills
        
        # 根据分类和情绪选择客服
        category_skill_map = {
            TicketCategory.ACCOUNT: 'account_management',
            TicketCategory.PAYMENT: 'payment_support',
            TicketCategory.LETTER: 'letter_specialist',
            TicketCategory.DELIVERY: 'delivery_expert',
            TicketCategory.CONTENT: 'content_moderator',
            TicketCategory.PRIVACY: 'privacy_specialist',
            TicketCategory.COMPLAINT: 'complaint_handler',
            TicketCategory.OTHER: 'general_support'
        }
        
        required_skill = category_skill_map.get(category, 'general_support')
        
        # 情绪特殊要求
        if emotion_analysis['primary']['emotion'] in ['angry', 'frustrated']:
            required_skill += '+anger_management'
        
        # 寻找匹配的客服
        suitable_agents = []
        for agent_id, skills in agent_skills.items():
            if required_skill in skills:
                # 计算工作负载
                workload = int(self.redis_client.get(f'agent:workload:{agent_id}') or 0)
                
                suitable_agents.append({
                    'agent_id': agent_id,
                    'skills': skills,
                    'workload': workload,
                    'match_score': self.calculate_match_score(skills, required_skill, priority)
                })
        
        # 按匹配度排序
        if suitable_agents:
            suitable_agents.sort(key=lambda x: x['match_score'], reverse=True)
            best_agent = suitable_agents[0]
            
            return {
                'type': 'agent',
                'assignee_id': best_agent['agent_id'],
                'match_score': best_agent['match_score'],
                'reason': f'技能匹配: {required_skill}, 工作负载: {best_agent["workload"]}'
            }
        else:
            # 没有匹配的客服,选择通用客服
            return {
                'type': 'agent',
                'assignee_id': list(online_agents)[0],
                'reason': '无专业技能匹配,分配至通用客服'
            }
    
    def detect_urgent_keywords(self, ticket_data: Dict[str, Any]) -> List[str]:
        """检测紧急关键词"""
        text = f"{ticket_data['title']} {ticket_data['description']}"
        
        urgent_patterns = [
            r'紧急[!!]?',
            r'立刻?马上',
            r'现在就要',
            r'立即处理',
            r'救命',
            r'出大事了',
            r'要死了',
            r'活不下去了',
            r'自杀',
            r'自残',
            r'越狱',
            r'逃跑'
        ]
        
        found_keywords = []
        for pattern in urgent_patterns:
            if re.search(pattern, text):
                found_keywords.append(pattern)
        
        return found_keywords
    
    async def generate_handling_suggestions(self, ticket_data: Dict[str, Any], 
                                          emotion_analysis: Dict[str, Any],
                                          similar_tickets: List[Dict[str, Any]]) -> List[str]:
        """生成处理建议"""
        
        suggestions = []
        
        # 基于情绪的建议
        primary_emotion = emotion_analysis['primary']['emotion']
        
        if primary_emotion == 'angry':
            suggestions.append("用户情绪愤怒,建议使用安抚话术,表达理解和歉意")
            suggestions.append("优先处理,避免情绪升级")
        
        elif primary_emotion == 'anxious':
            suggestions.append("用户表现焦虑,需要提供明确的时间承诺和跟进计划")
        
        elif primary_emotion == 'urgent':
            suggestions.append("用户表达急迫需求,建议立即响应并设定明确的解决时间")
        
        # 基于内容的建议
        if '监狱' in ticket_data['description'] and '管理' in ticket_data['description']:
            suggestions.append("涉及监狱管理问题,需谨慎处理,必要时转交法务部门")
        
        if any(word in ticket_data['description'] for word in ['隐私', '泄露', '安全']):
            suggestions.append("涉及隐私安全问题,需启动安全响应流程")
        
        # 基于相似工单的建议
        if similar_tickets:
            resolved_count = sum(1 for t in similar_tickets if t.get('status') == 'resolved')
            if resolved_count > 0:
                suggestions.append(f"找到{len(similar_tickets)}个相似工单,其中{resolved_count}个已解决,可参考历史解决方案")
        
        return suggestions
    
    async def assess_risk(self, ticket_data: Dict[str, Any], emotion_analysis: Dict[str, Any]) -> Dict[str, Any]:
        """风险评估"""
        
        risk_score = 0
        risk_reasons = []
        
        # 情绪风险
        if emotion_analysis['primary']['emotion'] in ['angry', 'frustrated']:
            risk_score += 40
            risk_reasons.append(f"用户情绪{emotion_analysis['primary']['emotion']},风险较高")
        
        # 法律关键词风险
        legal_keywords = self.sentiment_keywords['legal']
        if any(keyword in ticket_data['description'] for keyword in legal_keywords):
            risk_score += 60
            risk_reasons.append("涉及法律词汇,存在诉讼风险")
        
        # 紧急关键词风险
        urgent_keywords = self.detect_urgent_keywords(ticket_data)
        if urgent_keywords:
            risk_score += 30
            risk_reasons.append(f"包含紧急关键词: {', '.join(urgent_keywords[:3])}")
        
        # 历史投诉记录
        user_complaint_history = await self.get_user_complaint_history(ticket_data['user_id'])
        if user_complaint_history > 3:
            risk_score += 20
            risk_reasons.append(f"用户历史投诉次数: {user_complaint_history}")
        
        # 确定风险等级
        if risk_score >= 80:
            risk_level = "critical"
        elif risk_score >= 60:
            risk_level = "high"
        elif risk_score >= 40:
            risk_level = "medium"
        else:
            risk_level = "low"
        
        return {
            'score': risk_score,
            'level': risk_level,
            'reasons': risk_reasons
        }

三、投诉处理与升级机制

3.1 投诉处理工作流

复制代码
python
# app/services/complaint_handler.py
class ComplaintHandler:
    """投诉处理专用处理器"""
    
    COMPLAINT_RESOLUTION_FLOW = {
        "acknowledgment": {
            "time_limit": 30,  # 分钟
            "actions": ["immediate_response", "emotion_acknowledgment", "apology_if_needed"]
        },
        "investigation": {
            "time_limit": 240,  # 分钟
            "actions": ["gather_facts", "contact_related_parties", "review_evidence"]
        },
        "resolution_proposal": {
            "time_limit": 60,  # 分钟
            "actions": ["propose_solution", "seek_user_agreement", "document_agreement"]
        },
        "implementation": {
            "time_limit": 1440,  # 24小时
            "actions": ["execute_solution", "update_status", "notify_user"]
        },
        "follow_up": {
            "time_limit": 10080,  # 7天
            "actions": ["satisfaction_survey", "preventive_measures", "case_close"]
        }
    }
    
    async def handle_complaint(self, ticket: Ticket) -> Dict[str, Any]:
        """处理投诉工单"""
        
        # 1. 启动投诉处理流程
        process_id = await self.initiate_complaint_process(ticket)
        
        # 2. 分配专业投诉处理员
        handler = await self.assign_complaint_specialist(ticket)
        
        # 3. 发送正式投诉受理通知
        await self.send_complaint_acknowledgment(ticket, handler)
        
        # 4. 调查阶段
        investigation_result = await self.investigate_complaint(ticket)
        
        # 5. 制定解决方案
        resolution_plan = await self.create_resolution_plan(ticket, investigation_result)
        
        # 6. 与用户协商
        user_agreement = await self.negotiate_with_user(ticket, resolution_plan)
        
        # 7. 执行解决方案
        if user_agreement:
            execution_result = await self.execute_resolution(ticket, resolution_plan)
        else:
            # 进入升级流程
            execution_result = await self.escalate_complaint(ticket)
        
        # 8. 跟进与关闭
        follow_up_result = await self.follow_up_and_close(ticket, execution_result)
        
        return {
            "process_id": process_id,
            "handler": handler,
            "investigation_result": investigation_result,
            "resolution_plan": resolution_plan,
            "user_agreement": user_agreement,
            "execution_result": execution_result,
            "follow_up_result": follow_up_result,
            "total_time_minutes": self.calculate_process_time(process_id)
        }
    
    async def investigate_complaint(self, ticket: Ticket) -> Dict[str, Any]:
        """投诉调查"""
        
        investigation = {
            "ticket_id": ticket.ticket_id,
            "investigator": ticket.assigned_to,
            "start_time": datetime.now(),
            "steps": [],
            "evidence": [],
            "findings": []
        }
        
        # 1. 收集相关数据
        related_data = await self.collect_related_data(ticket)
        investigation["steps"].append({
            "action": "collect_related_data",
            "result": f"收集到{len(related_data)}条相关记录"
        })
        
        # 2. 分析信件历史
        if ticket.related_letter_ids:
            letter_analysis = await self.analyze_letter_history(ticket.related_letter_ids)
            investigation["findings"].append({
                "type": "letter_history",
                "data": letter_analysis
            })
        
        # 3. 联系相关部门
        departments = self.identify_related_departments(ticket)
        for dept in departments:
            dept_response = await self.contact_department(dept, ticket)
            investigation["steps"].append({
                "action": f"contact_{dept}",
                "result": dept_response.get("status", "unknown")
            })
        
        # 4. 验证用户声称
        user_claims = self.extract_user_claims(ticket.description)
        verified_claims = []
        
        for claim in user_claims:
            verification = await self.verify_claim(claim, ticket)
            investigation["findings"].append({
                "claim": claim,
                "verified": verification["verified"],
                "evidence": verification.get("evidence")
            })
            
            if verification["verified"]:
                verified_claims.append(claim)
        
        # 5. 确定责任方
        responsible_party = await self.identify_responsible_party(ticket, investigation["findings"])
        
        investigation["end_time"] = datetime.now()
        investigation["responsible_party"] = responsible_party
        investigation["verified_claims"] = verified_claims
        
        # 保存调查记录
        await self.save_investigation_record(investigation)
        
        return investigation
    
    async def create_resolution_plan(self, ticket: Ticket, investigation: Dict[str, Any]) -> Dict[str, Any]:
        """制定解决方案"""
        
        # 根据调查结果制定方案
        resolution_types = {
            "apology_only": {"score": 10, "actions": ["formal_apology", "explanation"]},
            "compensation_small": {"score": 30, "actions": ["apology", "small_compensation"]},
            "compensation_medium": {"score": 50, "actions": ["apology", "medium_compensation", "service_credit"]},
            "compensation_full": {"score": 70, "actions": ["full_refund", "apology", "service_improvement"]},
            "service_recovery": {"score": 90, "actions": ["problem_fix", "compensation", "preventive_measures"]}
        }
        
        # 评估投诉严重性
        severity_score = self.calculate_complaint_severity(ticket, investigation)
        
        # 选择合适的解决方案
        selected_resolution = None
        for res_type, res_info in resolution_types.items():
            if severity_score >= res_info["score"]:
                selected_resolution = res_type
        
        if not selected_resolution:
            selected_resolution = "apology_only"
        
        # 生成具体方案
        resolution_plan = {
            "ticket_id": ticket.ticket_id,
            "resolution_type": selected_resolution,
            "severity_score": severity_score,
            "proposed_actions": resolution_types[selected_resolution]["actions"],
            "timeline": self.create_resolution_timeline(selected_resolution),
            "compensation_details": self.calculate_compensation(ticket, selected_resolution),
            "preventive_measures": self.suggest_preventive_measures(investigation),
            "approval_required": severity_score > 50
        }
        
        # 如果需要审批,发送给上级
        if resolution_plan["approval_required"]:
            await self.request_approval(resolution_plan, ticket.assigned_to)
        
        return resolution_plan
    
    async def negotiate_with_user(self, ticket: Ticket, resolution_plan: Dict[str, Any]) -> bool:
        """与用户协商解决方案"""
        
        # 1. 准备协商消息
        negotiation_message = self.prepare_negotiation_message(ticket, resolution_plan)
        
        # 2. 发送给用户
        message_id = await self.send_negotiation_message(ticket.user_id, negotiation_message)
        
        # 3. 等待用户回复(最长24小时)
        user_response = await self.wait_for_user_response(ticket.user_id, message_id, timeout_hours=24)
        
        if not user_response:
            # 用户未回复,默认接受
            return True
        
        # 4. 分析用户回复
        response_analysis = await self.analyze_user_response(user_response)
        
        if response_analysis["agreement"]:
            return True
        else:
            # 用户不接受,记录反对原因
            await self.record_user_objections(ticket, response_analysis["objections"])
            
            # 检查是否需要调整方案
            if response_analysis["suggested_changes"]:
                adjusted_plan = await self.adjust_resolution_plan(
                    resolution_plan, 
                    response_analysis["suggested_changes"]
                )
                
                # 再次协商
                return await self.negotiate_with_user(ticket, adjusted_plan)
            else:
                # 用户完全拒绝

3.2 工单升级机制

复制代码
# app/services/ticket_escalation.py
class TicketEscalationManager:
    """工单升级管理器"""
    
    ESCALATION_LEVELS = {
        1: {
            "name": "一线客服",
            "time_limit": 120,  # 2小时
            "actions": ["initial_response", "basic_troubleshooting"]
        },
        2: {
            "name": "高级客服",
            "time_limit": 240,  # 4小时
            "actions": ["advanced_troubleshooting", "issue_investigation"]
        },
        3: {
            "name": "专家团队",
            "time_limit": 480,  # 8小时
            "actions": ["root_cause_analysis", "solution_design"]
        },
        4: {
            "name": "管理层",
            "time_limit": 1440,  # 24小时
            "actions": ["strategic_decision", "compensation_approval"]
        },
        5: {
            "name": "执行层",
            "time_limit": 2880,  # 48小时
            "actions": ["executive_intervention", "policy_change"]
        }
    }
    
    ESCALATION_TRIGGERS = {
        "time_based": {
            "level1_to_2": 7200,  # 2小时无响应
            "level2_to_3": 14400,  # 4小时未解决
            "level3_to_4": 28800,  # 8小时未解决
            "level4_to_5": 86400   # 24小时未解决
        },
        "priority_based": {
            TicketPriority.URGENT: 3,  # 紧急工单直接到3级
            TicketPriority.CRITICAL: 4  # 严重工单直接到4级
        },
        "emotion_based": {
            "angry_escalation": 2,  # 愤怒用户升一级
            "legal_threat": 4       # 法律威胁到4级
        },
        "issue_based": {
            "privacy_breach": 4,
            "financial_loss": 3,
            "service_outage": 3,
            "security_issue": 4
        }
    }
    
    async def check_escalation_need(self, ticket: Ticket) -> Optional[Dict[str, Any]]:
        """检查是否需要升级"""
        
        escalation_reasons = []
        suggested_level = ticket.metadata.get('escalation_level', 1)
        
        # 1. 检查时间触发
        time_escalation = await self.check_time_based_escalation(ticket)
        if time_escalation:
            escalation_reasons.append(time_escalation["reason"])
            suggested_level = max(suggested_level, time_escalation["suggested_level"])
        
        # 2. 检查用户情绪触发
        emotion_escalation = await self.check_emotion_based_escalation(ticket)
        if emotion_escalation:
            escalation_reasons.append(emotion_escalation["reason"])
            suggested_level = max(suggested_level, emotion_escalation["suggested_level"])
        
        # 3. 检查问题严重性触发
        issue_escalation = await self.check_issue_based_escalation(ticket)
        if issue_escalation:
            escalation_reasons.append(issue_escalation["reason"])
            suggested_level = max(suggested_level, issue_escalation["suggested_level"])
        
        # 4. 检查用户价值触发(VIP用户)
        user_value_escalation = await self.check_user_value_escalation(ticket)
        if user_value_escalation:
            escalation_reasons.append(user_value_escalation["reason"])
            suggested_level = max(suggested_level, user_value_escalation["suggested_level"])
        
        # 5. 检查重复投诉触发
        repeat_escalation = await self.check_repeat_complaint_escalation(ticket)
        if repeat_escalation:
            escalation_reasons.append(repeat_escalation["reason"])
            suggested_level = max(suggested_level, repeat_escalation["suggested_level"])
        
        # 判断是否需要升级
        current_level = ticket.metadata.get('escalation_level', 1)
        
        if suggested_level > current_level and escalation_reasons:
            return {
                "ticket_id": ticket.ticket_id,
                "current_level": current_level,
                "suggested_level": suggested_level,
                "reasons": escalation_reasons,
                "escalation_required": True
            }
        
        return None
    
    async def escalate_ticket(self, ticket: Ticket, escalation_info: Dict[str, Any]) -> Dict[str, Any]:
        """执行工单升级"""
        
        current_level = escalation_info["current_level"]
        target_level = escalation_info["suggested_level"]
        
        # 1. 创建升级记录
        escalation_record = {
            "escalation_id": f"ESC-{ticket.ticket_id}-{datetime.now().strftime('%Y%m%d%H%M%S')}",
            "ticket_id": ticket.ticket_id,
            "from_level": current_level,
            "to_level": target_level,
            "reasons": escalation_info["reasons"],
            "escalated_by": "system",
            "escalated_at": datetime.now(),
            "previous_handler": ticket.assigned_to
        }
        
        # 2. 寻找目标级别处理人
        target_handler = await self.find_handler_for_level(target_level, ticket)
        
        # 3. 更新工单
        ticket.assigned_to = target_handler["agent_id"]
        ticket.assignee_role = target_handler["role"]
        ticket.metadata["escalation_level"] = target_level
        ticket.metadata["escalation_history"] = ticket.metadata.get("escalation_history", []) + [escalation_record]
        
        # 4. 发送升级通知
        notifications_sent = await self.send_escalation_notifications(
            ticket, escalation_record, target_handler
        )
        
        # 5. 应用升级后的SLA
        new_sla = self.ESCALATION_LEVELS[target_level]
        ticket.metadata["current_sla"] = new_sla
        
        # 6. 记录升级操作
        await self.log_escalation_action(escalation_record)
        
        # 7. 更新升级后的处理计划
        await self.update_handling_plan_after_escalation(ticket, target_level)
        
        return {
            "success": True,
            "escalation_id": escalation_record["escalation_id"],
            "new_handler": target_handler,
            "new_sla": new_sla,
            "notifications_sent": notifications_sent,
            "timestamp": datetime.now().isoformat()
        }
    
    async def find_handler_for_level(self, level: int, ticket: Ticket) -> Dict[str, Any]:
        """寻找适合级别的处理人"""
        
        level_info = self.ESCALATION_LEVELS.get(level, self.ESCALATION_LEVELS[1])
        
        # 从Redis获取该级别可用人员
        level_key = f"support_agents:level_{level}"
        available_agents = self.redis_client.smembers(level_key)
        
        if not available_agents:
            # 没有该级别人员,尝试上一级
            if level > 1:
                return await self.find_handler_for_level(level - 1, ticket)
            else:
                # 回到一线客服
                return {
                    "agent_id": "system",
                    "role": "system",
                    "level": 1,
                    "reason": "无可用处理人,系统托管"
                }
        
        # 根据工单特点选择最合适的处理人
        suitable_agent = await self.select_most_suitable_agent(
            list(available_agents), ticket, level
        )
        
        return {
            "agent_id": suitable_agent["id"],
            "role": suitable_agent["role"],
            "level": level,
            "name": suitable_agent.get("name", "Unknown"),
            "specialties": suitable_agent.get("specialties", []),
            "reason": suitable_agent.get("selection_reason", "自动分配")
        }

四、API接口设计

4.1 工单相关API

复制代码
# app/api/tickets.py
from fastapi import APIRouter, Depends, HTTPException, status
from typing import List, Optional
from app.models.ticket import Ticket, TicketCreate, TicketUpdate, TicketStatus
from app.services.ticket_engine import IntelligentTicketEngine
from app.services.complaint_handler import ComplaintHandler

router = APIRouter(prefix="/api/v1/tickets", tags=["tickets"])

@router.post("/", response_model=Ticket, status_code=status.HTTP_201_CREATED)
async def create_ticket(
    ticket_create: TicketCreate,
    current_user: dict = Depends(get_current_user),
    ticket_engine: IntelligentTicketEngine = Depends(get_ticket_engine)
):
    """
    创建新工单
    """
    try:
        # 1. 基础数据验证
        if len(ticket_create.description) < 10:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="问题描述至少需要10个字符"
            )
        
        # 2. 检查用户是否有未解决的相似工单
        similar_active = await check_similar_active_tickets(
            current_user["user_id"],
            ticket_create.title,
            ticket_create.description
        )
        
        if similar_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"您已有相似问题正在处理中,工单ID: {similar_active[0]['ticket_id']}"
            )
        
        # 3. 生成工单ID
        ticket_id = generate_ticket_id(current_user["user_id"])
        
        # 4. 构建工单对象
        ticket_data = {
            "ticket_id": ticket_id,
            "user_id": current_user["user_id"],
            **ticket_create.dict(),
            "source": "api",
            "ip_address": request.client.host,
            "user_agent": request.headers.get("user-agent")
        }
        
        # 5. 智能分析
        enhanced_ticket = await ticket_engine.process_new_ticket(ticket_data)
        
        # 6. 保存到数据库
        ticket = await save_ticket_to_db(enhanced_ticket)
        
        # 7. 发送创建通知
        await send_ticket_creation_notifications(ticket)
        
        # 8. 记录用户行为
        await log_user_action(
            current_user["user_id"],
            "create_ticket",
            {"ticket_id": ticket_id, "category": ticket_create.category.value}
        )
        
        return ticket
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建工单失败: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="工单创建失败,请稍后重试"
        )

@router.get("/{ticket_id}", response_model=Ticket)
async def get_ticket(
    ticket_id: str,
    current_user: dict = Depends(get_current_user),
    check_permission: bool = Depends(check_ticket_permission)
):
    """
    获取工单详情
    """
    ticket = await get_ticket_from_db(ticket_id)
    
    if not ticket:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="工单不存在"
        )
    
    # 检查权限
    if not await check_permission(ticket, current_user):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权访问此工单"
        )
    
    # 脱敏处理(如果是客服查看)
    if current_user.get("role") == "customer_service":
        ticket = sanitize_ticket_for_agent(ticket)
    
    return ticket

@router.post("/{ticket_id}/interactions")
async def add_ticket_interaction(
    ticket_id: str,
    interaction_data: dict,
    current_user: dict = Depends(get_current_user)
):
    """
    添加工单交互记录
    """
    # 1. 验证工单状态
    ticket = await get_ticket_from_db(ticket_id)
    if not ticket:
        raise HTTPException(status_code=404, detail="工单不存在")
    
    if ticket.status in [TicketStatus.CLOSED, TicketStatus.RESOLVED]:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="工单已关闭,无法添加交互"
        )
    
    # 2. 创建交互记录
    interaction_id = generate_interaction_id(ticket_id)
    
    interaction = {
        "interaction_id": interaction_id,
        "ticket_id": ticket_id,
        "user_id": current_user["user_id"],
        "user_type": current_user.get("role", "user"),
        "content": interaction_data.get("content"),
        "content_type": interaction_data.get("content_type", "text"),
        "attachments": interaction_data.get("attachments", []),
        "internal_note": interaction_data.get("internal_note", False),
        "created_at": datetime.now()
    }
    
    # 3. 保存交互
    await save_interaction_to_db(interaction)
    
    # 4. 更新工单状态
    if current_user.get("role") == "customer_service":
        # 客服回复,更新首次响应时间
        if not ticket.first_response_at:
            ticket.first_response_at = datetime.now()
            ticket.first_response_time = calculate_response_time(
                ticket.created_at, ticket.first_response_at
            )
        
        # 更新工单状态
        if ticket.status == TicketStatus.SUBMITTED:
            ticket.status = TicketStatus.IN_PROGRESS
    
    # 5. 发送通知
    if not interaction["internal_note"]:
        recipient = ticket.user_id if current_user.get("role") == "customer_service" else "customer_service"
        await send_interaction_notification(interaction, recipient)
    
    # 6. 触发自动响应(如果是用户回复)
    if current_user.get("role") == "user":
        await trigger_auto_response(ticket, interaction)
    
    return {"success": True, "interaction_id": interaction_id}

@router.post("/{ticket_id}/escalate")
async def escalate_ticket(
    ticket_id: str,
    escalation_reason: dict,
    current_user: dict = Depends(get_current_user),
    escalation_manager: TicketEscalationManager = Depends(get_escalation_manager)
):
    """
    手动升级工单
    """
    # 权限检查:只有客服或管理员可以手动升级
    if current_user.get("role") not in ["customer_service", "admin", "supervisor"]:
        raise HTTPException(status_code=403, detail="无权升级工单")
    
    ticket = await get_ticket_from_db(ticket_id)
    if not ticket:
        raise HTTPException(status_code=404, detail="工单不存在")
    
    # 检查是否需要审批
    current_level = ticket.metadata.get("escalation_level", 1)
    target_level = escalation_reason.get("target_level", current_level + 1)
    
    if target_level >= 4 and current_user.get("role") != "admin":
        # 需要管理员审批
        approval_required = True
    else:
        approval_required = False
    
    if approval_required:
        # 创建审批请求
        approval_request = await create_escalation_approval_request(
            ticket, current_user, escalation_reason, target_level
        )
        
        return {
            "status": "pending_approval",
            "approval_id": approval_request["approval_id"],
            "message": "升级需要管理员审批,已提交审批请求"
        }
    else:
        # 直接执行升级
        escalation_info = {
            "ticket_id": ticket_id,
            "current_level": current_level,
            "suggested_level": target_level,
            "reasons": [escalation_reason.get("reason", "手动升级")]
        }
        
        result = await escalation_manager.escalate_ticket(ticket, escalation_info)
        
        return {
            "status": "escalated",
            "escalation_id": result["escalation_id"],
            "new_handler": result["new_handler"],
            "new_sla": result["new_sla"]
        }

@router.get("/user/{user_id}/history")
async def get_user_ticket_history(
    user_id: str,
    page: int = 1,
    limit: int = 20,
    status_filter: Optional[str] = None,
    current_user: dict = Depends(get_current_user)
):
    """
    获取用户工单历史
    """
    # 权限检查:只能查看自己的工单或客服查看用户工单
    if current_user["user_id"] != user_id and current_user.get("role") != "customer_service":
        raise HTTPException(status_code=403, detail="无权查看该用户工单")
    
    # 构建查询条件
    query_filters = {"user_id": user_id}
    if status_filter:
        query_filters["status"] = status_filter
    
    # 分页查询
    tickets, total = await get_tickets_by_filters(
        query_filters,
        skip=(page - 1) * limit,
        limit=limit,
        sort_by="-created_at"
    )
    
    # 脱敏处理
    if current_user.get("role") == "customer_service":
        tickets = [sanitize_ticket_for_agent(t) for t in tickets]
    
    return {
        "tickets": tickets,
        "pagination": {
            "page": page,
            "limit": limit,
            "total": total,
            "pages": (total + limit - 1) // limit
        }
    }

五、监控与分析系统

5.1 工单数据监控

复制代码
# app/services/ticket_analytics.py
class TicketAnalyticsService:
    """工单数据分析服务"""
    
    async def generate_daily_report(self, date: datetime = None) -> Dict[str, Any]:
        """生成日报"""
        if date is None:
            date = datetime.now()
        
        start_date = date.replace(hour=0, minute=0, second=0, microsecond=0)
        end_date = start_date + timedelta(days=1)
        
        # 1. 基础统计
        stats = await self.get_daily_stats(start_date, end_date)
        
        # 2. 分类分析
        category_analysis = await self.analyze_by_category(start_date, end_date)
        
        # 3. 满意度分析
        satisfaction_analysis = await self.analyze_satisfaction(start_date, end_date)
        
        # 4. 响应时间分析
        response_time_analysis = await self.analyze_response_times(start_date, end_date)
        
        # 5. 客服绩效
        agent_performance = await self.analyze_agent_performance(start_date, end_date)
        
        # 6. 问题趋势
        issue_trends = await self.identify_issue_trends(start_date, end_date)
        
        # 7. 投诉分析
        complaint_analysis = await self.analyze_complaints(start_date, end_date)
        
        # 8. 生成洞察
        insights = await self.generate_insights(
            stats, category_analysis, satisfaction_analysis, issue_trends
        )
        
        report = {
            "report_date": start_date.strftime("%Y-%m-%d"),
            "generated_at": datetime.now().isoformat(),
            "summary": {
                "total_tickets": stats["total"],
                "resolved_tickets": stats["resolved"],
                "avg_response_time": response_time_analysis["average"],
                "avg_resolution_time": response_time_analysis["avg_resolution"],
                "satisfaction_rate": satisfaction_analysis["average_score"]
            },
            "detailed_analysis": {
                "by_category": category_analysis,
                "by_priority": await self.analyze_by_priority(start_date, end_date),
                "by_channel": await self.analyze_by_channel(start_date, end_date),
                "by_time": await self.analyze_by_time_of_day(start_date, end_date)
            },
            "performance_metrics": {
                "agents": agent_performance,
                "sla_compliance": await self.calculate_sla_compliance(start_date, end_date),
                "escalation_rate": await self.calculate_escalation_rate(start_date, end_date)
            },
            "complaint_analysis": complaint_analysis,
            "trends_and_patterns": issue_trends,
            "insights_and_recommendations": insights,
            "anomalies": await self.detect_anomalies(start_date, end_date)
        }
        
        # 保存报告
        await self.save_report(report)
        
        return report
    
    async def analyze_complaints(self, start_date: datetime, end_date: datetime) -> Dict[str, Any]:
        """投诉深度分析"""
        
        # 获取投诉工单
        complaint_tickets = await self.get_tickets_by_category(
            start_date, end_date, "complaint"
        )
        
        analysis = {
            "total_complaints": len(complaint_tickets),
            "resolved_complaints": sum(1 for t in complaint_tickets if t.status == "resolved"),
            "open_complaints": sum(1 for t in complaint_tickets if t.status not in ["resolved", "closed"]),
            "by_reason": await self.categorize_complaint_reasons(complaint_tickets),
            "by_severity": await self.analyze_complaint_severity(complaint_tickets),
            "resolution_time": await self.analyze_complaint_resolution_time(complaint_tickets),
            "repeat_complaints": await self.identify_repeat_complainers(complaint_tickets),
            "compensation_given": await self.analyze_compensation_cases(complaint_tickets),
            "root_causes": await self.identify_root_causes(complaint_tickets),
            "preventive_actions": await self.suggest_preventive_actions(complaint_tickets)
        }
        
        return analysis
    
    async def generate_insights(self, stats: Dict, category_analysis: Dict, 
                              satisfaction_analysis: Dict, issue_trends: Dict) -> List[Dict[str, Any]]:
        """生成业务洞察"""
        
        insights = []
        
        # 1. 问题集中领域洞察
        top_category = max(category_analysis.items(), key=lambda x: x[1]["count"])
        if top_category[1]["count"] > stats["total"] * 0.3:  # 占比超过30%
            insights.append({
                "type": "concentration_risk",
                "severity": "high",
                "message": f"{top_category[0]}类问题占比过高 ({top_category[1]['percentage']}%)",
                "recommendation": "需要专项优化该领域服务流程",
                "impact": "可能影响整体用户满意度"
            })
        
        # 2. 满意度下降洞察
        if satisfaction_analysis.get("trend") == "decreasing":
            insights.append({
                "type": "satisfaction_decline",
                "severity": "medium",
                "message": "用户满意度呈下降趋势",
                "recommendation": "深入分析最近解决的工单,找出满意度下降原因",
                "impact": "长期可能影响用户留存"
            })
        
        # 3. 响应时间洞察
        if stats.get("avg_response_time") > 60:  # 超过1小时
            insights.append({
                "type": "slow_response",
                "severity": "high",
                "message": f"平均响应时间较长 ({stats['avg_response_time']}分钟)",
                "recommendation": "优化客服排班或引入自动响应机制",
                "impact": "影响用户即时服务体验"
            })
        
        # 4. 投诉趋势洞察
        if issue_trends.get("complaint_trend") == "increasing":
            insights.append({
                "type": "complaint_increase",
                "severity": "critical",
                "message": "投诉量持续上升,需要立即关注",
                "recommendation": "召开专项会议分析投诉原因,制定改进措施",
                "impact": "可能引发大规模用户流失或品牌危机"
            })
        
        # 5. 重复问题洞察
        recurring_issues = issue_trends.get("recurring_issues", [])
        if recurring_issues:
            insights.append({
                "type": "recurring_problems",
                "severity": "medium",
                "message": f"发现{len(recurring_issues)}个重复出现的问题",
                "recommendation": "建立问题知识库,优化解决方案复用",
                "data": recurring_issues[:5]  # 前5个重复问题
            })
        
        return insights

六、部署与运维

6.1 环境配置

复制代码
# docker-compose.ticket.yml
version: '3.8'

services:
  ticket-api:
    build: 
      context: .
      dockerfile: Dockerfile.ticket
    image: weiaibang/ticket-api:latest
    container_name: ticket-api
    environment:
      - NODE_ENV=production
      - REDIS_HOST=redis-ticket
      - MYSQL_HOST=mysql-ticket
      - ELASTICSEARCH_HOST=elasticsearch
      - KAFKA_HOST=kafka
    ports:
      - "8001:8000"
    depends_on:
      - redis-ticket
      - mysql-ticket
    networks:
      - ticket-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  ticket-worker:
    build:
      context: .
      dockerfile: Dockerfile.ticket-worker
    image: weiaibang/ticket-worker:latest
    container_name: ticket-worker
    environment:
      - NODE_ENV=production
      - REDIS_HOST=redis-ticket
      - MYSQL_HOST=mysql-ticket
    depends_on:
      - redis-ticket
      - mysql-ticket
    networks:
      - ticket-network
    deploy:
      replicas: 3

  redis-ticket:
    image: redis:6-alpine
    container_name: redis-ticket
    ports:
      - "6379:6379"
    volumes:
      - redis-ticket-data:/data
    command: redis-server --appendonly yes
    networks:
      - ticket-network

  mysql-ticket:
    image: mysql:8.0
    container_name: mysql-ticket
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ticket_system
      MYSQL_USER: ticket_user
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - "3307:3306"
    volumes:
      - mysql-ticket-data:/var/lib/mysql
      - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - ticket-network

  ticket-monitor:
    image: prom/prometheus:latest
    container_name: ticket-monitor
    volumes:
      - ./prometheus/ticket.yml:/etc/prometheus/prometheus.yml
      - prometheus-ticket-data:/prometheus
    ports:
      - "9091:9090"
    networks:
      - ticket-network

networks:
  ticket-network:
    driver: bridge

volumes:
  redis-ticket-data:
  mysql-ticket-data:
  prometheus-ticket-data:

6.2 性能监控配置

复制代码
# prometheus/ticket.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "ticket_alerts.yml"

scrape_configs:
  - job_name: 'ticket-api'
    static_configs:
      - targets: ['ticket-api:8000']
    metrics_path: '/metrics'
  
  - job_name: 'ticket-redis'
    static_configs:
      - targets: ['redis-ticket:6379']
  
  - job_name: 'ticket-mysql'
    static_configs:
      - targets: ['mysql-ticket:3306']
  
  - job_name: 'ticket-worker'
    static_configs:
      - targets: ['ticket-worker:8000']

# 告警规则
# ticket_alerts.yml
groups:
  - name: ticket_system_alerts
    rules:
      - alert: HighTicketVolume
        expr: rate(tickets_created_total[5m]) > 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "工单创建量过高"
          description: "过去5分钟工单创建速率超过10/分钟"
      
      - alert: SlowResponseTime
        expr: histogram_quantile(0.95, rate(ticket_response_time_seconds_bucket[5m])) > 300
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "工单响应时间过长"
          description: "95%的工单响应时间超过5分钟"
      
      - alert: HighComplaintRate
        expr: rate(tickets_created_total{category="complaint"}[1h]) / rate(tickets_created_total[1h]) > 0.2
        for: 1h
        labels:
          severity: critical
        annotations:
          summary: "投诉率过高"
          description: "投诉工单占比超过20%"
      
      - alert: LowSatisfactionScore
        expr: avg_over_time(ticket_satisfaction_score[1h]) < 3
        for: 2h
        labels:
          severity: warning
        annotations:
          summary: "用户满意度过低"
          description: "过去1小时平均满意度低于3分"

七、总结

微爱帮工单系统通过以下技术创新,实现了高效、智能的投诉处理:

7.1 核心优势

  1. 情感智能分析:识别用户情绪状态,提供个性化响应策略

  2. 智能路由分配:基于技能、工作负载和工单特性自动分配

  3. 动态升级机制:多维度触发条件,确保重要问题及时升级

  4. 全面数据监控:实时分析工单数据,提供业务洞察

  5. 安全隐私保护:敏感信息脱敏,符合等保3.0要求

7.2 关键性能指标

  • 平均响应时间:< 30分钟(紧急工单<15分钟)

  • 首次解决率:> 85%

  • 用户满意度:> 4.5/5.0

  • 系统可用性:> 99.95%

  • 投诉解决率:> 95%

7.3 特殊场景优化

针对监狱通信场景的特殊性,系统额外提供:

  • 司法相关工单:特殊处理流程,法律顾问介入

  • 情绪危机干预:识别高风险情绪,启动心理支持

  • 隐私保护强化:敏感信息多重加密,访问严格审计

  • 跨部门协同:与监狱管理部门协同处理机制

该系统不仅解决了微爱帮平台的投诉处理需求,更为特殊群体提供了有温度、有效率的问题解决通道,是平台服务质量的重要保障。

相关推荐
弓.长.2 小时前
深入解析MoE架构:大模型高效训练的核心技术
人工智能·机器学习·语言模型·架构
胡伯来了2 小时前
22 Transformers - 训练计算机视觉模型
人工智能·计算机视觉·transformer·transformers
Lun3866buzha2 小时前
心血管造影图像目标检测_YOLO11-CSFCN模型实现与优化_1
人工智能·目标检测·目标跟踪
谈思汽车2 小时前
车企如何拿到 ISO/PAS 8800 汽车AI安全流程认证!
人工智能·安全·ai·汽车·智能汽车
AndrewHZ2 小时前
【图像处理基石】什么是神经渲染?
图像处理·人工智能·神经网络·算法·cnn·计算机图形学·神经渲染
yy_xzz2 小时前
003 卷积神经网络(CNN)-- 原理到实践
人工智能·神经网络·cnn
雪花desu2 小时前
深入 LangChain LCEL 的 10 个核心特性
数据库·人工智能·深度学习·langchain
byzh_rc2 小时前
[模式识别-从入门到入土] 组合分类器
人工智能·算法·机器学习·支持向量机·概率论
zhongerzixunshi2 小时前
以技术创新为翼 筑就发展新高度
大数据·人工智能·物联网