Files
WonderQ-Project/WonderQ-Admin/alembic/versions/0001_initial_schema.py
duanshuwen 4e04feda5b feat(admin, miniapp): 优化数据库迁移逻辑与小程序图片资源处理
- 为后端Admin新增migration_compat工具,支持离线迁移时的基线资源检查,重构全部alembic迁移脚本适配离线模式,避免重复创建已存在的数据库表和字段
- 完善初始数据库迁移脚本,添加默认部门种子数据,新增ConciergeAdvisor详情字段从JSON到JSONB的类型转换迁移
- 小程序端新增图片资源解析工具resolveNetworkImage,实现本地静态资源到CDN的自动映射,添加图片加载容错降级机制
- 完善HeroSlide类型定义,新增actionLabel字段,优化首页轮播组件的文本渲染与错误处理逻辑
- 新增对应测试用例验证迁移路径正确性与前端数据处理逻辑
- 新增临时 brainstorm UI对比草稿与开发临时状态文件
2026-08-27 11:37:03 +08:00

73 lines
2.0 KiB
Python

"""Initial SQLAlchemy schema.
Revision ID: 0001_initial_schema
Revises:
Create Date: 2026-06-30
"""
from datetime import datetime, timezone
from alembic import context, op
import sqlalchemy as sa
from sqlalchemy import inspect
from app.database import Base
from app import models # noqa: F401
revision = "0001_initial_schema"
down_revision = None
branch_labels = None
depends_on = None
DEFAULT_DEPT_ID = "00000000-0000-0000-0000-000000000001"
def _seed_default_department(bind) -> None:
department_table = sa.table(
"AdminDepartment",
sa.column("id", sa.String()),
sa.column("name", sa.String()),
sa.column("sortOrder", sa.Integer()),
sa.column("isActive", sa.Boolean()),
sa.column("createdAt", sa.DateTime()),
sa.column("updatedAt", sa.DateTime()),
)
if context.is_offline_mode():
should_seed = True
else:
should_seed = bind.execute(
sa.text('SELECT 1 FROM "AdminDepartment" LIMIT 1')
).first() is None
if should_seed:
timestamp = datetime.now(timezone.utc).replace(tzinfo=None)
op.bulk_insert(
department_table,
[
{
"id": DEFAULT_DEPT_ID,
"name": "默认部门",
"sortOrder": 0,
"isActive": True,
"createdAt": timestamp,
"updatedAt": timestamp,
}
],
)
def upgrade() -> None:
bind = op.get_bind()
if context.is_offline_mode():
Base.metadata.create_all(bind=bind, checkfirst=False)
return
existing_tables = set(inspect(bind).get_table_names())
for table in Base.metadata.sorted_tables:
if table.name not in existing_tables:
table.create(bind)
if "AdminDepartment" in Base.metadata.tables:
_seed_default_department(bind)
def downgrade() -> None:
Base.metadata.drop_all(bind=op.get_bind(), checkfirst=not context.is_offline_mode())