package admin import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/gothinkster/golang-gin-realworld-example-app/common" "github.com/gothinkster/golang-gin-realworld-example-app/models" ) func ListAssets(c *gin.Context) { db := common.GetDB() p := ParsePagination(c) query := db.Model(&models.Asset{}) if v := c.Query("name"); v != "" { query = query.Where("name LIKE ?", "%"+v+"%") } if v := c.Query("asset_code"); v != "" { query = query.Where("asset_code LIKE ?", "%"+v+"%") } if v := c.Query("category"); v != "" { query = query.Where("category = ?", v) } if v := c.Query("is_active"); v != "" { query = query.Where("is_active = ?", v == "true") } var total int64 query.Count(&total) var items []models.Asset if err := query.Order("id DESC").Offset(p.Offset()).Limit(p.PageSize).Find(&items).Error; err != nil { Fail(c, http.StatusInternalServerError, "Failed to fetch assets") return } OKList(c, items, total) } func GetAsset(c *gin.Context) { db := common.GetDB() var item models.Asset if err := db.First(&item, c.Param("id")).Error; err != nil { Fail(c, http.StatusNotFound, "Asset not found") return } OK(c, item) } func CreateAsset(c *gin.Context) { db := common.GetDB() var item models.Asset if err := BindJSONFlexTime(c, &item); err != nil { Fail(c, http.StatusBadRequest, err.Error()) return } item.ID = 0 // 合约地址唯一性校验(非空才校验) if item.ContractAddress != "" { var conflict models.Asset if err := db.Where("contract_address = ?", item.ContractAddress).First(&conflict).Error; err == nil { Fail(c, http.StatusConflict, "合约地址已被资产「"+conflict.Name+"」使用,请检查后重试") return } } now := time.Now() if item.CreatedAt.IsZero() { item.CreatedAt = now } item.UpdatedAt = now if err := db.Create(&item).Error; err != nil { Fail(c, http.StatusInternalServerError, err.Error()) return } LogOp(c, "create", "asset", "create_asset", &item.ID, item) OK(c, item) } func UpdateAsset(c *gin.Context) { db := common.GetDB() var existing models.Asset if err := db.First(&existing, c.Param("id")).Error; err != nil { Fail(c, http.StatusNotFound, "Asset not found") return } var item models.Asset if err := BindJSONFlexTime(c, &item); err != nil { Fail(c, http.StatusBadRequest, err.Error()) return } item.ID = existing.ID // 合约地址唯一性校验(非空且与原值不同时校验) if item.ContractAddress != "" && item.ContractAddress != existing.ContractAddress { var conflict models.Asset if err := db.Where("contract_address = ? AND id != ?", item.ContractAddress, existing.ID).First(&conflict).Error; err == nil { Fail(c, http.StatusConflict, "合约地址已被资产「"+conflict.Name+"」使用,请检查后重试") return } } if existing.CreatedAt.IsZero() { item.CreatedAt = time.Now() } else { item.CreatedAt = existing.CreatedAt } if err := db.Save(&item).Error; err != nil { Fail(c, http.StatusInternalServerError, err.Error()) return } LogOp(c, "update", "asset", "update_asset", &item.ID, item) OK(c, item) } func DeleteAsset(c *gin.Context) { db := common.GetDB() var item models.Asset if err := db.First(&item, c.Param("id")).Error; err != nil { Fail(c, http.StatusNotFound, "Asset not found") return } if err := db.Delete(&item).Error; err != nil { Fail(c, http.StatusInternalServerError, err.Error()) return } LogOp(c, "delete", "asset", "delete_asset", &item.ID, nil) OK(c, gin.H{"message": "deleted"}) }