欢迎光临
我们一直在努力

UisimpleQR解析

UiSimpleQR 是 uipageframe 的三泛型版本,位于 uiframe 包中(注意包名是 uiframe 而非 uipageframe)。以下是深度解析:

 UiSimpleQR 框架核心解析
UiSimpleQR 是 uipageframe 框架的进阶版,核心差异在于它采用了三泛型参数,支持查询参数 → 实体 → DTO 的完整转换链路,专门用于复杂业务场景下的联表查询和 DTO 映射。

 一、与 UiSimpleR 的对比
特性    UiSimpleR[E, P]    UiSimpleQR[Q, E, R]
泛型参数    2个:实体 E + 参数 P    3个:查询 Q + 实体 E + 返回 DTO R
适用场景    单表 CRUD    联表查询、DTO 映射、复杂报表
查询对象    self.Param    self.Query
返回类型    PageResult[E]    PageResult[R](DTO 类型)
核心方法    QueryModel()    QueryModelR()

 二、三泛型参数定义
type UiSimpleQR[Q any, E any, R any] struct {
    basedto.BaseEntity
    Query        Q           // 查询参数(前端传入)
    Param        E           // 实体参数(中间转换)
    PageDbRequest *pagedb.PageDbWebRequest
    
    // 继承自 UiSimpleR 的能力
    *UiSimpleR[E, E]  // 内嵌双泛型版本
    
    // DTO 转换器
    FillRows     interface{}
    FillRow      interface{}
}

泛型    含义    示例
Q    Query 查询条件参数    TrainFlowQuery
E    Entity 数据库实体    *StudentTrainFlow
R    Result/DTO 返回给前端的 DTO    *TransDto

 三、完整使用案例:训练流转查询
 1. 定义三层数据结构
// ========== ① Query 层:前端查询条件 ==========
package trainflow

type TrainFlowQuery struct {
    basedto.BaseEntitySingle
    StudentId      int64             `json:"studentId,string"`   // 学生ID
    TrialTrainType apitype.TrainType `json:"trialTrainType"`      // 试训类型
    User           *model.User       `json:"-"`                   // 当前用户(内部使用)
}

// ========== ② Entity 层:数据库实体 ==========
package uitraintype

type StudentTrainFlow struct {
    // … 数据库表字段
    StudentId        int64     `json:"studentId,string"`
    TrialTrainType   int32     `json:"trialTrainType"`
    FlowType         int32     `json:"flowType"`
    TransStatus      int32     `json:"transStatus"`
    TrialCoachFrom   int64     `json:"trialCoachFrom,string"`
    TrialCoachAccept int64     `json:"trialCoachAccept,string"`
    // …
}

// ========== ③ DTO 层:返回给前端的数据 ==========
package trainflow

type TransDto struct {
    basedto.BaseEntity
    TrialStatus      int       `json:"trialStatus"`      // 试训状态
    CommitAt         time.Time `json:"commitAt"`         // 提交时间
    ReviewAt         time.Time `json:"reviewAt"`         // 审核时间
    TrialCoachFrom   int64     `json:"fromId,string"`    // 转出教练ID
    TrialCoachAccept int64     `json:"toId,string"`      // 转收教练ID
    TrialTrainType   int       `json:"trialTrainType"`   // 试训类型
    FromName         string    `json:"fromName"`         // 转出教练姓名
    ToName           string    `json:"toName"`           // 转收教练姓名
    CommitOpinion    string    `json:"commitOpinion"`    // 提交意见
    ReviewOpinion    string    `json:"reviewOpinion"`    // 审核意见
}

 2. 创建 UiSimpleQR Request
package traintype

import (
    "gitea.super-study.com/ys-study/gotrain/beapi/db/apiconst"
    "gitea.super-study.com/ys-study/gotrain/beapi/db/dbentity/stuentity/uitraintype"
    "gitea.super-study.com/ys-study/gotrain/beapi/dbopc/opcdto/trainflow"
    "gitea.super-study.com/ys-study/gotrain/beapi/gotool/dbframe/uiframe"
    "gitee.com/gowebframe3/webframe.git/goconfig/base/basedto"
    "gitee.com/gowebframe3/webframe.git/goweb/pagemodel"
)

// 三泛型:[Query, Entity, DTO]
type UiStudentTrainFlow struct {
    basedto.BaseEntity `json:"-"`
    uiframe.UiSimpleQR[trainflow.TrainFlowQuery, *uitraintype.StudentTrainFlow, *trainflow.TransDto]
}

func NewUiStudentTrainFlow() *UiStudentTrainFlow {
    var req = &UiStudentTrainFlow{}
    req.InitDao()      // 初始化 DAO
    req.initQuery()    // 配置查询条件
    return req
}

 3. 配置动态查询条件
func (self *UiStudentTrainFlow) initQuery() *UiStudentTrainFlow {
    self.SetBeforeQuery(func() {
        // 构建通用参数(分页、排序等)
        self.BuildGeneralParams(self.PageDbRequest)
        
        // 条件1:按学生ID筛选
        if self.Query.StudentId > 0 {
            self.DbEq("student_id", self.Query.StudentId)
        }
        
        // 条件2:按试训类型筛选
        if self.Query.TrialTrainType > 0 {
            self.DbEq("trial_train_type", self.Query.TrialTrainType)
        }
        
        // 条件3:固定条件 – 只查转训类型
        self.DbEq("flow_type", apiconst.TransTransFlowType)
    })
    return self
}

 4. 核心查询方法
// 对外暴露的业务方法
func (self *UiStudentTrainFlow) UiQueryTransFlow() *pagemodel.PageResult[*trainflow.TransDto] {
    var uiret = self.List()
    
    // DTO 后处理:填充教练姓名(联表查询的替代方案)
    if uiret.ExistRecord() {
        for _, item := range uiret.Data {
            userservice.FindBeanUserService().CacheFillName(&item.FromName, item.TrialCoachFrom)
            userservice.FindBeanUserService().CacheFillName(&item.ToName, item.TrialCoachAccept)
        }
    }
    return uiret
}

// 底层 List 方法
func (self *UiStudentTrainFlow) List() *pagemodel.PageResult[*trainflow.TransDto] {
    self.BuildRequest().BeforeQuery()()   // 构建请求 + 执行前置条件
    if self.OrderBys == "" {
        self.OrderByDesc("created_at")     // 默认排序
    }
    return self.QueryModelR()              // ⭐ 关键:调用三泛型查询
}

 四、核心方法:QueryModelR()
func (self *UiSimpleR[E, R]) QueryModelR(pagesize …int) *pagemodel.PageResult[R] {
    // ① 先执行基础泛型查询(返回 Entity 类型)
    var ret = self.QueryModel(pagesize…)
    
    // ② 将 Entity 分页结果转换为 DTO 分页结果
    return self.PageTo(ret)
}

执行流程:
前端请求 JSON
    │
    ▼
┌─────────────────┐
│  BindQuery()    │  ← 解析到 Query 泛型 (TrainFlowQuery)
│  (self.Query)   │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  BuildRequest() │  ← 构建分页请求
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ BeforeQuery()() │  ← 动态条件(DbEq/DbLike 等)
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  QueryModel()   │  ← 查询数据库,返回 PageResult[Entity]
│                 │  ← StudentTrainFlow 列表
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│   PageTo()      │  ← Entity → DTO 转换
│                 │  ← 字段映射 + 数据填充
└────────┬────────┘
         │
         ▼
  PageResult[DTO]  ← 返回前端 (TransDto)

 五、另一个案例:取消流水查询
type UiStudentTrainFlowcancel struct {
    basedto.BaseEntity `json:"-"`
    // 三泛型:相同 Query,相同 Entity,不同 DTO (CancelDto)
    uiframe.UiSimpleQR[trainflow.TrainFlowQuery, *uitraintype.StudentTrainFlow, *trainflow.CancelDto]
}

func (self *UiStudentTrainFlowcancel) initQuery() *UiStudentTrainFlowcancel {
    self.SetBeforeQuery(func() {
        self.BuildGeneralParams(self.PageDbRequest)
        if self.Query.StudentId > 0 {
            self.DbEq("student_id", self.Query.StudentId)
        }
        if self.Query.TrialTrainType > 0 {
            self.DbEq("trial_train_type", self.Query.TrialTrainType)
        }
        
        // 区别:查询多种 flow_type
        self.DbIn("flow_type", apiconst.TransCancelFlowType, apiconst.TransCancelPlanType)
    })
    return self
}

func (self *UiStudentTrainFlowcancel) UiQueryCancelFlow() *pagemodel.PageResult[*trainflow.CancelDto] {
    return self.List()  // 直接返回,无需额外处理
}

func (self *UiStudentTrainFlowcancel) List() *pagemodel.PageResult[*trainflow.CancelDto] {
    self.BuildRequest().BeforeQuery()()
    if self.OrderBys == "" {
        self.OrderByDesc("created_at")
    }
    return self.QueryModelR()
}

关键洞察: 相同的 Query 和 Entity,通过更换第三个泛型 R(TransDto vs CancelDto),实现了同一数据源的不同视图返回。

 六、与 UiSimpleR 的架构关系
┌─────────────────────────────────────────────────────────────┐
│                    uiframe.UiSimpleQR[Q, E, R]               │
│                    (三泛型 – 复杂场景)                         │
│                         ↓ 内嵌                               │
├─────────────────────────────────────────────────────────────┤
│                    uipageframe.UiSimpleR[E, P]               │
│                    (双泛型 – 基础场景)                         │
│                         ↓ 调用                               │
├─────────────────────────────────────────────────────────────┤
│                    goweb/generaldb/generaldao                │
│                    GeneralDao[E] (泛型 DAO)                   │
└─────────────────────────────────────────────────────────────┘

 七、适用场景总结
场景    推荐框架    原因
单表 CRUD,返回实体    UiSimpleR[E, P]    简单直接
联表查询,需要 DTO 映射    UiSimpleQR[Q, E, R]    三泛型分离
同一实体,多种返回视图    UiSimpleQR    更换 R 泛型即可
需要后处理填充关联数据    UiSimpleQR    DTO 层独立处理
复杂报表,字段来自多表    UiSimpleQR    Query 条件 + DTO 结果解耦

 八、核心设计哲学
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Query     │────→│   Entity    │────→│    DTO      │
│  (前端条件)  │     │  (数据库表)  │     │ (返回前端)   │
│             │     │             │     │             │
│ StudentId   │     │ student_id  │     │ FromName    │
│ TrainType   │     │ flow_type   │     │ ToName      │
│             │     │ trans_status│     │ CommitAt    │
└─────────────┘     └─────────────┘     └─────────────┘
       Q                  E                   R
       
       ↑                  ↑                   ↑
   动态条件构建        数据库查询映射          Entity→DTO转换
   (SetBeforeQuery)   (QueryModel)          (PageTo)

UiSimpleQR 的精髓在于通过泛型在编译期固化三层数据结构,避免了运行时的类型断言和反射,同时保持了代码的整洁和可维护性。
 

赞(0)
未经允许不得转载:171主机测评 » UisimpleQR解析
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址