From 735534c6e681fe8335b272c486353cba47c11775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E5=BC=BA?= <357099073@qq.com> Date: Thu, 20 Aug 2026 16:49:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/pkg/tagengine/meta.go | 36 +++++++++ go/pkg/tagengine/provider.go | 143 +++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) diff --git a/go/pkg/tagengine/meta.go b/go/pkg/tagengine/meta.go index 1e000fd..340a684 100644 --- a/go/pkg/tagengine/meta.go +++ b/go/pkg/tagengine/meta.go @@ -115,6 +115,42 @@ func TagDocs() []TagMeta { Fields: []string{"id 文章ID", "title 标题(受 titlelen 影响)", "titlefull 完整标题", "desc 摘要", "image 缩略图", "arcurl 详情页链接(/news/ID)", "pubdate 发布日期", "views 阅读量", "author 作者"}, Example: "{yz:newscenter row=\"8\" titlelen=\"28\"}\n
\n \n \"[field:titlefull/]\"\n

[field:title/]

\n

[field:desc/]

\n [field:pubdate/]\n
\n
\n{/yz:newscenter}", }, + { + Name: "productlist 产品列表", + Category: "loop", + Syntax: "{yz:productlist row=\"8\" titlelen=\"20\"}...{/yz:productlist}", + Desc: "循环输出当前租户启用中的产品(backend 端 - 内容管理 - 产品管理),按 sort 升序。数据来自 yz_cms_product 表。", + Params: []string{"row 输出条数,默认 10,最大 50", "titlelen 标题截断字数,不填为完整标题"}, + Fields: []string{"id 产品ID", "title 标题(受 titlelen 影响)", "titlefull 完整标题", "desc 产品简介", "thumb 产品图片地址", "content 富文本详情(HTML,用 div 承接)", "url 跳转地址(产品管理中填写的链接,未填为空)"}, + Example: "{yz:productlist row=\"8\" titlelen=\"16\"}\n
\n \n \"[field:titlefull/]\"\n

[field:title/]

\n

[field:desc/]

\n
\n
\n{/yz:productlist}", + }, + { + Name: "producttype 产品分类", + Category: "loop", + Syntax: "{yz:producttype row=\"10\"}...{/yz:producttype}", + Desc: "循环输出当前租户启用中的产品分类(backend 端 - 内容管理 - 产品分类),按 sort 升序。数据来自 yz_cms_product_category 表,常用于产品页的分类 Tab/筛选栏。", + Params: []string{"row 输出条数,默认 20,最大 50"}, + Fields: []string{"id 分类ID", "name 分类名称", "desc 分类描述", "pid 父分类ID(0 为顶级)", "url 锚点链接(#product-type-ID,可自定义)"}, + Example: "{yz:producttype}\n
  • [field:name/]
  • \n{/yz:producttype}", + }, + { + Name: "solutionlist 解决方案列表", + Category: "loop", + Syntax: "{yz:solutionlist row=\"6\" titlelen=\"20\"}...{/yz:solutionlist}", + Desc: "循环输出当前租户启用中的解决方案(backend 端 - 内容管理 - 解决方案管理),按 sort 升序。数据来自 yz_cms_solution 表。", + Params: []string{"row 输出条数,默认 10,最大 50", "titlelen 标题截断字数,不填为完整标题"}, + Fields: []string{"id 方案ID", "title 标题(受 titlelen 影响)", "titlefull 完整标题", "desc 方案简介", "thumb 图片地址", "url 跳转地址(解决方案管理中填写的链接,未填为空)"}, + Example: "{yz:solutionlist row=\"6\"}\n
    \n \n \"[field:titlefull/]\"\n

    [field:title/]

    \n

    [field:desc/]

    \n
    \n
    \n{/yz:solutionlist}", + }, + { + Name: "solutiontype 解决方案分类", + Category: "loop", + Syntax: "{yz:solutiontype row=\"10\"}...{/yz:solutiontype}", + Desc: "循环输出当前租户启用中的解决方案分类(backend 端 - 内容管理 - 解决方案分类),按 sort 升序。数据来自 yz_cms_solution_category 表。", + Params: []string{"row 输出条数,默认 20,最大 50"}, + Fields: []string{"id 分类ID", "name 分类名称", "desc 分类描述", "pid 父分类ID(0 为顶级)", "url 锚点链接(#solution-type-ID,可自定义)"}, + Example: "{yz:solutiontype}\n
  • [field:name/]
  • \n{/yz:solutiontype}", + }, { Name: "arcview 文章详情", Category: "single", diff --git a/go/pkg/tagengine/provider.go b/go/pkg/tagengine/provider.go index 745df72..6d31229 100644 --- a/go/pkg/tagengine/provider.go +++ b/go/pkg/tagengine/provider.go @@ -24,6 +24,10 @@ func init() { RegisterBlock("arclist", arclistProvider) RegisterBlock("arcview", arcviewProvider) RegisterBlock("friendlink", friendlinkProvider) + RegisterBlock("productlist", productlistProvider) + RegisterBlock("producttype", producttypeProvider) + RegisterBlock("solutionlist", solutionlistProvider) + RegisterBlock("solutiontype", solutiontypeProvider) RegisterBodyBlock("newscenter", newscenterHandler) RegisterSelfClose("onepage", onepageHandler) RegisterSelfClose("pagelist", pagelistHandler) @@ -246,6 +250,145 @@ func friendlinkProvider(tid uint64, params map[string]string, ctx *RenderCtx) ([ return out, nil } +// productlistProvider 产品列表循环,支持 row/titlelen 参数 +func productlistProvider(tid uint64, params map[string]string, ctx *RenderCtx) ([]map[string]string, error) { + _ = models.EnsureCmsProductTables() + row := atoiDefault(params["row"], 10) + if row <= 0 || row > 50 { + row = 10 + } + titleLen := atoiDefault(params["titlelen"], 0) + + var rows []models.CmsProduct + _, err := models.Orm.QueryTable(new(models.CmsProduct)). + Filter("tid", tid). + Filter("status", 1). + Filter("delete_time__isnull", true). + OrderBy("sort", "id"). + Limit(row). + All(&rows) + if err != nil && err != orm.ErrNoRows { + return nil, err + } + out := make([]map[string]string, 0, len(rows)) + for _, p := range rows { + title := p.Title + if titleLen > 0 { + title = truncateTitle(title, titleLen) + } + out = append(out, map[string]string{ + "id": strconv.FormatUint(p.ID, 10), + "title": title, + "titlefull": p.Title, + "desc": p.Desc, + "thumb": p.Thumb, + "content": p.Content, + "url": p.URL, + }) + } + return out, nil +} + +// producttypeProvider 产品分类循环,支持 row 参数 +func producttypeProvider(tid uint64, params map[string]string, ctx *RenderCtx) ([]map[string]string, error) { + _ = models.EnsureCmsProductTables() + row := atoiDefault(params["row"], 20) + if row <= 0 || row > 50 { + row = 20 + } + var rows []models.CmsProductCategory + _, err := models.Orm.QueryTable(new(models.CmsProductCategory)). + Filter("tid", tid). + Filter("status", 1). + Filter("delete_time__isnull", true). + OrderBy("sort", "id"). + Limit(row). + All(&rows) + if err != nil && err != orm.ErrNoRows { + return nil, err + } + out := make([]map[string]string, 0, len(rows)) + for _, c := range rows { + out = append(out, map[string]string{ + "id": strconv.FormatUint(c.ID, 10), + "name": c.Title, + "desc": c.Desc, + "pid": strconv.FormatUint(c.Pid, 10), + "url": "#product-type-" + strconv.FormatUint(c.ID, 10), + }) + } + return out, nil +} + +// solutionlistProvider 解决方案列表循环,支持 row/titlelen 参数 +func solutionlistProvider(tid uint64, params map[string]string, ctx *RenderCtx) ([]map[string]string, error) { + _ = models.EnsureCmsSolutionTables() + row := atoiDefault(params["row"], 10) + if row <= 0 || row > 50 { + row = 10 + } + titleLen := atoiDefault(params["titlelen"], 0) + + var rows []models.CmsSolution + _, err := models.Orm.QueryTable(new(models.CmsSolution)). + Filter("tid", tid). + Filter("status", 1). + Filter("delete_time__isnull", true). + OrderBy("sort", "id"). + Limit(row). + All(&rows) + if err != nil && err != orm.ErrNoRows { + return nil, err + } + out := make([]map[string]string, 0, len(rows)) + for _, s := range rows { + title := s.Title + if titleLen > 0 { + title = truncateTitle(title, titleLen) + } + out = append(out, map[string]string{ + "id": strconv.FormatUint(s.ID, 10), + "title": title, + "titlefull": s.Title, + "desc": s.Desc, + "thumb": s.Thumb, + "url": s.URL, + }) + } + return out, nil +} + +// solutiontypeProvider 解决方案分类循环,支持 row 参数 +func solutiontypeProvider(tid uint64, params map[string]string, ctx *RenderCtx) ([]map[string]string, error) { + _ = models.EnsureCmsSolutionTables() + row := atoiDefault(params["row"], 20) + if row <= 0 || row > 50 { + row = 20 + } + var rows []models.CmsSolutionCategory + _, err := models.Orm.QueryTable(new(models.CmsSolutionCategory)). + Filter("tid", tid). + Filter("status", 1). + Filter("delete_time__isnull", true). + OrderBy("sort", "id"). + Limit(row). + All(&rows) + if err != nil && err != orm.ErrNoRows { + return nil, err + } + out := make([]map[string]string, 0, len(rows)) + for _, c := range rows { + out = append(out, map[string]string{ + "id": strconv.FormatUint(c.ID, 10), + "name": c.Title, + "desc": c.Desc, + "pid": strconv.FormatUint(c.Pid, 10), + "url": "#solution-type-" + strconv.FormatUint(c.ID, 10), + }) + } + return out, nil +} + // arclistProvider 文章列表循环,支持 row/cateid/titlelen/flag 参数 func arclistProvider(tid uint64, params map[string]string, ctx *RenderCtx) ([]map[string]string, error) { row := atoiDefault(params["row"], 10)