Files
2026-06-25 17:41:06 +08:00

119 lines
5.7 KiB
Python

from tortoise import fields
from .base import BaseModel, TimestampMixin
from .enums import TaskStatus, TaskType, ActionType, TaskStatus, ScenarioScope
class Scenario(BaseModel, TimestampMixin):
title = fields.CharField(max_length=255, description="场景标题", index=True)
trigger = fields.JSONField(description="触发条件(事件/时间)")
actions = fields.JSONField(default=list, description="执行动作模板列表")
visible = fields.BooleanField(default=True, description="是否可见", index=True)
notes = fields.TextField(null=True, description="备注")
is_global = fields.BooleanField(default=True, description="是否全局场景", index=True)
owner_user_id = fields.CharField(max_length=64, null=True, description="归属用户ID(非全局时有效)", index=True)
enabled = fields.BooleanField(default=True, description="是否启用", index=True)
scope = fields.CharEnumField(ScenarioScope, default=ScenarioScope.ALL, description="作用角色范围", index=True)
due_days = fields.IntField(null=True, description="截止时间(天)")
class Meta:
table = "automation_scenario"
indexes = [
["is_global", "enabled"],
["owner_user_id", "enabled"],
]
"""
CREATE TABLE automation_scenario_trigger_index (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
scenario_id BIGINT NOT NULL,
event_name VARCHAR(64) NOT NULL COMMENT '监听的事件名,如 group_chat_updated',
enabled TINYINT(1) NOT NULL DEFAULT 1,
is_global TINYINT(1) NOT NULL DEFAULT 1,
owner_user_id VARCHAR(64) DEFAULT NULL,
scope VARCHAR(8) NOT NULL DEFAULT 'all',
PRIMARY KEY (id),
KEY idx_event_enabled (event_name, enabled),
KEY idx_scenario_id (scenario_id),
CONSTRAINT fk_scenario_def FOREIGN KEY (scenario_id) REFERENCES automation_scenario(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
"""
class ScenarioTriggerIndex(BaseModel, TimestampMixin):
scenario_id = fields.BigIntField(description="场景ID")
type = fields.CharEnumField(TaskType, default=TaskType.EVENT, description="事件类型", index=True)
event_name = fields.CharField(max_length=64, description="监听的事件名,如 group_chat_updated", index=True)
enabled = fields.BooleanField(default=True, description="是否启用", index=True)
is_global = fields.BooleanField(default=True, description="是否全局场景", index=True)
owner_user_id = fields.CharField(max_length=64, null=True, description="归属用户ID(非全局时有效)", index=True)
scope = fields.CharEnumField(ScenarioScope, default=ScenarioScope.ALL, description="作用角色范围")
class Meta:
table = "automation_scenario_trigger_index"
class Task(BaseModel, TimestampMixin):
title = fields.CharField(max_length=255, description="待办标题", index=True)
event_data = fields.JSONField(default=dict, description="事件数据")
notes = fields.TextField(null=True, description="备注")
reason = fields.TextField(null=True, description="触发原因")
completed_at = fields.DatetimeField(null=True, description="完成时间")
# 关联字段
source_scenario = fields.ForeignKeyField(
"models.Scenario",
related_name="generated_tasks",
null=True,
on_delete=fields.SET_NULL,
description="来源场景"
)
related_order_id = fields.CharField(max_length=64, null=True, description="关联订单ID", index=True)
owner_user_id = fields.CharField(max_length=64, null=True, description="归属用户ID", index=True)
# 分配与状态
assignee_user_id = fields.CharField(max_length=64, null=True, description="指派人用户ID", index=True)
assignee_username = fields.CharField(max_length=64, null=True, description="指派人用户名", index=True)
status = fields.CharEnumField(TaskStatus, default=TaskStatus.PENDING, description="任务状态", index=True)
# 自动化控制
due_at = fields.DatetimeField(null=True, description="截止时间")
auto_closeable = fields.BooleanField(default=True, description="是否允许自动消除")
closed_by = fields.CharField(max_length=32, null=True, description="关闭方式: manual/auto/expired", index=True)
class Meta:
table = "automation_task"
indexes = [
["assignee_user_id", "status"],
]
class Action(BaseModel, TimestampMixin):
type = fields.CharEnumField(ActionType, null=True, description="操作类型", index=True)
detail = fields.JSONField(default={}, description="操作详情")
done = fields.BooleanField(default=False, description="是否已完成", index=True)
done_at = fields.DatetimeField(null=True, description="完成时间")
result = fields.JSONField(default={}, description="操作结果")
userid = fields.CharField(max_length=64, null=True, description="操作用户ID", index=True)
username = fields.CharField(max_length=64, null=True, description="操作用户名称", index=True)
notes = fields.TextField(null=True, description="操作备注")
# 硬外键:必须属于一个 Task
task = fields.ForeignKeyField(
"models.Task",
related_name="actions",
null=True, # ← 允许为空
on_delete=fields.SET_NULL, # ← 注意:CASCADE 不能和 null=True 同时用于 SET_NULL
description="所属任务"
)
# 可选:记录来自哪个动作模板(场景中的定义)
action_template_id = fields.CharField(max_length=64, null=True, description="操作模板ID", index=True)
class Meta:
table = "automation_action"
indexes = [
["task_id", "done"], # 优化查询未完成动作
["type", "done"],
]