Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
智布道
OneBlog
提交
5cc2c44b
O
OneBlog
项目概览
智布道
/
OneBlog
9 个月 前同步成功
通知
11
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
OneBlog
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
5cc2c44b
编写于
9月 20, 2018
作者:
智布道
👁
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
优化freemarker自定义标签的实现代码,便于扩展
上级
0275ca01
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
324 addition
and
24 deletion
+324
-24
blog-admin/src/main/resources/static/assets/images/favicon.ico
...admin/src/main/resources/static/assets/images/favicon.ico
+0
-0
blog-core/src/main/java/com/zyd/blog/business/aspect/FreemarkerSharedVariableMonitorAspects.java
...siness/aspect/FreemarkerSharedVariableMonitorAspects.java
+4
-4
blog-core/src/main/java/com/zyd/blog/framework/config/FreeMarkerConfig.java
.../java/com/zyd/blog/framework/config/FreeMarkerConfig.java
+6
-6
blog-core/src/main/java/com/zyd/blog/framework/tag/ArticleTags.java
...src/main/java/com/zyd/blog/framework/tag/ArticleTags.java
+96
-0
blog-core/src/main/java/com/zyd/blog/framework/tag/BaseTag.java
...ore/src/main/java/com/zyd/blog/framework/tag/BaseTag.java
+90
-0
blog-core/src/main/java/com/zyd/blog/framework/tag/CustomTags.java
.../src/main/java/com/zyd/blog/framework/tag/CustomTags.java
+118
-0
blog-web/src/main/resources/static/img/favicon.ico
blog-web/src/main/resources/static/img/favicon.ico
+0
-0
blog-web/src/main/resources/templates/layout/sidebar.ftl
blog-web/src/main/resources/templates/layout/sidebar.ftl
+10
-14
未找到文件。
blog-admin/src/main/resources/static/assets/images/favicon.ico
查看替换文件 @
0275ca01
浏览文件 @
5cc2c44b
4.2 KB
|
W:
|
H:
1.1 KB
|
W:
|
H:
2-up
Swipe
Onion skin
blog-core/src/main/java/com/zyd/blog/business/aspect/
Rende
rAspects.java
→
blog-core/src/main/java/com/zyd/blog/business/aspect/
FreemarkerSharedVariableMonito
rAspects.java
浏览文件 @
5cc2c44b
...
...
@@ -13,7 +13,7 @@ import org.springframework.core.annotation.Order;
import
org.springframework.stereotype.Component
;
/**
*
提到core模块中,方便控制前后台
*
用于监控freemarker自定义标签中共享变量是否发生变化,发生变化时实时更新到内存中
*
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
* @version 2.0
...
...
@@ -23,7 +23,7 @@ import org.springframework.stereotype.Component;
@Component
@Aspect
@Order
(
1
)
public
class
Rende
rAspects
{
public
class
FreemarkerSharedVariableMonito
rAspects
{
private
static
volatile
long
configLastUpdateTime
=
0L
;
@Autowired
...
...
@@ -46,10 +46,10 @@ public class RenderAspects {
}
Long
updateTime
=
config
.
getUpdateTime
().
getTime
();
if
(
updateTime
==
configLastUpdateTime
)
{
log
.
info
(
"config表未更新"
);
log
.
debug
(
"config表未更新"
);
return
;
}
log
.
info
(
"config表已更新,重新加载config到freemarker tag
"
);
log
.
debug
(
"config表已更新,重新加载config到shared variable
"
);
configLastUpdateTime
=
updateTime
;
try
{
configuration
.
setSharedVariable
(
"config"
,
config
);
...
...
blog-core/src/main/java/com/zyd/blog/framework/config/FreeMarkerConfig.java
浏览文件 @
5cc2c44b
...
...
@@ -21,8 +21,8 @@ package com.zyd.blog.framework.config;
import
com.jagregory.shiro.freemarker.ShiroTags
;
import
com.zyd.blog.business.service.SysConfigService
;
import
com.zyd.blog.framework.tag.ArticleTag
Directive
;
import
com.zyd.blog.framework.tag.CustomTag
Directive
;
import
com.zyd.blog.framework.tag.ArticleTag
s
;
import
com.zyd.blog.framework.tag.CustomTag
s
;
import
freemarker.template.TemplateModelException
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -43,9 +43,9 @@ public class FreeMarkerConfig {
@Autowired
protected
freemarker
.
template
.
Configuration
configuration
;
@Autowired
protected
CustomTag
Directive
customTagDirective
;
protected
CustomTag
s
customTags
;
@Autowired
protected
ArticleTag
Directive
articleTagDirective
;
protected
ArticleTag
s
articleTags
;
@Autowired
private
SysConfigService
configService
;
...
...
@@ -54,8 +54,8 @@ public class FreeMarkerConfig {
*/
@PostConstruct
public
void
setSharedVariable
()
{
configuration
.
setSharedVariable
(
"zhydTag"
,
customTag
Directive
);
configuration
.
setSharedVariable
(
"articleTag"
,
articleTag
Directive
);
configuration
.
setSharedVariable
(
"zhydTag"
,
customTag
s
);
configuration
.
setSharedVariable
(
"articleTag"
,
articleTag
s
);
try
{
configuration
.
setSharedVariable
(
"config"
,
configService
.
get
());
//shiro标签
...
...
blog-core/src/main/java/com/zyd/blog/framework/tag/ArticleTag
Directive
.java
→
blog-core/src/main/java/com/zyd/blog/framework/tag/ArticleTag
s
.java
浏览文件 @
5cc2c44b
/**
* MIT License
*
*
<p>
* Copyright (c) 2018 yadong.zhang
*
*
<p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
<p>
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
*
<p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
...
...
@@ -28,12 +28,10 @@ import com.zyd.blog.business.entity.Article;
import
com.zyd.blog.business.enums.ArticleStatusEnum
;
import
com.zyd.blog.business.service.BizArticleService
;
import
com.zyd.blog.business.vo.ArticleConditionVO
;
import
freemarker.core.Environment
;
import
freemarker.template.*
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StringUtils
;
import
java.io.IOException
;
import
java.util.Map
;
/**
...
...
@@ -44,61 +42,55 @@ import java.util.Map;
* @website https://www.zhyd.me
* @date 2018/4/16 16:26
* @since 1.0
* @modify by zhyd 2018-09-20
* 调整实现,所有自定义标签只需继承BaseTag后通过构造函数将自定义标签类的className传递给父类即可。
* 增加标签时,只需要添加相关的方法即可,默认自定义标签的method就是自定义方法的函数名。
* 例如:<@articleTag method="recentArticles" ...></@articleTag>就对应 {{@link #recentArticles(Map)}}方法
*/
@Component
public
class
ArticleTagDirective
implements
TemplateDirectiveModel
{
private
static
final
String
METHOD_KEY
=
"method"
;
public
class
ArticleTags
extends
BaseTag
{
@Autowired
private
BizArticleService
articleService
;
@Override
public
void
execute
(
Environment
environment
,
Map
map
,
TemplateModel
[]
templateModels
,
TemplateDirectiveBody
templateDirectiveBody
)
throws
TemplateException
,
IOException
{
DefaultObjectWrapperBuilder
builder
=
new
DefaultObjectWrapperBuilder
(
Configuration
.
VERSION_2_3_25
);
if
(
map
.
containsKey
(
METHOD_KEY
))
{
String
method
=
map
.
get
(
METHOD_KEY
).
toString
();
int
pageSize
=
10
;
if
(
map
.
containsKey
(
"pageSize"
))
{
String
pageSizeStr
=
map
.
get
(
"pageSize"
).
toString
();
pageSize
=
Integer
.
parseInt
(
pageSizeStr
);
}
long
typeId
=
-
1
;
if
(
map
.
containsKey
(
"typeId"
))
{
String
typeStr
=
map
.
get
(
"typeId"
).
toString
();
typeId
=
Long
.
parseLong
(
typeStr
);
}
public
ArticleTags
()
{
super
(
ArticleTags
.
class
.
getName
());
}
public
Object
recentArticles
(
Map
params
)
{
int
pageSize
=
this
.
getPageSize
(
params
);
return
articleService
.
listRecent
(
pageSize
);
}
public
Object
recommendedList
(
Map
params
)
{
int
pageSize
=
this
.
getPageSize
(
params
);
return
articleService
.
listRecommended
(
pageSize
);
}
public
Object
randomList
(
Map
params
)
{
int
pageSize
=
this
.
getPageSize
(
params
);
return
articleService
.
listRandom
(
pageSize
);
}
public
Object
hotList
(
Map
params
)
{
int
pageSize
=
this
.
getPageSize
(
params
);
return
articleService
.
listHotArticle
(
pageSize
);
}
switch
(
method
)
{
case
"recentArticles"
:
// 近期文章
environment
.
setVariable
(
"recentArticles"
,
builder
.
build
().
wrap
(
articleService
.
listRecent
(
pageSize
)));
break
;
case
"recommendedList"
:
// 站长推荐
environment
.
setVariable
(
"recommendedList"
,
builder
.
build
().
wrap
(
articleService
.
listRecommended
(
pageSize
)));
break
;
case
"randomList"
:
// 随机文章
environment
.
setVariable
(
"randomList"
,
builder
.
build
().
wrap
(
articleService
.
listRandom
(
pageSize
)));
break
;
case
"hotList"
:
// 热门文章
environment
.
setVariable
(
"hotList"
,
builder
.
build
().
wrap
(
articleService
.
listHotArticle
(
pageSize
)));
break
;
case
"typeList"
:
// 按文章分类查询
ArticleConditionVO
vo
=
new
ArticleConditionVO
();
vo
.
setTypeId
(
typeId
);
// 已发布状态
vo
.
setStatus
(
ArticleStatusEnum
.
PUBLISHED
.
getCode
());
vo
.
setPageSize
(
pageSize
);
PageInfo
<
Article
>
pageInfo
=
articleService
.
findPageBreakByCondition
(
vo
);
environment
.
setVariable
(
"typeList"
,
builder
.
build
().
wrap
(
null
==
pageInfo
?
null
:
pageInfo
.
getList
()));
break
;
default
:
break
;
}
public
Object
typeList
(
Map
params
)
{
int
pageSize
=
this
.
getPageSize
(
params
);
long
typeId
=
-
1
;
String
typeStr
=
getParam
(
params
,
"typeId"
);
if
(!
StringUtils
.
isEmpty
(
typeStr
))
{
typeId
=
Long
.
parseLong
(
typeStr
);
}
templateDirectiveBody
.
render
(
environment
.
getOut
());
// 按文章分类查询
ArticleConditionVO
vo
=
new
ArticleConditionVO
();
vo
.
setTypeId
(
typeId
);
// 已发布状态
vo
.
setStatus
(
ArticleStatusEnum
.
PUBLISHED
.
getCode
());
vo
.
setPageSize
(
pageSize
);
PageInfo
<
Article
>
pageInfo
=
articleService
.
findPageBreakByCondition
(
vo
);
return
null
==
pageInfo
?
null
:
pageInfo
.
getList
();
}
}
blog-core/src/main/java/com/zyd/blog/framework/tag/BaseTag.java
0 → 100644
浏览文件 @
5cc2c44b
package
com.zyd.blog.framework.tag
;
import
freemarker.core.Environment
;
import
freemarker.template.Configuration
;
import
freemarker.template.DefaultObjectWrapper
;
import
freemarker.template.DefaultObjectWrapperBuilder
;
import
freemarker.template.SimpleScalar
;
import
freemarker.template.TemplateDirectiveBody
;
import
freemarker.template.TemplateDirectiveModel
;
import
freemarker.template.TemplateException
;
import
freemarker.template.TemplateModel
;
import
freemarker.template.TemplateModelException
;
import
org.springframework.util.StringUtils
;
import
java.io.IOException
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
/**
* 所有自定义标签的父类,负责调用具体的子类方法
*
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
* @version 1.0
* @website https://www.zhyd.me
* @date 2018/9/18 16:19
* @since 1.8
*/
public
abstract
class
BaseTag
implements
TemplateDirectiveModel
{
private
String
clazzPath
=
null
;
public
BaseTag
(
String
targetClassPath
)
{
clazzPath
=
targetClassPath
;
}
private
String
getMethod
(
Map
params
)
{
return
this
.
getParam
(
params
,
"method"
);
}
protected
int
getPageSize
(
Map
params
)
{
int
pageSize
=
10
;
String
pageSizeStr
=
this
.
getParam
(
params
,
"pageSize"
);
if
(!
StringUtils
.
isEmpty
(
pageSizeStr
))
{
pageSize
=
Integer
.
parseInt
(
pageSizeStr
);
}
return
pageSize
;
}
private
void
verifyParameters
(
Map
params
)
throws
TemplateModelException
{
String
permission
=
this
.
getMethod
(
params
);
if
(
permission
==
null
||
permission
.
length
()
==
0
)
{
throw
new
TemplateModelException
(
"The 'name' tag attribute must be set."
);
}
}
String
getParam
(
Map
params
,
String
paramName
)
{
Object
value
=
params
.
get
(
paramName
);
return
value
instanceof
SimpleScalar
?
((
SimpleScalar
)
value
).
getAsString
()
:
null
;
}
private
DefaultObjectWrapper
getBuilder
()
{
return
new
DefaultObjectWrapperBuilder
(
Configuration
.
VERSION_2_3_25
).
build
();
}
private
TemplateModel
getModel
(
Object
o
)
throws
TemplateModelException
{
return
this
.
getBuilder
().
wrap
(
o
);
}
@Override
public
void
execute
(
Environment
environment
,
Map
map
,
TemplateModel
[]
templateModels
,
TemplateDirectiveBody
templateDirectiveBody
)
throws
TemplateException
,
IOException
{
this
.
verifyParameters
(
map
);
String
funName
=
getMethod
(
map
);
Method
method
=
null
;
try
{
Class
clazz
=
Class
.
forName
(
clazzPath
);
method
=
clazz
.
getDeclaredMethod
(
funName
,
Map
.
class
);
if
(
method
!=
null
)
{
// 核心处理,调用子类的具体方法,获取返回值
Object
res
=
method
.
invoke
(
this
,
map
);
environment
.
setVariable
(
funName
,
getModel
(
res
));
}
}
catch
(
NoSuchMethodException
|
IllegalAccessException
|
InvocationTargetException
|
ClassNotFoundException
e
)
{
e
.
printStackTrace
();
}
templateDirectiveBody
.
render
(
environment
.
getOut
());
}
}
blog-core/src/main/java/com/zyd/blog/framework/tag/CustomTag
Directive
.java
→
blog-core/src/main/java/com/zyd/blog/framework/tag/CustomTag
s
.java
浏览文件 @
5cc2c44b
...
...
@@ -25,17 +25,21 @@ package com.zyd.blog.framework.tag;
import
com.zyd.blog.business.entity.User
;
import
com.zyd.blog.business.enums.UserTypeEnum
;
import
com.zyd.blog.business.service.*
;
import
com.zyd.blog.business.service.BizCommentService
;
import
com.zyd.blog.business.service.BizTagsService
;
import
com.zyd.blog.business.service.BizTypeService
;
import
com.zyd.blog.business.service.SysConfigService
;
import
com.zyd.blog.business.service.SysResourcesService
;
import
com.zyd.blog.util.SessionUtil
;
import
freemarker.core.Environment
;
import
freemarker.template.*
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.NumberUtils
;
import
org.springframework.util.StringUtils
;
import
java.
io.IOException
;
import
java.
text.DecimalFormat
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Random
;
/**
* 自定义的freemarker标签
...
...
@@ -45,10 +49,17 @@ import java.util.Map;
* @website https://www.zhyd.me
* @date 2018/4/16 16:26
* @since 1.0
* @modify by zhyd 2018-09-20
* 调整实现,所有自定义标签只需继承BaseTag后通过构造函数将自定义标签类的className传递给父类即可。
* 增加标签时,只需要添加相关的方法即可,默认自定义标签的method就是自定义方法的函数名。
* 例如:<@zhydTag method="types" ...></@zhydTag>就对应 {{@link #types(Map)}}方法
*/
@Component
public
class
CustomTagDirective
implements
TemplateDirectiveModel
{
private
static
final
String
METHOD_KEY
=
"method"
;
public
class
CustomTags
extends
BaseTag
{
private
final
Random
randoms
=
new
Random
();
private
final
DecimalFormat
df
=
new
DecimalFormat
(
"#.##"
);
@Autowired
private
BizTypeService
bizTypeService
;
@Autowired
...
...
@@ -60,55 +71,48 @@ public class CustomTagDirective implements TemplateDirectiveModel {
@Autowired
private
SysConfigService
configService
;
@Override
public
void
execute
(
Environment
environment
,
Map
map
,
TemplateModel
[]
templateModels
,
TemplateDirectiveBody
templateDirectiveBody
)
throws
TemplateException
,
IOException
{
DefaultObjectWrapperBuilder
builder
=
new
DefaultObjectWrapperBuilder
(
Configuration
.
VERSION_2_3_25
);
if
(
map
.
containsKey
(
METHOD_KEY
))
{
String
method
=
map
.
get
(
METHOD_KEY
).
toString
();
int
pageSize
=
10
;
if
(
map
.
containsKey
(
"pageSize"
))
{
String
pageSizeStr
=
map
.
get
(
"pageSize"
).
toString
();
pageSize
=
Integer
.
parseInt
(
pageSizeStr
);
}
switch
(
method
)
{
case
"types"
:
environment
.
setVariable
(
"types"
,
builder
.
build
().
wrap
(
bizTypeService
.
listTypeForMenu
()));
break
;
case
"tagsList"
:
// 所有标签
environment
.
setVariable
(
"tagsList"
,
builder
.
build
().
wrap
(
bizTagsService
.
listAll
()));
break
;
case
"availableMenus"
:
// 所有可用的菜单资源
environment
.
setVariable
(
"availableMenus"
,
builder
.
build
().
wrap
(
resourcesService
.
listAllAvailableMenu
()));
break
;
case
"recentComments"
:
// 近期评论
environment
.
setVariable
(
"recentComments"
,
builder
.
build
().
wrap
(
commentService
.
listRecentComment
(
pageSize
)));
break
;
case
"siteInfo"
:
// 站点属性
environment
.
setVariable
(
"siteInfo"
,
builder
.
build
().
wrap
(
configService
.
getSiteInfo
()));
break
;
case
"menus"
:
Integer
userId
=
null
;
User
user
=
SessionUtil
.
getUser
();
if
(
map
.
containsKey
(
"userId"
)
&&
user
!=
null
&&
!
user
.
getUserTypeEnum
().
equals
(
UserTypeEnum
.
ROOT
))
{
String
userIdStr
=
map
.
get
(
"userId"
).
toString
();
if
(
StringUtils
.
isEmpty
(
userIdStr
))
{
return
;
}
userId
=
Integer
.
parseInt
(
userIdStr
);
}
Map
<
String
,
Object
>
params
=
new
HashMap
<>(
2
);
params
.
put
(
"type"
,
"menu"
);
params
.
put
(
"userId"
,
userId
);
environment
.
setVariable
(
"menus"
,
builder
.
build
().
wrap
(
resourcesService
.
listUserResources
(
params
)));
break
;
default
:
break
;
}
public
CustomTags
()
{
super
(
CustomTags
.
class
.
getName
());
}
public
Object
types
(
Map
params
)
{
return
bizTypeService
.
listTypeForMenu
();
}
public
Object
tagsList
(
Map
params
)
{
return
bizTagsService
.
listAll
();
}
public
Object
availableMenus
(
Map
params
)
{
return
resourcesService
.
listAllAvailableMenu
();
}
public
Object
recentComments
(
Map
params
)
{
int
pageSize
=
this
.
getPageSize
(
params
);
return
commentService
.
listRecentComment
(
pageSize
);
}
public
Object
siteInfo
(
Map
params
)
{
return
configService
.
getSiteInfo
();
}
public
Object
menus
(
Map
params
)
{
User
user
=
SessionUtil
.
getUser
();
String
userIdStr
=
getParam
(
params
,
"userId"
);
Integer
userId
=
null
;
if
(!
StringUtils
.
isEmpty
(
userIdStr
)
&&
user
!=
null
&&
!
user
.
getUserTypeEnum
().
equals
(
UserTypeEnum
.
ROOT
))
{
userId
=
Integer
.
parseInt
(
userIdStr
);
return
null
;
}
templateDirectiveBody
.
render
(
environment
.
getOut
());
Map
<
String
,
Object
>
p
=
new
HashMap
<>(
2
);
p
.
put
(
"type"
,
"menu"
);
p
.
put
(
"userId"
,
userId
);
return
resourcesService
.
listUserResources
(
p
);
}
public
Object
random
(
Map
params
)
{
int
max
=
NumberUtils
.
parseNumber
(
getParam
(
params
,
"max"
),
Integer
.
class
);
int
min
=
NumberUtils
.
parseNumber
(
getParam
(
params
,
"min"
),
Integer
.
class
);
return
df
.
format
(
randoms
.
nextInt
(
max
)
%
(
max
-
min
+
1
)
+
min
+
Math
.
random
());
}
}
blog-web/src/main/resources/static/img/favicon.ico
查看替换文件 @
0275ca01
浏览文件 @
5cc2c44b
4.2 KB
|
W:
|
H:
1.1 KB
|
W:
|
H:
2-up
Swipe
Onion skin
blog-web/src/main/resources/templates/layout/sidebar.ftl
浏览文件 @
5cc2c44b
...
...
@@ -55,20 +55,16 @@
</div>
</div>
<div class="sidebar-module">
<h5 class="sidebar-title"><i class="fa fa-tags icon"></i><strong>文章标签</strong></h5>
<ul class="list-unstyled list-inline">
<@zhydTag method="tagsList" pageSize="10">
<#if tagsList?exists && (tagsList?size > 0)>
<#list tagsList as item>
<li class="tag-li">
<a class="btn btn-default btn-xs" href="${config.siteUrl}/tag/${item.id?c}" title="${item.name?if_exists}" data-toggle="tooltip" data-placement="bottom">
${item.name?if_exists}
</a>
</li>
</#list>
</#if>
</@zhydTag>
</ul>
<h5 class="sidebar-title"><i class="fa fa-tags icon"></i><strong>标签云</strong></h5>
<@zhydTag method="tagsList" pageSize="10">
<#if tagsList?exists && (tagsList?size > 0)>
<#list tagsList as item>
<a style="font-size: <@zhydTag method="random" max="15" min="10">${random}</@zhydTag>px;margin: 5px;" href="${config.siteUrl}/tag/${item.id?c}" title="${item.name?if_exists}" data-toggle="tooltip" data-placement="bottom">
${item.name?if_exists}
</a>
</#list>
</#if>
</@zhydTag>
</div>
<@zhydTag method="recentComments" pageSize="10">
<#if recentComments?? && recentComments?size gt 0>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录