- 新增 seed 迁移插入完整菜单树(4 directory + 23 menu = 27 条) - 新增 GET /api/v1/menus/user 端点(仅需登录,无需 menu.list 权限) - MainLayout 从 API 动态获取菜单树替换硬编码数组 - 扩展图标映射表覆盖 22 个 Ant Design 图标 - Header 标题从动态菜单数据查找,保留 fallback
129 lines
6.9 KiB
Rust
129 lines
6.9 KiB
Rust
use sea_orm_migration::prelude::*;
|
|
|
|
#[derive(DeriveMigrationName)]
|
|
pub struct Migration;
|
|
|
|
#[async_trait::async_trait]
|
|
impl MigrationTrait for Migration {
|
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
|
let db = manager.get_connection();
|
|
|
|
// 软删除已有菜单数据
|
|
db.execute(sea_orm::Statement::from_string(
|
|
sea_orm::DatabaseBackend::Postgres,
|
|
"UPDATE menus SET deleted_at = NOW() WHERE deleted_at IS NULL".to_string(),
|
|
))
|
|
.await?;
|
|
|
|
// 获取默认租户 ID
|
|
let result = db.query_one(sea_orm::Statement::from_string(
|
|
sea_orm::DatabaseBackend::Postgres,
|
|
"SELECT id::text FROM tenant LIMIT 1".to_string(),
|
|
))
|
|
.await?;
|
|
|
|
let tid = match result {
|
|
Some(row) => row.try_get_by_index::<String>(0).unwrap_or_default(),
|
|
None => return Ok(()),
|
|
};
|
|
|
|
let sys = "00000000-0000-0000-0000-000000000000";
|
|
let nil = "NULL";
|
|
|
|
// === Directory 节点 ===
|
|
insert_dir(db, &tid, "a0000000-0000-0000-0000-000000000001", "基础模块", 1, sys).await?;
|
|
insert_dir(db, &tid, "a0000000-0000-0000-0000-000000000002", "业务模块", 2, sys).await?;
|
|
insert_dir(db, &tid, "a0000000-0000-0000-0000-000000000003", "健康管理", 3, sys).await?;
|
|
insert_dir(db, &tid, "a0000000-0000-0000-0000-000000000004", "系统", 4, sys).await?;
|
|
|
|
// === 基础模块菜单 ===
|
|
let d1 = "a0000000-0000-0000-0000-000000000001";
|
|
insert_menu(db, &tid, d1, "b0000001-0000-0000-0000-000000000001", "工作台", "/", "HomeOutlined", 0, sys).await?;
|
|
insert_menu(db, &tid, d1, "b0000001-0000-0000-0000-000000000002", "用户管理", "/users", "UserOutlined", 1, sys).await?;
|
|
insert_menu(db, &tid, d1, "b0000001-0000-0000-0000-000000000003", "权限管理", "/roles", "SafetyOutlined", 2, sys).await?;
|
|
insert_menu(db, &tid, d1, "b0000001-0000-0000-0000-000000000004", "组织架构", "/organizations", "ApartmentOutlined", 3, sys).await?;
|
|
|
|
// === 业务模块菜单 ===
|
|
let d2 = "a0000000-0000-0000-0000-000000000002";
|
|
insert_menu(db, &tid, d2, "b0000002-0000-0000-0000-000000000001", "工作流", "/workflow", "PartitionOutlined", 0, sys).await?;
|
|
insert_menu(db, &tid, d2, "b0000002-0000-0000-0000-000000000002", "消息中心", "/messages", "MessageOutlined", 1, sys).await?;
|
|
|
|
// === 健康管理菜单 ===
|
|
let d3 = "a0000000-0000-0000-0000-000000000003";
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000001", "统计报表", "/health/statistics", "DashboardOutlined", 0, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000002", "患者管理", "/health/patients", "TeamOutlined", 1, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000003", "医护管理", "/health/doctors", "MedicineBoxOutlined", 2, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000004", "预约排班", "/health/appointments", "CalendarOutlined", 3, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000005", "排班管理", "/health/schedules", "HeartOutlined", 4, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000006", "随访管理", "/health/follow-up-tasks", "PhoneOutlined", 5, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000007", "咨询管理", "/health/consultations", "CommentOutlined", 6, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000008", "标签管理", "/health/tags", "TagsOutlined", 7, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000009", "积分规则", "/health/points-rules", "TrophyOutlined", 8, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000010", "商品管理", "/health/points-products", "ShopOutlined", 9, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000011", "订单管理", "/health/points-orders", "FileTextOutlined", 10, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000012", "线下活动", "/health/offline-events", "CalendarOutlined", 11, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000013", "AI Prompt 管理", "/health/ai-prompts", "RobotOutlined", 12, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000014", "AI 分析历史", "/health/ai-analysis", "HistoryOutlined", 13, sys).await?;
|
|
insert_menu(db, &tid, d3, "b0000003-0000-0000-0000-000000000015", "AI 用量统计", "/health/ai-usage", "BarChartOutlined", 14, sys).await?;
|
|
|
|
// === 系统菜单 ===
|
|
let d4 = "a0000000-0000-0000-0000-000000000004";
|
|
insert_menu(db, &tid, d4, "b0000004-0000-0000-0000-000000000001", "系统设置", "/settings", "SettingOutlined", 0, sys).await?;
|
|
insert_menu(db, &tid, d4, "b0000004-0000-0000-0000-000000000002", "插件管理", "/plugins/admin", "AppstoreOutlined", 1, sys).await?;
|
|
|
|
let _ = nil;
|
|
Ok(())
|
|
}
|
|
|
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
|
let db = manager.get_connection();
|
|
db.execute(sea_orm::Statement::from_string(
|
|
sea_orm::DatabaseBackend::Postgres,
|
|
"DELETE FROM menus WHERE id LIKE 'a0000000-0000-0000-0000-00000000000%' OR id LIKE 'b000000%-0000-0000-0000-00000000000%'".to_string(),
|
|
))
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
async fn insert_dir(
|
|
db: &sea_orm_migration::SchemaManagerConnection<'_>,
|
|
tenant_id: &str,
|
|
id: &str,
|
|
title: &str,
|
|
sort: i32,
|
|
sys: &str,
|
|
) -> Result<(), DbErr> {
|
|
db.execute(sea_orm::Statement::from_string(
|
|
sea_orm::DatabaseBackend::Postgres,
|
|
format!(
|
|
"INSERT INTO menus (id, tenant_id, parent_id, title, path, icon, sort_order, visible, menu_type, permission, created_at, updated_at, created_by, updated_by, deleted_at, version) \
|
|
VALUES ('{id}', '{tenant_id}', NULL, '{title}', NULL, NULL, {sort}, true, 'directory', NULL, NOW(), NOW(), '{sys}', '{sys}', NULL, 1) ON CONFLICT (id) DO NOTHING"
|
|
),
|
|
))
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn insert_menu(
|
|
db: &sea_orm_migration::SchemaManagerConnection<'_>,
|
|
tenant_id: &str,
|
|
parent_id: &str,
|
|
id: &str,
|
|
title: &str,
|
|
path: &str,
|
|
icon: &str,
|
|
sort: i32,
|
|
sys: &str,
|
|
) -> Result<(), DbErr> {
|
|
db.execute(sea_orm::Statement::from_string(
|
|
sea_orm::DatabaseBackend::Postgres,
|
|
format!(
|
|
"INSERT INTO menus (id, tenant_id, parent_id, title, path, icon, sort_order, visible, menu_type, permission, created_at, updated_at, created_by, updated_by, deleted_at, version) \
|
|
VALUES ('{id}', '{tenant_id}', '{parent_id}', '{title}', '{path}', '{icon}', {sort}, true, 'menu', NULL, NOW(), NOW(), '{sys}', '{sys}', NULL, 1) ON CONFLICT (id) DO NOTHING"
|
|
),
|
|
))
|
|
.await?;
|
|
Ok(())
|
|
}
|