feat(admin, miniapp): 优化数据库迁移逻辑与小程序图片资源处理
- 为后端Admin新增migration_compat工具,支持离线迁移时的基线资源检查,重构全部alembic迁移脚本适配离线模式,避免重复创建已存在的数据库表和字段 - 完善初始数据库迁移脚本,添加默认部门种子数据,新增ConciergeAdvisor详情字段从JSON到JSONB的类型转换迁移 - 小程序端新增图片资源解析工具resolveNetworkImage,实现本地静态资源到CDN的自动映射,添加图片加载容错降级机制 - 完善HeroSlide类型定义,新增actionLabel字段,优化首页轮播组件的文本渲染与错误处理逻辑 - 新增对应测试用例验证迁移路径正确性与前端数据处理逻辑 - 新增临时 brainstorm UI对比草稿与开发临时状态文件
This commit is contained in:
1 parent
96bcc7c032
commit
4e04feda5b
27 files changed
+2695
-377
No files matched your search
@@ -5,12 +5,15 @@ Revises: 0016_concierge_advisors
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
from alembic import context, op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import inspect
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
from app.migration_compat import baseline_column_names, baseline_table_names
|
||||
|
||||
|
||||
revision = "0017_home_content"
|
||||
down_revision = "0016_concierge_advisors"
|
||||
@@ -142,6 +145,13 @@ SEED_WILD_ARCHIVES = (
|
||||
|
||||
|
||||
def _create_table(table_name: str, columns: list[sa.Column]) -> None:
|
||||
if is_offline_mode():
|
||||
if table_name in baseline_table_names():
|
||||
return
|
||||
op.create_table(table_name, *columns, sa.PrimaryKeyConstraint("id"))
|
||||
op.create_index(f"ix_{table_name}_isActive", table_name, ["isActive"])
|
||||
op.create_index(f"ix_{table_name}_sortOrder", table_name, ["sortOrder"])
|
||||
return
|
||||
bind = op.get_bind()
|
||||
if table_name in set(inspect(bind).get_table_names()):
|
||||
return
|
||||
@@ -178,6 +188,11 @@ def _seed_table(table_name: str, columns: list[sa.Column], rows: tuple[dict, ...
|
||||
column_types = {column.name: column.type for column in columns}
|
||||
if is_offline_mode():
|
||||
available_columns = set(column_types)
|
||||
if table_name in baseline_table_names():
|
||||
available_columns.update(baseline_column_names(table_name))
|
||||
for name, column_type in OPTIONAL_SEED_COLUMN_TYPES.items():
|
||||
if name in available_columns:
|
||||
column_types.setdefault(name, column_type)
|
||||
else:
|
||||
bind = op.get_bind()
|
||||
current_columns = inspect(bind).get_columns(table_name)
|
||||
@@ -200,7 +215,31 @@ def _seed_table(table_name: str, columns: list[sa.Column], rows: tuple[dict, ...
|
||||
],
|
||||
)
|
||||
timestamp = datetime(2026, 1, 1)
|
||||
op.bulk_insert(table, prepare_seed_rows(rows, seed_column_names, timestamp))
|
||||
seed_rows = prepare_seed_rows(rows, seed_column_names, timestamp)
|
||||
if is_offline_mode():
|
||||
seed_rows = [
|
||||
{
|
||||
**row,
|
||||
**{
|
||||
name: json.dumps(row[name], ensure_ascii=False)
|
||||
for name in ("detailParagraphs", "images")
|
||||
if name in row
|
||||
},
|
||||
}
|
||||
for row in seed_rows
|
||||
]
|
||||
for name in ("detailParagraphs", "images"):
|
||||
if name in column_types:
|
||||
column_types[name] = sa.Text()
|
||||
table = sa.table(
|
||||
table_name,
|
||||
*[
|
||||
sa.column(name, column_types[name])
|
||||
for name in column_types
|
||||
if name in seed_column_names
|
||||
],
|
||||
)
|
||||
op.bulk_insert(table, seed_rows)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
|
||||
Reference in new issue
Block a user