Files
yunzerwebsiteallinone/go/controllers/index_portal.go
T
2026-07-21 14:04:49 +08:00

465 lines
11 KiB
Go

package controllers
import (
"fmt"
"net/url"
"strconv"
"strings"
"server/models"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
)
// IndexPortalController 前台门户及租户官网公共接口(无需登录)
type IndexPortalController struct {
beego.Controller
}
// getTidByHost 根据访问域名识别租户 ID,默认返回 1
func (c *IndexPortalController) getTidByHost() uint64 {
host := c.Ctx.Request.Host
parts := strings.Split(host, ":")
domain := parts[0]
if domain == "localhost" || domain == "127.0.0.1" {
return 1 // 开发环境默认租户
}
var td models.SystemTenantDomain
err := models.Orm.QueryTable(new(models.SystemTenantDomain)).
Filter("full_domain", domain).
Filter("status", 1).
Filter("delete_time__isnull", true).
One(&td)
if err == nil && td.Tid != nil {
return *td.Tid
}
return 1 // 默认租户
}
// 获取后端菜单数据(支持开发环境租户切换)
func (c *IndexPortalController) GetHeadMenu() {
// DEV 环境下支持通过 X-Tenant-ID 切换租户
runmode, _ := beego.AppConfig.String("runmode")
tenantName := c.Ctx.Request.Header.Get("X-Tenant-ID")
// 解码
if decoded, err := url.QueryUnescape(tenantName); err == nil {
tenantName = decoded
}
// 强制打印,确保你能从终端看到真实值
fmt.Printf("[DEBUG] runmode: %s, Decoded TenantName: %s\n", runmode, tenantName)
if runmode == "dev" && tenantName != "" {
// 查找租户 ID - 支持 name 或 short_name
var tenant models.SystemTenant
// 使用 OR 逻辑查询 name 或 short_name
cond := orm.NewCondition()
cond = cond.Or("tenant_name", tenantName).Or("tenant_short_name", tenantName)
err := models.Orm.QueryTable(new(models.SystemTenant)).
SetCond(cond).
One(&tenant)
if err != nil {
fmt.Printf("[DEBUG] QueryTenant Error: %v, Looking for: %s\n", err, tenantName)
} else {
fmt.Printf("[DEBUG] Found Tenant ID: %d\n", tenant.ID)
// 查询该租户的自定义菜单
var menus []models.BackendMenuFront
_, err = models.Orm.QueryTable("yz_backend_menu_front").
Filter("tenant_id", tenant.ID).
Filter("delete_time__isnull", true).
OrderBy("sort").
All(&menus)
if err == nil && len(menus) > 0 {
// 转换数据格式供前端使用
menuData := buildFrontMenuTree(menus, 0)
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": menuData}
_ = c.ServeJSON()
return
} else {
fmt.Printf("[DEBUG] No menus found for tenant: %d\n", tenant.ID)
}
}
}
// 前台的静态导航菜单结构
menuData := []map[string]interface{}{
{
"id": 1,
"title": "首页",
"path": "/",
"type": 2,
},
{
"id": 2,
"title": "解决方案",
"path": "/solutions",
"type": 2,
"children": []map[string]interface{}{
{
"id": 21,
"title": "行业解决方案",
"path": "/solutions/solution",
"type": 2,
},
{
"id": 22,
"title": "成功案例",
"path": "/solutions/successCases",
"type": 2,
},
},
},
{
"id": 3,
"title": "新闻中心",
"path": "/newsCenter",
"type": 2,
"children": []map[string]interface{}{
{
"id": 31,
"title": "站点新闻",
"path": "/newsCenter/news",
"type": 2,
},
{
"id": 32,
"title": "站点公告",
"path": "/newsCenter/announcement",
"type": 2,
},
{
"id": 33,
"title": "技术中心",
"path": "/newsCenter/technologyCenter",
"type": 2,
},
},
},
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": menuData,
}
_ = c.ServeJSON()
}
// 辅助构建树结构
func buildFrontMenuTree(menus []models.BackendMenuFront, pid int64) []map[string]interface{} {
var tree []map[string]interface{}
for _, m := range menus {
if int64(m.Pid) == pid {
node := map[string]interface{}{
"id": m.ID,
"title": m.Title,
"path": m.Path,
"type": m.Type,
}
children := buildFrontMenuTree(menus, int64(m.ID))
if len(children) > 0 {
node["children"] = children
}
tree = append(tree, node)
}
}
return tree
}
// GetFooterData GET /index/footerdata
func (c *IndexPortalController) GetFooterData() {
tid := c.getTidByHost()
// 准备默认的 Footer 配置数据
footerMap := map[string]string{
"sitename": "云泽官方网站",
"companyname": "云泽智能科技有限公司",
"copyright": "Copyright © 2026 Yunzer. All Rights Reserved.",
"icp": "苏ICP备2026000000号-1",
"description": "专业为企业建设数字化管理与官网门户的一站式 SaaS 服务平台",
"logo": "",
"logow": "",
"ico": "",
}
// 尝试从租户站点设置表中查询最新的配置
var rows []models.TenantSiteSetting
_, err := models.Orm.QueryTable(new(models.TenantSiteSetting)).
Filter("tid", tid).
Filter("delete_time__isnull", true).
Limit(1).
All(&rows)
if err == nil && len(rows) > 0 {
r := rows[0]
if r.Sitename != "" {
footerMap["sitename"] = r.Sitename
}
if r.Companyname != "" {
footerMap["companyname"] = r.Companyname
}
if r.Copyright != "" {
footerMap["copyright"] = r.Copyright
}
if r.Icp != "" {
footerMap["icp"] = r.Icp
}
if r.Description != "" {
footerMap["description"] = r.Description
}
footerMap["logo"] = r.Logo
footerMap["logow"] = r.Logow
footerMap["ico"] = r.Ico
}
// 将 Map 转换为前端需要的 [{label: "...", value: "..."}] 数组格式
var dataList []map[string]string
for k, v := range footerMap {
dataList = append(dataList, map[string]string{
"label": k,
"value": v,
})
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": dataList,
}
_ = c.ServeJSON()
}
// GetNewsCenterTop4 GET /index/newscentertop4
func (c *IndexPortalController) GetNewsCenterTop4() {
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
var articles []models.CmsArticle
_, err := models.Orm.QueryTable(new(models.CmsArticle)).
Filter("tid", tid).
Filter("status", 1).
Filter("delete_time__isnull", true).
OrderBy("-top", "-recommend", "-id").
Limit(4).
All(&articles)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 200, "data": []interface{}{}}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": articles,
}
_ = c.ServeJSON()
}
// queryCmsArticles 统一的分页查询文章辅助方法
func (c *IndexPortalController) queryCmsArticles(categoryName string, categoryID int64) {
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
page, _ := c.GetInt("page", 1)
limit, _ := c.GetInt("limit", 10)
if page < 1 {
page = 1
}
if limit < 1 {
limit = 10
}
qs := models.Orm.QueryTable(new(models.CmsArticle)).
Filter("tid", tid).
Filter("status", 1).
Filter("delete_time__isnull", true)
// 如果有传具体的分类 ID
if categoryID > 0 {
qs = qs.Filter("cate_id", categoryID)
}
total, _ := qs.Count()
var articles []models.CmsArticle
_, err := qs.OrderBy("-top", "-id").
Limit(limit, (page-1)*limit).
All(&articles)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 200,
"data": map[string]interface{}{
"list": []interface{}{},
"total": 0,
},
}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{
"list": articles,
"total": total,
},
}
_ = c.ServeJSON()
}
// GetCompanyNews GET /index/companynews
func (c *IndexPortalController) GetCompanyNews() {
// 可根据实际需要分配固定的分类 ID
c.queryCmsArticles("companynews", 0)
}
// GetKingdeeNews GET /index/kingdeenews
func (c *IndexPortalController) GetKingdeeNews() {
c.queryCmsArticles("kingdeenews", 0)
}
// GetTechnologyCenter GET /index/technologyCenter
func (c *IndexPortalController) GetTechnologyCenter() {
categoryID, _ := c.GetInt64("category_id", 0)
c.queryCmsArticles("technologyCenter", categoryID)
}
// GetTechnologyCategories GET /index/technologyCategories
func (c *IndexPortalController) GetTechnologyCategories() {
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
var categories []models.CmsArticleCategory
_, err := models.Orm.QueryTable(new(models.CmsArticleCategory)).
Filter("tid", tid).
Filter("status", 1).
Filter("delete_time__isnull", true).
OrderBy("sort", "id").
All(&categories)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 200, "data": []interface{}{}}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": categories,
}
_ = c.ServeJSON()
}
// GetCompanyNewsDetail GET /index/companynews/detail/:id
func (c *IndexPortalController) GetCompanyNewsDetail() {
c.getArticleDetail()
}
// GetKingdeeNewsDetail GET /index/kingdeeNews/detail/:id
func (c *IndexPortalController) GetKingdeeNewsDetail() {
c.getArticleDetail()
}
// getArticleDetail 查询文章详情的内部辅助方法
func (c *IndexPortalController) getArticleDetail() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
var article models.CmsArticle
err := models.Orm.QueryTable(new(models.CmsArticle)).
Filter("id", id).
Filter("tid", tid).
Filter("delete_time__isnull", true).
One(&article)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 404, "msg": "文章不存在"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": article,
}
_ = c.ServeJSON()
}
// AddLike POST /index/articleLikes/:id
func (c *IndexPortalController) AddLike() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
_, _ = models.Orm.QueryTable(new(models.CmsArticle)).
Filter("id", id).
Filter("tid", tid).
Update(orm.Params{
"likes": orm.ColValue(orm.ColAdd, 1),
})
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "点赞成功"}
_ = c.ServeJSON()
}
// ReduceLike POST /index/articleUnlikes/:id
func (c *IndexPortalController) ReduceLike() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
_, _ = models.Orm.QueryTable(new(models.CmsArticle)).
Filter("id", id).
Filter("tid", tid).
Filter("likes__gt", 0).
Update(orm.Params{
"likes": orm.ColValue(orm.ColMinus, 1),
})
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "已取消点赞"}
_ = c.ServeJSON()
}
// AddViews POST /index/views/:id
func (c *IndexPortalController) AddViews() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
tid := c.getTidByHost()
_ = models.EnsureCmsArticleTables()
_, _ = models.Orm.QueryTable(new(models.CmsArticle)).
Filter("id", id).
Filter("tid", tid).
Update(orm.Params{
"views": orm.ColValue(orm.ColAdd, 1),
})
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "阅读量+1"}
_ = c.ServeJSON()
}
// GetOnePageByPath GET /index/onepage/:path
func (c *IndexPortalController) GetOnePageByPath() {
// 简单返回空数据,防止前端单页接口报错
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": nil,
}
_ = c.ServeJSON()
}