调整项目结构,factory只负责暴露方法,不实现业务细节

This commit is contained in:
2025-12-07 00:04:01 +08:00
parent b66f345281
commit 339920a940
23 changed files with 2165 additions and 1231 deletions

View File

@@ -9,11 +9,13 @@ import (
"git.toowon.com/jimmy/go-common/config"
"git.toowon.com/jimmy/go-common/email"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/logger"
"git.toowon.com/jimmy/go-common/middleware"
"git.toowon.com/jimmy/go-common/migration"
"git.toowon.com/jimmy/go-common/sms"
"git.toowon.com/jimmy/go-common/storage"
"git.toowon.com/jimmy/go-common/tools"
"github.com/redis/go-redis/v9"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
@@ -21,6 +23,51 @@ import (
"gorm.io/gorm"
)
// ========== HTTP响应结构体暴露给外部项目使用 ==========
// Response 标准响应结构(暴露给外部项目使用)
// 外部项目可以直接使用 factory.Response 创建响应对象
//
// 示例:
//
// response := factory.Response{
// Code: 0,
// Message: "success",
// Data: data,
// }
type Response = commonhttp.Response
// PageResponse 分页响应结构(暴露给外部项目使用)
// 外部项目可以直接使用 factory.PageResponse 创建分页响应对象
type PageResponse = commonhttp.PageResponse
// PageData 分页数据(暴露给外部项目使用)
// 外部项目可以直接使用 factory.PageData 创建分页数据对象
//
// 示例:
//
// pageData := &factory.PageData{
// List: users,
// Total: 100,
// Page: 1,
// PageSize: 20,
// }
// fac.Success(w, pageData)
type PageData = commonhttp.PageData
// ========== HTTP请求结构体暴露给外部项目使用 ==========
// PaginationRequest 分页请求结构(暴露给外部项目使用)
// 外部项目可以直接使用 factory.PaginationRequest 创建分页请求对象
//
// 示例:
//
// type ListUserRequest struct {
// Keyword string `json:"keyword"`
// factory.PaginationRequest // 嵌入分页请求结构
// }
type PaginationRequest = commonhttp.PaginationRequest
// Factory 工厂类 - 黑盒模式设计
//
// 核心理念:
@@ -90,17 +137,8 @@ func (f *Factory) getEmailClient() (*email.Email, error) {
return f.email, nil
}
if f.cfg.Email == nil {
return nil, fmt.Errorf("email config is nil")
}
e, err := email.NewEmail(f.cfg.Email)
if err != nil {
return nil, fmt.Errorf("failed to create email client: %w", err)
}
f.email = e
return e, nil
f.email = email.NewEmail(f.cfg)
return f.email, nil
}
// SendEmail 发送邮件(黑盒模式,推荐使用)
@@ -114,18 +152,7 @@ func (f *Factory) SendEmail(to []string, subject, body string, htmlBody ...strin
if err != nil {
return err
}
msg := &email.Message{
To: to,
Subject: subject,
Body: body,
}
if len(htmlBody) > 0 && htmlBody[0] != "" {
msg.HTMLBody = htmlBody[0]
}
return e.Send(msg)
return e.SendEmail(to, subject, body, htmlBody...)
}
// getSMSClient 获取短信客户端(内部方法,延迟初始化)
@@ -134,17 +161,8 @@ func (f *Factory) getSMSClient() (*sms.SMS, error) {
return f.sms, nil
}
if f.cfg.SMS == nil {
return nil, fmt.Errorf("SMS config is nil")
}
s, err := sms.NewSMS(f.cfg.SMS)
if err != nil {
return nil, fmt.Errorf("failed to create SMS client: %w", err)
}
f.sms = s
return s, nil
f.sms = sms.NewSMS(f.cfg)
return f.sms, nil
}
// SendSMS 发送短信(黑盒模式,推荐使用)
@@ -157,17 +175,7 @@ func (f *Factory) SendSMS(phoneNumbers []string, templateParam interface{}, temp
if err != nil {
return nil, err
}
req := &sms.SendRequest{
PhoneNumbers: phoneNumbers,
TemplateParam: templateParam,
}
if len(templateCode) > 0 && templateCode[0] != "" {
req.TemplateCode = templateCode[0]
}
return s.Send(req)
return s.SendSMS(phoneNumbers, templateParam, templateCode...)
}
// getLogger 获取日志记录器(内部方法,延迟初始化)
@@ -862,3 +870,328 @@ func (f *Factory) GetMigrationStatus(migrationsDir string) ([]migration.Migratio
return status, nil
}
// ========== HTTP响应方法黑盒模式推荐使用 ==========
//
// 这些方法直接调用 http 包的公共方法,保持低耦合。
// 推荐直接使用 factory.Success() 等方法,而不是通过 handler。
// Success 成功响应(黑盒模式,推荐使用)
// w: ResponseWriter
// data: 响应数据可以为nil
// message: 响应消息(可选),如果为空则使用默认消息 "success"
//
// 示例:
//
// fac, _ := factory.NewFactoryFromFile("config.json")
// http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
// fac.Success(w, user) // 只有数据
// fac.Success(w, user, "查询成功") // 数据+消息
// })
func (f *Factory) Success(w http.ResponseWriter, data interface{}, message ...string) {
commonhttp.Success(w, data, message...)
}
// SuccessPage 分页成功响应(黑盒模式,推荐使用)
// w: ResponseWriter
// list: 数据列表
// total: 总记录数
// page: 当前页码
// pageSize: 每页大小
// message: 响应消息(可选),如果为空则使用默认消息 "success"
func (f *Factory) SuccessPage(w http.ResponseWriter, list interface{}, total int64, page, pageSize int, message ...string) {
commonhttp.SuccessPage(w, list, total, page, pageSize, message...)
}
// Error 错误响应(黑盒模式,推荐使用)
// w: ResponseWriter
// code: 业务错误码非0表示业务错误
// message: 错误消息
func (f *Factory) Error(w http.ResponseWriter, code int, message string) {
commonhttp.Error(w, code, message)
}
// SystemError 系统错误响应返回HTTP 500黑盒模式推荐使用
// w: ResponseWriter
// message: 错误消息
func (f *Factory) SystemError(w http.ResponseWriter, message string) {
commonhttp.SystemError(w, message)
}
// ========== HTTP请求解析方法黑盒模式推荐使用 ==========
//
// 这些方法直接调用 http 包的公共方法,保持低耦合。
// 推荐直接使用 factory.ParseJSON()、factory.GetQuery() 等方法。
// ParseJSON 解析JSON请求体黑盒模式推荐使用
// r: HTTP请求
// v: 目标结构体指针
//
// 示例:
//
// var req struct {
// Name string `json:"name"`
// }
// if err := fac.ParseJSON(r, &req); err != nil {
// fac.Error(w, 400, "请求参数解析失败")
// return
// }
func (f *Factory) ParseJSON(r *http.Request, v interface{}) error {
return commonhttp.ParseJSON(r, v)
}
// ParsePaginationRequest 从请求中解析分页参数(黑盒模式,推荐使用)
// r: HTTP请求
// 支持从查询参数和form表单中解析
// 优先级:查询参数 > form表单
//
// 示例:
//
// pagination := fac.ParsePaginationRequest(r)
// page := pagination.GetPage()
// pageSize := pagination.GetSize()
func (f *Factory) ParsePaginationRequest(r *http.Request) *PaginationRequest {
return commonhttp.ParsePaginationRequest(r)
}
// GetQuery 获取查询参数(字符串)(黑盒模式,推荐使用)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetQuery(r *http.Request, key, defaultValue string) string {
return commonhttp.GetQuery(r, key, defaultValue)
}
// GetQueryInt 获取整数查询参数(黑盒模式,推荐使用)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetQueryInt(r *http.Request, key string, defaultValue int) int {
return commonhttp.GetQueryInt(r, key, defaultValue)
}
// GetQueryInt64 获取int64查询参数黑盒模式推荐使用
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetQueryInt64(r *http.Request, key string, defaultValue int64) int64 {
return commonhttp.GetQueryInt64(r, key, defaultValue)
}
// GetQueryBool 获取布尔查询参数(黑盒模式,推荐使用)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetQueryBool(r *http.Request, key string, defaultValue bool) bool {
return commonhttp.GetQueryBool(r, key, defaultValue)
}
// GetQueryFloat64 获取float64查询参数黑盒模式推荐使用
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetQueryFloat64(r *http.Request, key string, defaultValue float64) float64 {
return commonhttp.GetQueryFloat64(r, key, defaultValue)
}
// GetFormValue 获取表单值(字符串)(黑盒模式,推荐使用)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetFormValue(r *http.Request, key, defaultValue string) string {
return commonhttp.GetFormValue(r, key, defaultValue)
}
// GetFormInt 获取表单整数(黑盒模式,推荐使用)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetFormInt(r *http.Request, key string, defaultValue int) int {
return commonhttp.GetFormInt(r, key, defaultValue)
}
// GetFormInt64 获取表单int64黑盒模式推荐使用
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetFormInt64(r *http.Request, key string, defaultValue int64) int64 {
return commonhttp.GetFormInt64(r, key, defaultValue)
}
// GetFormBool 获取表单布尔值(黑盒模式,推荐使用)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func (f *Factory) GetFormBool(r *http.Request, key string, defaultValue bool) bool {
return commonhttp.GetFormBool(r, key, defaultValue)
}
// GetHeader 获取请求头(黑盒模式,推荐使用)
// r: HTTP请求
// key: 请求头名称
// defaultValue: 默认值
func (f *Factory) GetHeader(r *http.Request, key, defaultValue string) string {
return commonhttp.GetHeader(r, key, defaultValue)
}
// GetTimezone 从请求的context中获取时区黑盒模式推荐使用
// r: HTTP请求
// 如果使用了middleware.Timezone中间件可以从context中获取时区信息
// 如果未设置,返回默认时区 AsiaShanghai
func (f *Factory) GetTimezone(r *http.Request) string {
return commonhttp.GetTimezone(r)
}
// ========== Tools工具方法黑盒模式推荐使用 ==========
//
// 这些方法直接调用 tools 包的公共方法,保持低耦合。
// factory 只负责方法暴露,具体业务在 tools 包中实现。
// ========== Version 版本工具 ==========
// GetVersion 获取版本号(黑盒模式,推荐使用)
// 优先从环境变量 DOCKER_TAG 或 VERSION 中读取
// 如果没有设置环境变量,则使用默认版本号
func (f *Factory) GetVersion() string {
return tools.GetVersion()
}
// ========== Money 金额工具 ==========
// GetMoneyCalculator 获取金额计算器(黑盒模式,推荐使用)
// 返回金额计算器实例,可用于金额计算操作
func (f *Factory) GetMoneyCalculator() *tools.MoneyCalculator {
return tools.NewMoneyCalculator()
}
// YuanToCents 元转分(黑盒模式,推荐使用)
func (f *Factory) YuanToCents(yuan float64) int64 {
return tools.YuanToCents(yuan)
}
// CentsToYuan 分转元(黑盒模式,推荐使用)
func (f *Factory) CentsToYuan(cents int64) float64 {
return tools.CentsToYuan(cents)
}
// FormatYuan 格式化显示金额分转元保留2位小数黑盒模式推荐使用
func (f *Factory) FormatYuan(cents int64) string {
return tools.FormatYuan(cents)
}
// ========== DateTime 日期时间工具 ==========
// Now 获取当前时间(使用指定时区)(黑盒模式,推荐使用)
func (f *Factory) Now(timezone ...string) time.Time {
return tools.Now(timezone...)
}
// ParseDateTime 解析日期时间字符串2006-01-02 15:04:05黑盒模式推荐使用
func (f *Factory) ParseDateTime(value string, timezone ...string) (time.Time, error) {
return tools.ParseDateTime(value, timezone...)
}
// ParseDate 解析日期字符串2006-01-02黑盒模式推荐使用
func (f *Factory) ParseDate(value string, timezone ...string) (time.Time, error) {
return tools.ParseDate(value, timezone...)
}
// FormatDateTime 格式化日期时间2006-01-02 15:04:05黑盒模式推荐使用
func (f *Factory) FormatDateTime(t time.Time, timezone ...string) string {
return tools.FormatDateTime(t, timezone...)
}
// FormatDate 格式化日期2006-01-02黑盒模式推荐使用
func (f *Factory) FormatDate(t time.Time, timezone ...string) string {
return tools.FormatDate(t, timezone...)
}
// FormatTime 格式化时间15:04:05黑盒模式推荐使用
func (f *Factory) FormatTime(t time.Time, timezone ...string) string {
return tools.FormatTime(t, timezone...)
}
// ToUnix 转换为Unix时间戳黑盒模式推荐使用
func (f *Factory) ToUnix(t time.Time) int64 {
return tools.ToUnix(t)
}
// FromUnix 从Unix时间戳创建时间黑盒模式推荐使用
func (f *Factory) FromUnix(sec int64, timezone ...string) time.Time {
return tools.FromUnix(sec, timezone...)
}
// ToUnixMilli 转换为Unix毫秒时间戳黑盒模式推荐使用
func (f *Factory) ToUnixMilli(t time.Time) int64 {
return tools.ToUnixMilli(t)
}
// FromUnixMilli 从Unix毫秒时间戳创建时间黑盒模式推荐使用
func (f *Factory) FromUnixMilli(msec int64, timezone ...string) time.Time {
return tools.FromUnixMilli(msec, timezone...)
}
// AddDays 添加天数(黑盒模式,推荐使用)
func (f *Factory) AddDays(t time.Time, days int) time.Time {
return tools.AddDays(t, days)
}
// AddMonths 添加月数(黑盒模式,推荐使用)
func (f *Factory) AddMonths(t time.Time, months int) time.Time {
return tools.AddMonths(t, months)
}
// AddYears 添加年数(黑盒模式,推荐使用)
func (f *Factory) AddYears(t time.Time, years int) time.Time {
return tools.AddYears(t, years)
}
// StartOfDay 获取一天的开始时间00:00:00黑盒模式推荐使用
func (f *Factory) StartOfDay(t time.Time, timezone ...string) time.Time {
return tools.StartOfDay(t, timezone...)
}
// EndOfDay 获取一天的结束时间23:59:59.999999999)(黑盒模式,推荐使用)
func (f *Factory) EndOfDay(t time.Time, timezone ...string) time.Time {
return tools.EndOfDay(t, timezone...)
}
// StartOfMonth 获取月份的开始时间(黑盒模式,推荐使用)
func (f *Factory) StartOfMonth(t time.Time, timezone ...string) time.Time {
return tools.StartOfMonth(t, timezone...)
}
// EndOfMonth 获取月份的结束时间(黑盒模式,推荐使用)
func (f *Factory) EndOfMonth(t time.Time, timezone ...string) time.Time {
return tools.EndOfMonth(t, timezone...)
}
// StartOfYear 获取年份的开始时间(黑盒模式,推荐使用)
func (f *Factory) StartOfYear(t time.Time, timezone ...string) time.Time {
return tools.StartOfYear(t, timezone...)
}
// EndOfYear 获取年份的结束时间(黑盒模式,推荐使用)
func (f *Factory) EndOfYear(t time.Time, timezone ...string) time.Time {
return tools.EndOfYear(t, timezone...)
}
// DiffDays 计算两个时间之间的天数差(黑盒模式,推荐使用)
func (f *Factory) DiffDays(t1, t2 time.Time) int {
return tools.DiffDays(t1, t2)
}
// DiffHours 计算两个时间之间的小时差(黑盒模式,推荐使用)
func (f *Factory) DiffHours(t1, t2 time.Time) int64 {
return tools.DiffHours(t1, t2)
}
// DiffMinutes 计算两个时间之间的分钟差(黑盒模式,推荐使用)
func (f *Factory) DiffMinutes(t1, t2 time.Time) int64 {
return tools.DiffMinutes(t1, t2)
}
// DiffSeconds 计算两个时间之间的秒数差(黑盒模式,推荐使用)
func (f *Factory) DiffSeconds(t1, t2 time.Time) int64 {
return tools.DiffSeconds(t1, t2)
}