2026-07-27 01:32:44 +08:00
|
|
|
// Package platform 提供平台总后台的同步 HTTP 业务逻辑。
|
2026-07-26 18:29:36 +08:00
|
|
|
package platform
|
|
|
|
|
|
|
|
|
|
import (
|
2026-07-27 00:18:42 +08:00
|
|
|
"errors"
|
|
|
|
|
|
2026-07-26 18:29:36 +08:00
|
|
|
"git.apinb.com/bsm-sdk/core/errcode"
|
|
|
|
|
"git.apinb.com/bsm-sdk/core/infra"
|
|
|
|
|
"git.apinb.com/bsm-sdk/core/utils"
|
2026-07-27 00:18:42 +08:00
|
|
|
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
2026-07-26 18:29:36 +08:00
|
|
|
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2026-07-27 00:18:42 +08:00
|
|
|
"gorm.io/gorm"
|
2026-07-26 18:29:36 +08:00
|
|
|
)
|
|
|
|
|
|
2026-07-27 00:18:42 +08:00
|
|
|
// UpdateRecordStatus 更新主表状态,停用和归档均保留历史记录。
|
|
|
|
|
func UpdateRecordStatus(ctx *gin.Context, model any) {
|
|
|
|
|
var request struct {
|
|
|
|
|
Status string `json:"status" binding:"required,max=32"`
|
|
|
|
|
}
|
|
|
|
|
if err := ctx.ShouldBindJSON(&request); err != nil {
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-07-27 01:32:44 +08:00
|
|
|
updateAllowedByIdentity(ctx, model, gin.H{"status": request.Status}, []string{"status"})
|
2026-07-26 18:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-27 00:18:42 +08:00
|
|
|
// ArchiveRecord 通过 archived 状态实现逻辑删除,不物理删除主数据。
|
|
|
|
|
func ArchiveRecord(ctx *gin.Context, model any) {
|
2026-07-27 01:32:44 +08:00
|
|
|
updateAllowedByIdentity(ctx, model, archiveValues(), []string{"status"})
|
2026-07-26 18:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-27 00:18:42 +08:00
|
|
|
func newEntity(status string) models.Entity {
|
|
|
|
|
return models.Entity{Identity: models.NewIdentity(), Status: status, Version: 1}
|
2026-07-26 18:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-27 00:18:42 +08:00
|
|
|
func listPage[T any](ctx *gin.Context) {
|
2026-07-26 18:29:36 +08:00
|
|
|
page, size := pageSize(ctx)
|
2026-07-27 00:18:42 +08:00
|
|
|
var list []T
|
|
|
|
|
var total int64
|
|
|
|
|
databaseQuery := impl.DBService.Model(new(T))
|
|
|
|
|
if err := databaseQuery.Count(&total).Error; err != nil {
|
|
|
|
|
infra.Response.Error(ctx, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
2026-07-26 18:29:36 +08:00
|
|
|
infra.Response.Error(ctx, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-07-27 10:25:04 +08:00
|
|
|
infra.Response.Success(ctx, gin.H{"total": total, "list": publicResourceResponse(list)})
|
2026-07-27 00:18:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getByIdentity[T any](ctx *gin.Context) {
|
|
|
|
|
var data T
|
|
|
|
|
if err := impl.DBService.Where("identity = ?", ctx.Param("identity")).First(&data).Error; err != nil {
|
|
|
|
|
respondRecordError(ctx, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-07-27 10:25:04 +08:00
|
|
|
infra.Response.Success(ctx, publicResourceResponse(data))
|
2026-07-27 00:18:42 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-27 01:32:44 +08:00
|
|
|
func updateAllowedByIdentity(ctx *gin.Context, model any, values map[string]any, allowedFields []string) {
|
|
|
|
|
values = filterFields(values, allowedFields)
|
|
|
|
|
if len(values) == 0 {
|
|
|
|
|
infra.Response.Success(ctx, gin.H{"updated": false})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result := impl.DBService.Model(model).Where("identity = ?", ctx.Param("identity")).Updates(values)
|
|
|
|
|
if result.Error != nil {
|
|
|
|
|
infra.Response.Error(ctx, result.Error)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if result.RowsAffected == 0 {
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
infra.Response.Success(ctx, gin.H{"updated": true})
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-27 00:18:42 +08:00
|
|
|
func updateByIdentity(ctx *gin.Context, model any, values map[string]any) {
|
|
|
|
|
result := impl.DBService.Model(model).Where("identity = ?", ctx.Param("identity")).Updates(values)
|
|
|
|
|
if result.Error != nil {
|
|
|
|
|
infra.Response.Error(ctx, result.Error)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if result.RowsAffected == 0 {
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
infra.Response.Success(ctx, gin.H{"updated": true})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func respondRecordError(ctx *gin.Context, err error) {
|
|
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
infra.Response.Error(ctx, err)
|
2026-07-26 18:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func pageSize(ctx *gin.Context) (int, int) {
|
|
|
|
|
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
|
|
|
|
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
|
|
|
|
if page < 1 {
|
|
|
|
|
page = 1
|
|
|
|
|
}
|
|
|
|
|
if size < 1 || size > 100 {
|
|
|
|
|
size = 20
|
|
|
|
|
}
|
|
|
|
|
return page, size
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func maskPhone(phone string) string {
|
|
|
|
|
if len(phone) < 7 {
|
|
|
|
|
return "***"
|
|
|
|
|
}
|
|
|
|
|
return phone[:3] + "****" + phone[len(phone)-4:]
|
|
|
|
|
}
|