feat: 增加首页过滤和搜索
This commit is contained in:
@@ -41,6 +41,7 @@ dependencies {
|
|||||||
implementation("cn.bigmodel.openapi:oapi-java-sdk:release-V4-2.3.0")
|
implementation("cn.bigmodel.openapi:oapi-java-sdk:release-V4-2.3.0")
|
||||||
implementation("com.baidubce:qianfan:0.1.1")
|
implementation("com.baidubce:qianfan:0.1.1")
|
||||||
implementation("org.jsoup:jsoup:1.18.1")
|
implementation("org.jsoup:jsoup:1.18.1")
|
||||||
|
implementation("com.blinkfox:fenix-spring-boot-starter:3.0.0")
|
||||||
|
|
||||||
val hutoolVersion = "5.8.32"
|
val hutoolVersion = "5.8.32"
|
||||||
implementation("cn.hutool:hutool-core:$hutoolVersion")
|
implementation("cn.hutool:hutool-core:$hutoolVersion")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.lanyuanxiaoyao.digtal.market
|
package com.lanyuanxiaoyao.digtal.market
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.EnableFenix
|
||||||
import com.lanyuanxiaoyao.digtal.market.runner.NewsRunner
|
import com.lanyuanxiaoyao.digtal.market.runner.NewsRunner
|
||||||
import com.lanyuanxiaoyao.digtal.market.runner.PushRunner
|
import com.lanyuanxiaoyao.digtal.market.runner.PushRunner
|
||||||
import com.lanyuanxiaoyao.squirrel.core.common.Management
|
import com.lanyuanxiaoyao.squirrel.core.common.Management
|
||||||
@@ -20,7 +21,6 @@ import org.springframework.context.ApplicationListener
|
|||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import org.springframework.context.event.ContextClosedEvent
|
import org.springframework.context.event.ContextClosedEvent
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling
|
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry
|
import org.springframework.web.servlet.config.annotation.CorsRegistry
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||||
|
|
||||||
@@ -41,7 +41,8 @@ data class MailProperties @ConstructorBinding constructor(
|
|||||||
val targets: List<String>,
|
val targets: List<String>,
|
||||||
)
|
)
|
||||||
|
|
||||||
@EnableScheduling
|
// @EnableScheduling
|
||||||
|
@EnableFenix
|
||||||
@ConfigurationPropertiesScan
|
@ConfigurationPropertiesScan
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
class Application : ApplicationRunner, ApplicationListener<ContextClosedEvent> {
|
class Application : ApplicationRunner, ApplicationListener<ContextClosedEvent> {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.lanyuanxiaoyao.digtal.market
|
package com.lanyuanxiaoyao.digtal.market
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor
|
||||||
import jakarta.persistence.Column
|
import jakarta.persistence.Column
|
||||||
import jakarta.persistence.Entity
|
import jakarta.persistence.Entity
|
||||||
import jakarta.persistence.Id
|
import jakarta.persistence.Id
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor
|
|
||||||
import org.springframework.data.jpa.repository.Modifying
|
import org.springframework.data.jpa.repository.Modifying
|
||||||
import org.springframework.data.jpa.repository.Query
|
import org.springframework.data.jpa.repository.Query
|
||||||
import org.springframework.data.repository.query.Param
|
import org.springframework.data.repository.query.Param
|
||||||
@@ -30,12 +30,18 @@ class Article(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
interface ArticleRepository : JpaRepository<Article, String>, JpaSpecificationExecutor<Article> {
|
interface ArticleRepository : JpaRepository<Article, String>, FenixJpaSpecificationExecutor<Article> {
|
||||||
fun findAllByDescriptionIsNullAndTextIsNotNull(): List<Article>
|
fun findAllByDescriptionIsNullAndTextIsNotNull(): List<Article>
|
||||||
fun findAllByHtmlIsNotNull(): List<Article>
|
fun findAllByHtmlIsNotNull(): List<Article>
|
||||||
|
|
||||||
fun existsByCode(code: String): Boolean
|
fun existsByCode(code: String): Boolean
|
||||||
|
|
||||||
|
@Query("select distinct article.category from Article article where article.category is not null and article.category <> ''")
|
||||||
|
fun findAllCategory(): List<String>
|
||||||
|
|
||||||
|
@Query("select distinct article.author from Article article where article.author is not null and article.author <> ''")
|
||||||
|
fun findAllAuthor(): List<String>
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Transactional
|
@Transactional
|
||||||
@Query("update Article article set article.pushed = :pushed where article.id = :id")
|
@Query("update Article article set article.pushed = :pushed where article.id = :id")
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.lanyuanxiaoyao.digtal.market.controller
|
package com.lanyuanxiaoyao.digtal.market.controller
|
||||||
|
|
||||||
|
import cn.hutool.core.date.LocalDateTimeUtil
|
||||||
import com.lanyuanxiaoyao.digtal.market.ArticleRepository
|
import com.lanyuanxiaoyao.digtal.market.ArticleRepository
|
||||||
import com.lanyuanxiaoyao.digtal.market.sites
|
import com.lanyuanxiaoyao.digtal.market.sites
|
||||||
import com.lanyuanxiaoyao.squirrel.core.common.Site
|
import com.lanyuanxiaoyao.squirrel.core.common.Site
|
||||||
import jakarta.annotation.Resource
|
import jakarta.annotation.Resource
|
||||||
|
import jakarta.persistence.criteria.Predicate
|
||||||
|
import java.sql.Date
|
||||||
|
import java.time.Instant
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.data.domain.PageRequest
|
import org.springframework.data.domain.PageRequest
|
||||||
import org.springframework.data.domain.Sort
|
import org.springframework.data.domain.Sort
|
||||||
@@ -23,11 +27,66 @@ class OverviewController {
|
|||||||
@GetMapping("news")
|
@GetMapping("news")
|
||||||
fun news(
|
fun news(
|
||||||
@RequestParam("code", required = false) code: String?,
|
@RequestParam("code", required = false) code: String?,
|
||||||
|
@RequestParam("filter_keyword", required = false) filterKeyword: String?,
|
||||||
|
@RequestParam("filter_date", required = false) filterDate: Long?,
|
||||||
|
@RequestParam("filter_date_start", required = false) filterDateStart: Long?,
|
||||||
|
@RequestParam("filter_date_end", required = false) filterDateEnd: Long?,
|
||||||
|
@RequestParam("filter_source", required = false) filterSource: String?,
|
||||||
|
@RequestParam("filter_author", required = false) filterAuthor: String?,
|
||||||
|
@RequestParam("filter_category", required = false) filterCategory: String?,
|
||||||
@RequestParam("page", defaultValue = "1") page: Int,
|
@RequestParam("page", defaultValue = "1") page: Int,
|
||||||
@RequestParam("count", defaultValue = "10") count: Int,
|
@RequestParam("count", defaultValue = "10") count: Int,
|
||||||
): Map<String, Any> {
|
): Map<String, Any> {
|
||||||
val request = PageRequest.of(page - 1, count, Sort.by(Sort.Direction.DESC, "createTime"))
|
val pageRequest = PageRequest.of(page - 1, count, Sort.by(Sort.Direction.DESC, "createTime"))
|
||||||
val result = articleRepository.findAll(request)
|
val result = articleRepository.findAll({ root, _, builder ->
|
||||||
|
val predictions = mutableListOf<Predicate>()
|
||||||
|
filterKeyword?.let {
|
||||||
|
predictions.add(
|
||||||
|
builder.or(
|
||||||
|
builder.like(root.get("title"), "%${it}%"),
|
||||||
|
builder.like(root.get("subtitle"), "%${it}%"),
|
||||||
|
builder.like(root.get("text"), "%${it}%"),
|
||||||
|
builder.like(root.get("description"), "%${it}%"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (filterDate != null) {
|
||||||
|
val datetime = LocalDateTimeUtil.of(filterDate * 1000)
|
||||||
|
predictions.add(
|
||||||
|
builder.between(
|
||||||
|
root.get<Date>("createTime"),
|
||||||
|
Date.from(Instant.ofEpochMilli(LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.beginOfDay(datetime)))),
|
||||||
|
Date.from(Instant.ofEpochMilli(LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.endOfDay(datetime))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else if (filterDateStart != null && filterDateEnd != null) {
|
||||||
|
predictions.add(
|
||||||
|
builder.between(root.get<Date>("createTime"), Date.from(Instant.ofEpochSecond(filterDateStart)), Date.from(Instant.ofEpochSecond(filterDateEnd)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
filterSource?.let {
|
||||||
|
val site = sites.firstOrNull { site -> site.name == it }
|
||||||
|
if (site != null) {
|
||||||
|
predictions.add(
|
||||||
|
builder.equal(root.get<String>("code"), site.code)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterAuthor?.let {
|
||||||
|
predictions.add(
|
||||||
|
builder.equal(root.get<String>("author"), it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
filterCategory?.let {
|
||||||
|
predictions.add(
|
||||||
|
builder.equal(root.get<String>("category"), it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
builder.and(*predictions.toTypedArray())
|
||||||
|
}, pageRequest)
|
||||||
|
articleRepository.findAll({ builder ->
|
||||||
|
builder.build()
|
||||||
|
}, pageRequest)
|
||||||
return mapOf(
|
return mapOf(
|
||||||
"items" to result.content.map {
|
"items" to result.content.map {
|
||||||
val site = sites.find { site -> site.code == it.code }!!
|
val site = sites.find { site -> site.code == it.code }!!
|
||||||
@@ -49,4 +108,13 @@ class OverviewController {
|
|||||||
"total" to result.totalElements,
|
"total" to result.totalElements,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("all_source")
|
||||||
|
fun allSource() = sites.map { it.name }
|
||||||
|
|
||||||
|
@GetMapping("all_category")
|
||||||
|
fun allCategory() = articleRepository.findAllCategory()
|
||||||
|
|
||||||
|
@GetMapping("all_author")
|
||||||
|
fun allAuthor() = articleRepository.findAllAuthor()
|
||||||
}
|
}
|
||||||
@@ -43,4 +43,7 @@ messenger:
|
|||||||
binary-path: /Users/lanyuanxiaoyao/Downloads/chromium/128/macOS-1289987/Chromium.app/Contents/MacOS/Chromium
|
binary-path: /Users/lanyuanxiaoyao/Downloads/chromium/128/macOS-1289987/Chromium.app/Contents/MacOS/Chromium
|
||||||
database:
|
database:
|
||||||
h2-path: ./database/database.db
|
h2-path: ./database/database.db
|
||||||
json-path: ./database/database.json
|
json-path: ./database/database.json
|
||||||
|
fenix:
|
||||||
|
print-banner: false
|
||||||
|
print-sql: false
|
||||||
@@ -30,161 +30,264 @@ function overviewTab() {
|
|||||||
return {
|
return {
|
||||||
title: '总览',
|
title: '总览',
|
||||||
tab: {
|
tab: {
|
||||||
id: 'news_list',
|
type: 'crud',
|
||||||
columnClassName: 'px-2 pt-2',
|
syncLocation: false,
|
||||||
type: 'service',
|
|
||||||
api: {
|
api: {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '${base}/overview/news',
|
url: '${base}/overview/news',
|
||||||
data: {
|
data: {
|
||||||
page: '${page|default:1}',
|
page: '${page|default:1}',
|
||||||
count: '${count|default:10}',
|
count: '${count|default:10}',
|
||||||
|
filter_keyword: '${filter_keyword|default:undefined}',
|
||||||
|
filter_date: '${filter_date|default:undefined}',
|
||||||
|
filter_date_start: '${filter_date_start|default:undefined}',
|
||||||
|
filter_date_end: '${filter_date_end|default:undefined}',
|
||||||
|
filter_source: '${filter_source|default:undefined}',
|
||||||
|
filter_author: '${filter_author|default:undefined}',
|
||||||
|
filter_category: '${filter_category|default:undefined}',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
body: [
|
filterTogglable: true,
|
||||||
{
|
filterDefaultVisible: false,
|
||||||
type: 'action',
|
mode: 'list',
|
||||||
icon: 'fa fa-refresh',
|
headerToolbar: [
|
||||||
label: '刷新',
|
'reload',
|
||||||
className: 'mb-2',
|
'filter-toggler',
|
||||||
actionType: 'reload',
|
'pagination',
|
||||||
target: 'news_list',
|
],
|
||||||
|
footerToolbar: [],
|
||||||
|
filter: {
|
||||||
|
title: '搜索',
|
||||||
|
mode: 'horizontal',
|
||||||
|
horizontal: {
|
||||||
|
leftFixed: 'sm',
|
||||||
},
|
},
|
||||||
{
|
body: [
|
||||||
...pagination(),
|
{
|
||||||
className: 'float-right',
|
type: 'group',
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'list',
|
|
||||||
listItem: {
|
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
type: 'grid',
|
type: 'input-text',
|
||||||
columns: [
|
label: '关键字',
|
||||||
{
|
name: 'filter_keyword',
|
||||||
body: {
|
placeholder: '关键字搜索',
|
||||||
type: 'wrapper',
|
},
|
||||||
size: 'none',
|
]
|
||||||
className: 'py-2',
|
},
|
||||||
body: [
|
{
|
||||||
{
|
type: 'group',
|
||||||
type: 'wrapper',
|
body: [
|
||||||
className: 'text-md font-bold',
|
{
|
||||||
size: 'none',
|
type: 'input-date',
|
||||||
body: [
|
label: '日期',
|
||||||
'${title}'
|
name: 'filter_date',
|
||||||
]
|
columnRatio: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'wrapper',
|
type: 'input-date-range',
|
||||||
className: 'text-sm font-medium text-secondary',
|
label: '日期范围',
|
||||||
size: 'none',
|
name: 'filter_date_start',
|
||||||
body: [
|
extraName: 'filter_date_end',
|
||||||
'${subtitle}'
|
columnRatio: 8,
|
||||||
]
|
},
|
||||||
},
|
]
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
},
|
type: 'group',
|
||||||
{
|
body: [
|
||||||
sm: 2,
|
{
|
||||||
md: 2,
|
type: 'select',
|
||||||
lg: 2,
|
label: '来源',
|
||||||
columnClassName: 'content-center',
|
name: 'filter_source',
|
||||||
body: {
|
multiple: true,
|
||||||
type: 'operation',
|
searchable: true,
|
||||||
className: 'text-right',
|
source: {
|
||||||
buttons: [
|
method: 'get',
|
||||||
{
|
url: '${base}/overview/all_source',
|
||||||
visibleOn: '${!iframe}',
|
adaptor: (payload, response, api, context) => {
|
||||||
type: 'action',
|
console.log(payload, response, api, context)
|
||||||
label: '原文',
|
return payload.map(i => {
|
||||||
icon: 'fa fa-paperclip',
|
return {label: i, value: i}
|
||||||
actionType: 'url',
|
})
|
||||||
url: '${url}',
|
|
||||||
blank: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
visibleOn: '${iframe}',
|
|
||||||
type: 'action',
|
|
||||||
label: '原文',
|
|
||||||
icon: 'fa fa-firefox',
|
|
||||||
actionType: 'dialog',
|
|
||||||
dialog: {
|
|
||||||
title: '原文',
|
|
||||||
...readOnlyDialogOptions(),
|
|
||||||
size: 'xl',
|
|
||||||
body: {
|
|
||||||
type: 'iframe',
|
|
||||||
src: '${url}',
|
|
||||||
height: 1000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '搜索',
|
|
||||||
icon: 'fa fa-search',
|
|
||||||
actionType: 'url',
|
|
||||||
url: 'https://www.bing.com/search?q=${title}',
|
|
||||||
blank: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'tpl',
|
type: 'select',
|
||||||
className: 'text-current',
|
label: '作者',
|
||||||
tpl: '${description}',
|
name: 'filter_author',
|
||||||
|
multiple: true,
|
||||||
|
searchable: true,
|
||||||
|
source: {
|
||||||
|
method: 'get',
|
||||||
|
url: '${base}/overview/all_author',
|
||||||
|
adaptor: (payload, response, api, context) => {
|
||||||
|
console.log(payload, response, api, context)
|
||||||
|
return payload.map(i => {
|
||||||
|
return {label: i, value: i}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'tpl',
|
type: 'select',
|
||||||
className: 'text-blue-900 text-sm mt-2',
|
label: '关键词',
|
||||||
tpl: '${name}',
|
name: 'filter_category',
|
||||||
|
multiple: true,
|
||||||
|
searchable: true,
|
||||||
|
source: {
|
||||||
|
method: 'get',
|
||||||
|
url: '${base}/overview/all_category',
|
||||||
|
adaptor: (payload, response, api, context) => {
|
||||||
|
console.log(payload, response, api, context)
|
||||||
|
return payload.map(i => {
|
||||||
|
return {label: i, value: i}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: 'reset',
|
||||||
|
label: '清空'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'submit',
|
||||||
|
label: '搜索',
|
||||||
|
level: 'primary',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
canAccessSuperData: false,
|
||||||
|
listItem: {
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'grid',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
body: {
|
||||||
|
type: 'wrapper',
|
||||||
|
size: 'none',
|
||||||
|
className: 'py-2',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'wrapper',
|
||||||
|
className: 'text-md font-bold',
|
||||||
|
size: 'none',
|
||||||
|
body: [
|
||||||
|
'${title}'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'wrapper',
|
||||||
|
className: 'text-sm font-medium text-secondary',
|
||||||
|
size: 'none',
|
||||||
|
body: [
|
||||||
|
'${subtitle}'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'wrapper',
|
sm: 2,
|
||||||
size: 'none',
|
md: 2,
|
||||||
className: 'mt-2',
|
lg: 2,
|
||||||
body: [
|
columnClassName: 'content-center',
|
||||||
{
|
body: {
|
||||||
type: 'tag',
|
type: 'operation',
|
||||||
label: '${DATETOSTR(DATE(createTime), \'YYYY-MM-DD HH:mm\')}',
|
className: 'text-right',
|
||||||
displayMode: 'rounded',
|
buttons: [
|
||||||
color: '#4096ff',
|
{
|
||||||
},
|
visibleOn: '${!iframe}',
|
||||||
{
|
type: 'action',
|
||||||
type: 'tag',
|
label: '原文',
|
||||||
label: '${category}',
|
icon: 'fa fa-paperclip',
|
||||||
displayMode: 'rounded',
|
actionType: 'url',
|
||||||
color: '#2fa15d',
|
url: '${url}',
|
||||||
},
|
blank: true,
|
||||||
{
|
},
|
||||||
type: 'tag',
|
{
|
||||||
label: '${author}',
|
visibleOn: '${iframe}',
|
||||||
displayMode: 'rounded',
|
type: 'action',
|
||||||
color: '#bd6464',
|
label: '原文',
|
||||||
},
|
icon: 'fa fa-firefox',
|
||||||
]
|
actionType: 'dialog',
|
||||||
},
|
dialog: {
|
||||||
{
|
title: '原文',
|
||||||
type: 'each',
|
...readOnlyDialogOptions(),
|
||||||
className: 'mt-2',
|
size: 'xl',
|
||||||
source: "${SPLIT(tags, ',')}",
|
body: {
|
||||||
items: {
|
type: 'iframe',
|
||||||
type: 'tag',
|
src: '${url}',
|
||||||
label: '${item}',
|
height: 1000,
|
||||||
displayMode: 'rounded',
|
}
|
||||||
color: '#6b3481',
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '搜索',
|
||||||
|
icon: 'fa fa-search',
|
||||||
|
actionType: 'url',
|
||||||
|
url: 'https://www.bing.com/search?q=${title}',
|
||||||
|
blank: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
pagination(),
|
type: 'tpl',
|
||||||
]
|
className: 'text-current',
|
||||||
}
|
tpl: '${description}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tpl',
|
||||||
|
className: 'text-blue-900 text-sm mt-2',
|
||||||
|
tpl: '${name}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'wrapper',
|
||||||
|
size: 'none',
|
||||||
|
className: 'mt-2',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'tag',
|
||||||
|
label: '${DATETOSTR(DATE(createTime), \'YYYY-MM-DD HH:mm\')}',
|
||||||
|
displayMode: 'rounded',
|
||||||
|
color: '#4096ff',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tag',
|
||||||
|
label: '${category}',
|
||||||
|
displayMode: 'rounded',
|
||||||
|
color: '#2fa15d',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tag',
|
||||||
|
label: '${author}',
|
||||||
|
displayMode: 'rounded',
|
||||||
|
color: '#bd6464',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'each',
|
||||||
|
className: 'mt-2',
|
||||||
|
source: "${SPLIT(tags, ',')}",
|
||||||
|
items: {
|
||||||
|
type: 'tag',
|
||||||
|
label: '${item}',
|
||||||
|
displayMode: 'rounded',
|
||||||
|
color: '#6b3481',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user