第一次提交
This commit is contained in:
181
app/models/ticket.py
Normal file
181
app/models/ticket.py
Normal file
@@ -0,0 +1,181 @@
|
||||
from datetime import datetime
|
||||
from app import db
|
||||
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
|
||||
}
|
||||
|
||||
class Ticket(db.Model):
|
||||
"""工单模型"""
|
||||
__tablename__ = 'ticket'
|
||||
|
||||
ticket_id = db.Column(db.Integer, primary_key=True)
|
||||
ticket_number = db.Column(db.String(32), unique=True, nullable=False) # 工单编号
|
||||
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) # 处理备注
|
||||
contact_person = db.Column(db.String(64), nullable=True) # 联系人姓名
|
||||
phone = db.Column(db.String(20), 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) # 关闭时间
|
||||
|
||||
# 关系
|
||||
replies = relationship('TicketReply', backref='ticket', lazy='dynamic', cascade='all, delete-orphan')
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Ticket, self).__init__(**kwargs)
|
||||
# 如果没有提供工单编号,则自动生成
|
||||
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}"
|
||||
|
||||
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,
|
||||
'ticket_number': self.ticket_number,
|
||||
'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,
|
||||
'contact_person': self.contact_person,
|
||||
'phone': self.phone,
|
||||
'processing_days': self.get_processing_days(),
|
||||
'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,
|
||||
'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,
|
||||
'replies': [reply.to_dict() for reply in self.replies.order_by(TicketReply.create_time.asc()).all()]
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Ticket {self.ticket_id}: {self.title}>'
|
||||
Reference in New Issue
Block a user