You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.7 KiB
125 lines
3.7 KiB
package console
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"yunyan/comm"
|
|
"yunyan/lego/sys/postgres"
|
|
"yunyan/pb"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// ============================ 应用/产品域 (product) ============================
|
|
//
|
|
// 应用(产品) = SaaS 里的一个应用名(Voitrans/Lumi/…),下挂多条区域部署(app_registry,按应用名 app_name 关联)。
|
|
// 「应用管理」列表按应用名分组:一行一个应用,展开看它在各区域/环境的部署。
|
|
|
|
func (this *serverComp) productsList(c *gin.Context) {
|
|
models, err := this.module.model.listProducts()
|
|
if err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
writeOK(c, models)
|
|
}
|
|
|
|
func (this *serverComp) productsAdd(c *gin.Context) {
|
|
var model AppProduct
|
|
if err := c.ShouldBindJSON(&model); err != nil {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, err.Error())
|
|
return
|
|
}
|
|
model.Name = strings.TrimSpace(model.Name)
|
|
if model.Name == "" {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "应用名必填")
|
|
return
|
|
}
|
|
if exist, _ := this.module.model.getProductByName(model.Name); exist != nil && exist.Id != 0 {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "应用名已存在: "+model.Name)
|
|
return
|
|
}
|
|
model.Id = 0
|
|
now := time.Now().Unix()
|
|
model.Createtime = now
|
|
model.Updatetime = now
|
|
if err := this.module.model.addProduct(&model); err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
writeOK(c, &model)
|
|
}
|
|
|
|
func (this *serverComp) productsUpdate(c *gin.Context) {
|
|
var model AppProduct
|
|
if err := c.ShouldBindJSON(&model); err != nil {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, err.Error())
|
|
return
|
|
}
|
|
if model.Id == 0 {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "id 必填")
|
|
return
|
|
}
|
|
model.Name = strings.TrimSpace(model.Name)
|
|
if model.Name == "" {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "应用名必填")
|
|
return
|
|
}
|
|
// 判重:同名但非本行则拒绝。
|
|
if exist, _ := this.module.model.getProductByName(model.Name); exist != nil && exist.Id != 0 && exist.Id != model.Id {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "应用名已存在: "+model.Name)
|
|
return
|
|
}
|
|
old, err := this.module.model.getProduct(model.Id)
|
|
if err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, "应用不存在: "+err.Error())
|
|
return
|
|
}
|
|
model.Createtime = old.Createtime
|
|
model.Updatetime = time.Now().Unix()
|
|
if err := this.module.model.saveProduct(&model); err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
// 应用名即关联键:改名时级联把其名下部署的 app_name 一并更新,避免部署掉进「未分组」。
|
|
if old.Name != model.Name {
|
|
if res := postgres.Exec("UPDATE "+comm.TableAppRegistry+" SET app_name=? WHERE app_name=?", model.Name, old.Name); res.Error != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, "级联更新部署归属失败: "+res.Error.Error())
|
|
return
|
|
}
|
|
}
|
|
writeOK(c, &model)
|
|
}
|
|
|
|
func (this *serverComp) productsDel(c *gin.Context) {
|
|
var req struct {
|
|
Id uint32 `json:"id"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil || req.Id == 0 {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "id 必填")
|
|
return
|
|
}
|
|
// 引用完整性:应用下仍有区域部署(按应用名匹配)则拒删。
|
|
p, err := this.module.model.getProduct(req.Id)
|
|
if err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, "应用不存在: "+err.Error())
|
|
return
|
|
}
|
|
apps, err := this.module.model.listApps()
|
|
if err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
for _, a := range apps {
|
|
if a.AppName == p.Name {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "该应用下仍有区域部署,请先删除其部署")
|
|
return
|
|
}
|
|
}
|
|
if err := this.module.model.delProduct(req.Id); err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"id": req.Id})
|
|
}
|
|
|