2025-11-11 21:39:12 +08:00
|
|
|
from datetime import datetime
|
|
|
|
|
from app import db
|
|
|
|
|
|
|
|
|
|
class Ticket(db.Model):
|
|
|
|
|
"""工单模型"""
|
|
|
|
|
__tablename__ = 'ticket'
|
|
|
|
|
|
|
|
|
|
ticket_id = db.Column(db.Integer, primary_key=True)
|
|
|
|
|
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) # 处理备注
|
|
|
|
|
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) # 关闭时间
|
|
|
|
|
|
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
|
super(Ticket, self).__init__(**kwargs)
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
'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,
|
|
|
|
|
'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,
|
|
|
|
|
'close_time': self.close_time.strftime('%Y-%m-%d %H:%M:%S') if self.close_time else None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
return f'<Ticket {self.ticket_id}: {self.title}>'
|