Kamixitong/app/models/ticket.py

181 lines
6.7 KiB
Python
Raw Permalink Normal View History

2025-11-11 21:39:12 +08:00
from datetime import datetime
from app import db
2025-12-12 11:35:14 +08:00
from sqlalchemy.orm import relationship
class TicketReply(db.Model):
"""工单回复模型"""
__tablename__ = 'ticket_reply'
reply_id = db.Column(db.Integer, primary_key=True)
ticket_id = db.Column(db.Integer, db.ForeignKey('ticket.ticket_id'), nullable=False)
content = db.Column(db.Text, nullable=False) # 回复内容支持HTML
creator = db.Column(db.String(32), nullable=True) # 回复人(管理员账号或系统)
create_time = db.Column(db.DateTime, default=datetime.utcnow)
def to_dict(self):
"""转换为字典"""
return {
'reply_id': self.reply_id,
'ticket_id': self.ticket_id,
'content': self.content,
'creator': self.creator,
'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if self.create_time else None
}
2025-11-11 21:39:12 +08:00
class Ticket(db.Model):
"""工单模型"""
__tablename__ = 'ticket'
ticket_id = db.Column(db.Integer, primary_key=True)
2025-12-12 11:35:14 +08:00
ticket_number = db.Column(db.String(32), unique=True, nullable=False) # 工单编号
2025-11-11 21:39:12 +08:00
title = db.Column(db.String(128), nullable=False)
product_id = db.Column(db.String(32), db.ForeignKey('product.product_id'), nullable=False)
software_version = db.Column(db.String(16), nullable=True)
machine_code = db.Column(db.String(64), nullable=True)
license_key = db.Column(db.String(32), nullable=True)
description = db.Column(db.Text, nullable=False)
priority = db.Column(db.Integer, nullable=False, default=1) # 0=低, 1=中, 2=高
status = db.Column(db.Integer, nullable=False, default=0) # 0=待处理, 1=处理中, 2=已解决, 3=已关闭
operator = db.Column(db.String(32), nullable=True) # 处理人(管理员账号)
remark = db.Column(db.Text, nullable=True) # 处理备注
2025-12-12 11:35:14 +08:00
contact_person = db.Column(db.String(64), nullable=True) # 联系人姓名
phone = db.Column(db.String(20), nullable=True) # 联系电话
2025-11-11 21:39:12 +08:00
create_time = db.Column(db.DateTime, default=datetime.utcnow)
update_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
resolve_time = db.Column(db.DateTime, nullable=True) # 解决时间
close_time = db.Column(db.DateTime, nullable=True) # 关闭时间
2025-12-12 11:35:14 +08:00
# 关系
replies = relationship('TicketReply', backref='ticket', lazy='dynamic', cascade='all, delete-orphan')
2025-11-11 21:39:12 +08:00
def __init__(self, **kwargs):
super(Ticket, self).__init__(**kwargs)
2025-12-12 11:35:14 +08:00
# 如果没有提供工单编号,则自动生成
if not self.ticket_number:
self.ticket_number = self.generate_ticket_number()
def generate_ticket_number(self):
"""生成工单编号 TKT+日期+4位序号"""
from datetime import datetime
import random
date_str = datetime.now().strftime('%Y%m%d')
random_str = str(random.randint(1000, 9999))
return f"TKT{date_str}{random_str}"
2025-11-11 21:39:12 +08:00
def get_priority_name(self):
"""获取优先级名称"""
priority_map = {
0: '',
1: '',
2: ''
}
return priority_map.get(self.priority, '未知')
def get_status_name(self):
"""获取状态名称"""
status_map = {
0: '待处理',
1: '处理中',
2: '已解决',
3: '已关闭'
}
return status_map.get(self.status, '未知')
def is_pending(self):
"""是否待处理"""
return self.status == 0
def is_processing(self):
"""是否处理中"""
return self.status == 1
def is_resolved(self):
"""是否已解决"""
return self.status == 2
def is_closed(self):
"""是否已关闭"""
return self.status == 3
def assign_to(self, operator):
"""分配给处理人"""
self.operator = operator
if self.status == 0:
self.status = 1 # 待处理 -> 处理中
db.session.commit()
def resolve(self, remark=None):
"""解决工单"""
self.status = 2
self.resolve_time = datetime.utcnow()
if remark:
self.remark = remark
db.session.commit()
def close(self, remark=None):
"""关闭工单"""
self.status = 3
self.close_time = datetime.utcnow()
if remark:
self.remark = remark
db.session.commit()
def reopen(self):
"""重新打开工单"""
self.status = 1 # 处理中
self.resolve_time = None
self.close_time = None
db.session.commit()
def update_status(self, status, remark=None):
"""更新工单状态"""
old_status = self.status
self.status = status
# 更新时间戳
if status == 2 and old_status != 2:
self.resolve_time = datetime.utcnow()
elif status == 3 and old_status != 3:
self.close_time = datetime.utcnow()
if remark:
self.remark = remark
db.session.commit()
def get_processing_days(self):
"""获取处理天数"""
if self.resolve_time:
return (self.resolve_time - self.create_time).days
return (datetime.utcnow() - self.create_time).days
def to_dict(self):
"""转换为字典"""
return {
'ticket_id': self.ticket_id,
2025-12-12 11:35:14 +08:00
'ticket_number': self.ticket_number,
2025-11-11 21:39:12 +08:00
'title': self.title,
'product_id': self.product_id,
'product_name': self.product.product_name if self.product else None,
'software_version': self.software_version,
'machine_code': self.machine_code,
'license_key': self.license_key,
'description': self.description,
'priority': self.priority,
'priority_name': self.get_priority_name(),
'status': self.status,
'status_name': self.get_status_name(),
'operator': self.operator,
'remark': self.remark,
2025-12-12 11:35:14 +08:00
'contact_person': self.contact_person,
'phone': self.phone,
2025-11-11 21:39:12 +08:00
'processing_days': self.get_processing_days(),
2025-11-12 15:11:05 +08:00
'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if self.create_time else None,
'update_time': self.update_time.strftime('%Y-%m-%d %H:%M:%S') if self.update_time else None,
2025-11-11 21:39:12 +08:00
'resolve_time': self.resolve_time.strftime('%Y-%m-%d %H:%M:%S') if self.resolve_time else None,
2025-12-12 11:35:14 +08:00
'close_time': self.close_time.strftime('%Y-%m-%d %H:%M:%S') if self.close_time else None,
'replies': [reply.to_dict() for reply in self.replies.order_by(TicketReply.create_time.asc()).all()]
2025-11-11 21:39:12 +08:00
}
def __repr__(self):
return f'<Ticket {self.ticket_id}: {self.title}>'