Files
hms/crates/erp-plugin/src/data_dto.rs
iven a7a48167ca feat(plugin): P1-P4 审计修复 — 第三批 (配置变更通知 + 自定义视图)
3.1 配置变更通知:
- update_config 增加 EventBus 参数
- 更新成功后发布 plugin.config.updated 事件
- handler 传入 event_bus

3.2 自定义视图:
- plugin_user_views 表迁移 (id/tenant_id/user_id/plugin_id/entity/view_name/view_config/is_default)
- CRUD API: GET/POST /plugins/{id}/{entity}/views, DELETE /plugins/{id}/{entity}/views/{view_id}
- 默认视图互斥逻辑
2026-04-19 18:25:03 +08:00

331 lines
9.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
/// 插件数据记录响应
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PluginDataResp {
pub id: String,
pub data: serde_json::Value,
pub created_at: Option<DateTime<Utc>>,
pub updated_at: Option<DateTime<Utc>>,
pub version: Option<i32>,
}
/// 创建插件数据请求
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct CreatePluginDataReq {
pub data: serde_json::Value,
}
/// 更新插件数据请求(全量替换)
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct UpdatePluginDataReq {
pub data: serde_json::Value,
pub version: i32,
}
/// 部分更新请求PATCH — 只合并提供的字段)
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PatchPluginDataReq {
pub data: serde_json::Value,
pub version: i32,
}
/// 插件数据列表查询参数
#[derive(Debug, Serialize, Deserialize, utoipa::IntoParams)]
pub struct PluginDataListParams {
pub page: Option<u64>,
pub page_size: Option<u64>,
/// Base64 编码的游标(用于 Keyset 分页)
pub cursor: Option<String>,
pub search: Option<String>,
/// JSON 格式过滤: {"field":"value"}
pub filter: Option<String>,
pub sort_by: Option<String>,
/// "asc" or "desc"
pub sort_order: Option<String>,
}
/// 聚合查询响应项
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct AggregateItem {
/// 分组键(字段值)
pub key: String,
/// 计数
pub count: i64,
}
/// 多聚合查询响应项
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct AggregateMultiRow {
/// 分组键
pub key: String,
/// 计数
pub count: i64,
/// 聚合指标: {"sum_amount": 5000.0, "avg_price": 25.5}
#[serde(default)]
pub metrics: std::collections::HashMap<String, f64>,
}
/// 聚合查询参数
#[derive(Debug, Serialize, Deserialize, utoipa::IntoParams)]
pub struct AggregateQueryParams {
/// 分组字段名
pub group_by: String,
/// JSON 格式过滤: {"field":"value"}
pub filter: Option<String>,
}
/// 多聚合查询请求体
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct AggregateMultiReq {
/// 分组字段名
pub group_by: String,
/// 聚合定义列表: [{"func": "sum", "field": "amount"}]
pub aggregations: Vec<AggregateDefDto>,
/// JSON 格式过滤
pub filter: Option<serde_json::Value>,
}
/// 单个聚合定义
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct AggregateDefDto {
/// 聚合函数: count, sum, avg, min, max
pub func: String,
/// 字段名
pub field: String,
}
/// 统计查询参数
#[derive(Debug, Serialize, Deserialize, utoipa::IntoParams)]
pub struct CountQueryParams {
/// 搜索关键词
pub search: Option<String>,
/// JSON 格式过滤: {"field":"value"}
pub filter: Option<String>,
}
/// 批量操作请求
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct BatchActionReq {
/// 操作类型: "batch_delete" 或 "batch_update"
pub action: String,
/// 记录 ID 列表(上限 100
pub ids: Vec<String>,
/// batch_update 时的更新数据
pub data: Option<serde_json::Value>,
}
/// 时间序列查询参数
#[derive(Debug, Serialize, Deserialize, utoipa::IntoParams)]
pub struct TimeseriesParams {
/// 时间字段名
pub time_field: String,
/// 时间粒度: "day" / "week" / "month"
pub time_grain: String,
/// 开始日期 (ISO)
pub start: Option<String>,
/// 结束日期 (ISO)
pub end: Option<String>,
}
/// 时间序列数据项
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct TimeseriesItem {
/// 时间周期
pub period: String,
/// 计数
pub count: i64,
}
// ─── 跨插件引用 DTO ──────────────────────────────────────────────────
/// 批量标签解析请求
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ResolveLabelsReq {
/// 字段名 → UUID 列表
pub fields: std::collections::HashMap<String, Vec<String>>,
}
/// 批量标签解析响应
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ResolveLabelsResp {
/// 字段名 → { uuid: label } 映射
pub labels: serde_json::Value,
/// 字段名 → 目标插件元信息
pub meta: serde_json::Value,
}
/// 公开实体信息(实体注册表查询响应)
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PublicEntityResp {
pub manifest_id: String,
pub plugin_id: String,
pub entity_name: String,
pub display_name: String,
}
// ─── 导入导出 DTO ──────────────────────────────────────────────────
/// 数据导出参数
#[derive(Debug, Serialize, Deserialize, utoipa::IntoParams)]
pub struct ExportParams {
/// JSON 格式过滤: {"field":"value"}
pub filter: Option<String>,
/// 搜索关键词
pub search: Option<String>,
/// 排序字段
pub sort_by: Option<String>,
/// "asc" or "desc"
pub sort_order: Option<String>,
/// 导出格式: "json" (默认) | "csv" | "xlsx"
pub format: Option<String>,
}
/// 导出结果 — 根据格式返回不同内容
pub enum ExportPayload {
Json(Vec<serde_json::Value>),
Csv(Vec<u8>),
Xlsx(Vec<u8>),
}
/// 数据导入请求
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ImportReq {
/// 导入数据行列表,每行是一个 JSON 对象
pub rows: Vec<serde_json::Value>,
}
/// 数据导入结果
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ImportResult {
/// 成功导入行数
pub success_count: usize,
/// 失败行数
pub error_count: usize,
/// 每行错误详情: [{ row: 0, errors: ["字段 xxx 必填"] }]
#[serde(default)]
pub errors: Vec<ImportRowError>,
}
/// 单行导入错误
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ImportRowError {
/// 行号0-based
pub row: usize,
/// 错误消息列表
pub errors: Vec<String>,
}
// ─── 市场目录 DTO ──────────────────────────────────────────────────
/// 市场条目列表查询参数
#[derive(Debug, Serialize, Deserialize, utoipa::IntoParams)]
pub struct MarketListParams {
pub page: Option<u64>,
pub page_size: Option<u64>,
pub category: Option<String>,
pub search: Option<String>,
}
/// 市场条目响应(不含二进制数据)
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct MarketEntryResp {
pub id: String,
pub plugin_id: String,
pub name: String,
pub version: String,
pub description: Option<String>,
pub author: Option<String>,
pub category: Option<String>,
pub tags: Option<serde_json::Value>,
pub icon_url: Option<String>,
pub screenshots: Option<serde_json::Value>,
pub min_platform_version: Option<String>,
pub status: String,
pub download_count: i32,
pub rating_avg: f64,
pub rating_count: i32,
pub changelog: Option<String>,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}
/// 市场条目详情响应(含完整信息)
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct MarketEntryDetailResp {
#[serde(flatten)]
pub entry: MarketEntryResp,
/// 依赖提示(安装时检查 manifest.dependencies
pub dependency_warnings: Vec<String>,
}
/// 提交评分/评论请求
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct SubmitReviewReq {
/// 评分 1-5
pub rating: i32,
/// 评论内容
pub review_text: Option<String>,
}
/// 评论响应
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct MarketReviewResp {
pub id: String,
pub user_id: String,
pub market_entry_id: String,
pub rating: i32,
pub review_text: Option<String>,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
}
// ─── 对账扫描 DTO ──────────────────────────────────────────────────
/// 对账报告
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ReconciliationReport {
/// 有效引用数
pub valid_count: i64,
/// 悬空引用数
pub dangling_count: i64,
/// 悬空引用详情
pub details: Vec<DanglingRef>,
}
/// 悬空引用详情
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct DanglingRef {
/// 实体名
pub entity: String,
/// 字段名
pub field: String,
/// 记录 ID
pub record_id: String,
/// 悬空的 UUID 值
pub dangling_value: String,
}
// ─── 自定义视图 DTO ──────────────────────────────────────────────────
/// 用户视图配置请求
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct UserViewReq {
pub view_name: String,
pub view_config: serde_json::Value,
pub is_default: Option<bool>,
}
/// 用户视图响应
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
pub struct UserViewResp {
pub id: String,
pub plugin_id: String,
pub entity_name: String,
pub view_name: String,
pub view_config: serde_json::Value,
pub is_default: bool,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}