build: 打通 FastAPI 与 Vue 最小工程、依赖与数据库连接

后端入口、配置、Redis 与 Alembic 迁移就位;前端 Vite 工程可安装可构建。
This commit is contained in:
WangShen007 committed 2026-09-22 20:15:00 +08:00
1 parent ec5835ca77
commit 977783c126
167 files changed
+26082

No files matched your search

@@ -0,0 +1,43 @@
"""CSAT score linkage on tickets
Revision ID: add_tkt_csat_001
Revises: add_tkt_row_scope_001
Create Date: 2026-07-22
The CSAT ask already goes out on close; nothing carried the answer back. These
columns close the loop: when the customer rates the conversation linked to a
ticket, the score lands on the ticket itself, so AI-resolved vs human-resolved
CSAT is a plain query instead of a join through ratings/sessions.
"""
from alembic import op
import sqlalchemy as sa
revision = "add_tkt_csat_001"
down_revision = "add_tkt_row_scope_001"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column("tickets", sa.Column("csat_requested_at", sa.DateTime(timezone=True), nullable=True))
op.add_column("tickets", sa.Column("csat_score", sa.Integer(), nullable=True))
op.add_column("tickets", sa.Column("csat_rating_id", sa.UUID(), nullable=True))
op.add_column("tickets", sa.Column("csat_responded_at", sa.DateTime(timezone=True), nullable=True))
op.create_foreign_key(
"fk_tickets_csat_rating_id",
"tickets",
"ratings",
["csat_rating_id"],
["id"],
ondelete="SET NULL",
)
op.create_index("ix_tickets_org_csat", "tickets", ["organization_id", "csat_responded_at"])
def downgrade() -> None:
op.drop_index("ix_tickets_org_csat", table_name="tickets")
op.drop_constraint("fk_tickets_csat_rating_id", "tickets", type_="foreignkey")
op.drop_column("tickets", "csat_responded_at")
op.drop_column("tickets", "csat_rating_id")
op.drop_column("tickets", "csat_score")
op.drop_column("tickets", "csat_requested_at")