增加自定义绑定域名

This commit is contained in:
2026-09-02 15:11:32 +08:00
parent db519d9af2
commit f644c278c9
23 changed files with 2966 additions and 212 deletions
+104 -12
View File
@@ -323,20 +323,31 @@ func (c *PlatformTenantDomainController) Index() {
tid, _ := c.GetUint64("tid")
statusStr := strings.TrimSpace(c.GetString("status"))
subDomain := strings.TrimSpace(c.GetString("sub_domain"))
keyword := strings.TrimSpace(c.GetString("sub_domain"))
domainTypeStr := strings.TrimSpace(c.GetString("domain_type"))
qs := models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("delete_time__isnull", true)
// 条件一次性拼好:SetCond 会覆盖 Filter 累积的条件,不能混用
cond := orm.NewCondition().And("delete_time__isnull", true)
if tid > 0 {
qs = qs.Filter("tid", tid)
cond = cond.And("tid", tid)
}
if statusStr != "" {
if st, err := strconv.Atoi(statusStr); err == nil {
qs = qs.Filter("status", st)
cond = cond.And("status", st)
}
}
if subDomain != "" {
qs = qs.Filter("sub_domain__icontains", subDomain)
if domainTypeStr != "" {
if dt, err := strconv.Atoi(domainTypeStr); err == nil {
cond = cond.And("domain_type", dt)
}
}
// 关键字同时匹配二级前缀与完整域名:自有域名没有 sub_domain,只能靠 full_domain 命中
if keyword != "" {
cond = cond.AndCond(orm.NewCondition().
Or("sub_domain__icontains", keyword).
Or("full_domain__icontains", keyword))
}
qs := models.Orm.QueryTable(new(models.SystemTenantDomain)).SetCond(cond)
total, err := qs.Count()
if err != nil {
@@ -349,8 +360,7 @@ func (c *PlatformTenantDomainController) Index() {
jsonErr(&c.Controller, 500, 500, "获取租户域名失败: "+err.Error())
return
}
list := make([]models.SystemTenantDomain, 0, len(rows))
list = append(list, rows...)
list := tenantDomainList(rows)
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
@@ -360,6 +370,7 @@ func (c *PlatformTenantDomainController) Index() {
}
// MyDomains GET /platform/domain/tenant/myDomains?tid=1
// 平台端账号不归属租户,tid 必须显式传入(运营代租户查看)。
func (c *PlatformTenantDomainController) MyDomains() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
@@ -380,7 +391,73 @@ func (c *PlatformTenantDomainController) MyDomains() {
jsonErr(&c.Controller, 500, 500, "获取失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": rows}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": tenantDomainList(rows)}
_ = c.ServeJSON()
}
// BindCustom POST /platform/domain/tenant/bindCustom body:{tid,domain}
// 平台端代租户绑定自有域名,tid 必传。
func (c *PlatformTenantDomainController) BindCustom() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p customDomainPayload
if err := json.Unmarshal(raw, &p); err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
id, status, errMsg := bindCustomDomain(p.Tid, p.Domain)
if errMsg != "" {
jsonErr(&c.Controller, status, status, errMsg)
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "绑定成功,请按提示配置解析后点击「检测解析」",
"data": map[string]interface{}{"id": id},
}
_ = c.ServeJSON()
}
// CheckCustomDns POST /platform/domain/tenant/checkCustomDns body:{id}
// 平台端不限制域名归属,可为任意租户触发检测与签发。
func (c *PlatformTenantDomainController) CheckCustomDns() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p domainIDPayload
if err := json.Unmarshal(raw, &p); err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
data, status, errMsg := checkCustomDomainDNS(p.ID, 0)
if errMsg != "" {
jsonErr(&c.Controller, status, status, errMsg)
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": data}
_ = c.ServeJSON()
}
// CustomDomainGuide GET /platform/domain/tenant/customDomainGuide
func (c *PlatformTenantDomainController) CustomDomainGuide() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": customDomainGuideData()}
_ = c.ServeJSON()
}
@@ -423,13 +500,14 @@ func (c *PlatformTenantDomainController) Apply() {
return
}
// 该租户是否已有域名
// 该租户是否已申请过平台二级域名(自有域名单独计数,两者可以共存)
cnt, _ := models.Orm.QueryTable(new(models.SystemTenantDomain)).
Filter("tid", p.Tid).
Filter("domain_type", models.DomainTypePlatformSub).
Filter("delete_time__isnull", true).
Count()
if cnt > 0 {
jsonErr(&c.Controller, 400, 400, "该租户已有域名,请删除后再次申请")
jsonErr(&c.Controller, 400, 400, "该租户已有二级域名,请删除后再次申请")
return
}
@@ -460,6 +538,7 @@ func (c *PlatformTenantDomainController) Apply() {
tid := p.Tid
row := &models.SystemTenantDomain{
Tid: &tid,
DomainType: models.DomainTypePlatformSub,
SubDomain: &sub,
MainDomain: &main,
FullDomain: &full,
@@ -500,6 +579,10 @@ func (c *PlatformTenantDomainController) Audit() {
jsonErr(&c.Controller, 404, 404, "域名不存在")
return
}
if row.DomainType == models.DomainTypeCustom {
jsonErr(&c.Controller, 400, 400, "自有域名无需人工审核,解析检测与证书签发通过后自动生效")
return
}
if row.Status != 0 {
jsonErr(&c.Controller, 400, 400, "该域名已审核过了")
return
@@ -547,11 +630,20 @@ func (c *PlatformTenantDomainController) ToggleStatus() {
return
}
if row.Status == 0 {
jsonErr(&c.Controller, 400, 400, "审核中不可操作")
if row.DomainType == models.DomainTypeCustom {
jsonErr(&c.Controller, 400, 400, "该域名尚未生效(解析或证书未就绪),无需禁用")
} else {
jsonErr(&c.Controller, 400, 400, "审核中不可操作")
}
return
}
newStatus := 2
if row.Status == 2 {
// 自有域名重新启用要求证书还在,否则启用后访问会报证书错误
if row.DomainType == models.DomainTypeCustom && row.SSLStatus != models.SSLStatusIssued {
jsonErr(&c.Controller, 400, 400, "该域名的 HTTPS 证书未就绪,请先检测解析并等待证书签发")
return
}
newStatus = 1
}
now := time.Now()