CMS增加ES全文检索功能
This commit is contained in:
@@ -21,10 +21,11 @@ import java.util.List;
|
||||
/**
|
||||
* 栏目表Entity
|
||||
* @author 长春叭哥、ThinkGem
|
||||
* @version 2018-10-15
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Table(name = "${_prefix}cms_category", alias = "a", columns = {
|
||||
@Column(name = "category_code", attrName = "categoryCode", label = "栏目编码", isPK = true), @Column(includeEntity = TreeEntity.class),
|
||||
@Column(includeEntity = TreeEntity.class),
|
||||
@Column(name = "category_code", attrName = "categoryCode", label = "栏目编码", isPK = true),
|
||||
@Column(name = "category_name", attrName = "categoryName", label = "栏目名称", queryType = QueryType.LIKE, isTreeName = true),
|
||||
@Column(name = "site_code", attrName = "site.siteCode", label = "站点编码", queryType = QueryType.EQ),
|
||||
@Column(name = "module_type", attrName = "moduleType", label = "模块类型"), @Column(name = "image", attrName = "image", label = "栏目图片"),
|
||||
@@ -78,15 +79,15 @@ public class Category extends TreeEntity<Category> {
|
||||
private List<String> roleCodeList = ListUtils.newArrayList(); // 根据角色查询有权限的栏目列表
|
||||
|
||||
public Category() {
|
||||
this(null);
|
||||
super();
|
||||
}
|
||||
|
||||
public Category(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Category(String id, Site site) {
|
||||
super(id);
|
||||
public Category(Site site) {
|
||||
super();
|
||||
this.setSite(site);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.modules.cms.service;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.modules.cms.entity.Article;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文章全文检索服务类
|
||||
* @author ThinkGem
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
public interface ArticleIndexService {
|
||||
|
||||
/**
|
||||
* 保存索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
void save(Article article);
|
||||
|
||||
/**
|
||||
* 删除索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
void delete(Article article);
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
void rebuild(Article article);
|
||||
|
||||
/**
|
||||
* 文章高级搜索
|
||||
* @param page 分页对象
|
||||
* @param qStr 搜索字符串
|
||||
* @param qand 包含的字符串
|
||||
* @param qnot 不包含的字符串
|
||||
* @param bd 开始日期
|
||||
* @param ed 结束日期
|
||||
* @author ThinkGem
|
||||
*/
|
||||
Page<Map<String, Object>> searchPage(Page<Map<String, Object>> page, String qStr,
|
||||
String qand, String qnot, String bd, String ed,
|
||||
Map<String, String> params);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.modules.cms.dao.ArticleDao;
|
||||
import com.jeesite.modules.cms.dao.ArticleDataDao;
|
||||
import com.jeesite.modules.cms.entity.Article;
|
||||
@@ -34,7 +35,7 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* 文章表Service
|
||||
* @author 长春叭哥、ThinkGem
|
||||
* @version 2020-7-24
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Service
|
||||
public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
@@ -42,6 +43,8 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
@Autowired
|
||||
private ArticleDataDao articleDataDao;
|
||||
@Autowired(required = false)
|
||||
private ArticleIndexService articleIndexService;
|
||||
@Autowired(required = false)
|
||||
private PageCacheService pageCacheService;
|
||||
|
||||
private static ExecutorService updateExpiredWeightThreadPool = new ThreadPoolExecutor(5, 20,
|
||||
@@ -160,6 +163,10 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
}
|
||||
// 保存上传图片
|
||||
FileUploadUtils.saveFileUpload(article, article.getId(), "article_image");
|
||||
// 保存文章全文检索索引
|
||||
if (articleIndexService != null && Article.STATUS_NORMAL.equals(article.getStatus())) {
|
||||
articleIndexService.save(article);
|
||||
}
|
||||
// 清理首页、栏目和文章页面缓存
|
||||
if (pageCacheService != null) {
|
||||
pageCacheService.clearCache(article);
|
||||
@@ -174,6 +181,14 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
@Transactional
|
||||
public void updateStatus(Article article) {
|
||||
super.updateStatus(article);
|
||||
// 保存文章全文检索索引
|
||||
if (articleIndexService != null) {
|
||||
if (Article.STATUS_NORMAL.equals(article.getStatus())) {
|
||||
articleIndexService.save(article);
|
||||
} else {
|
||||
articleIndexService.delete(article);
|
||||
}
|
||||
}
|
||||
// 清理首页、栏目和文章页面缓存
|
||||
if (pageCacheService != null) {
|
||||
pageCacheService.clearCache(article);
|
||||
@@ -203,12 +218,27 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
@Transactional
|
||||
public void delete(Article article) {
|
||||
super.delete(article);
|
||||
// 保存文章全文检索索引
|
||||
if (articleIndexService != null) {
|
||||
articleIndexService.delete(article);
|
||||
}
|
||||
// 清理首页、栏目和文章页面缓存
|
||||
if (pageCacheService != null) {
|
||||
pageCacheService.clearCache(article);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public void rebuildIndex(Article article) {
|
||||
if (articleIndexService == null) {
|
||||
throw new ServiceException(text("未安装全文检索模块"));
|
||||
}
|
||||
articleIndexService.rebuild(article);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章高级搜索
|
||||
* @param page 分页对象
|
||||
@@ -217,10 +247,14 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
* @param qnot 不包含的字符串
|
||||
* @param bd 开始日期
|
||||
* @param ed 结束日期
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public Page<Map<String, Object>> searchPage(Page<Map<String, Object>> page, String qStr,
|
||||
String qand, String qnot, String bd, String ed, Map<String, String> params) {
|
||||
return page;
|
||||
if (articleIndexService == null) {
|
||||
throw new ServiceException(text("未安装全文检索模块"));
|
||||
}
|
||||
return articleIndexService.searchPage(page, qStr, qand, qnot, bd, ed, params);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,10 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.service;
|
||||
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.common.service.TreeService;
|
||||
import com.jeesite.modules.cms.dao.CategoryDao;
|
||||
import com.jeesite.modules.cms.entity.Article;
|
||||
import com.jeesite.modules.cms.entity.Category;
|
||||
import com.jeesite.modules.cms.utils.CmsUtils;
|
||||
import com.jeesite.modules.file.utils.FileUploadUtils;
|
||||
@@ -18,11 +20,13 @@ import java.util.List;
|
||||
/**
|
||||
* 栏目表Service
|
||||
* @author 长春叭哥、ThinkGem
|
||||
* @version 2020-7-24
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Service
|
||||
public class CategoryService extends TreeService<CategoryDao, Category> {
|
||||
|
||||
@Autowired(required = false)
|
||||
private ArticleIndexService articleIndexService;
|
||||
@Autowired(required = false)
|
||||
private PageCacheService pageCacheService;
|
||||
|
||||
@@ -110,4 +114,15 @@ public class CategoryService extends TreeService<CategoryDao, Category> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public void rebuildIndex(Category category) {
|
||||
if (articleIndexService == null) {
|
||||
throw new ServiceException(text("未安装全文检索模块"));
|
||||
}
|
||||
articleIndexService.rebuild(new Article(category));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,9 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.service;
|
||||
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.modules.cms.entity.Article;
|
||||
import com.jeesite.modules.cms.entity.Category;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -18,11 +21,13 @@ import com.jeesite.modules.file.utils.FileUploadUtils;
|
||||
/**
|
||||
* 站点表Service
|
||||
* @author 长春叭哥、ThinkGem
|
||||
* @version 2020-7-24
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Service
|
||||
public class SiteService extends CrudService<SiteDao, Site> {
|
||||
|
||||
@Autowired(required = false)
|
||||
private ArticleIndexService articleIndexService;
|
||||
@Autowired(required = false)
|
||||
private PageCacheService pageCacheService;
|
||||
|
||||
@@ -103,5 +108,16 @@ public class SiteService extends CrudService<SiteDao, Site> {
|
||||
super.delete(site);
|
||||
CmsUtils.removeCache("siteList");
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public void rebuildIndex(Site site) {
|
||||
if (articleIndexService == null) {
|
||||
throw new ServiceException(text("未安装全文检索模块"));
|
||||
}
|
||||
articleIndexService.rebuild(new Article(new Category(site)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.jeesite.common.collect.MapUtils;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.idgen.IdGen;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.lang.TimeUtils;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.cms.entity.Article;
|
||||
import com.jeesite.modules.cms.entity.Category;
|
||||
@@ -37,7 +38,7 @@ import java.util.Map;
|
||||
/**
|
||||
* 栏目表Controller
|
||||
* @author 长春叭哥、ThinkGem
|
||||
* @version 2020-7-24
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/cms/category")
|
||||
@@ -246,6 +247,20 @@ public class CategoryController extends BaseController {
|
||||
return renderResult(Global.TRUE, text("删除栏目表成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
@RequiresPermissions("cms:category:rebuildIndex")
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "rebuildIndex")
|
||||
public String rebuildIndex(Category category) {
|
||||
long start = System.currentTimeMillis();
|
||||
categoryService.rebuildIndex(category);
|
||||
return renderResult(Global.TRUE, "重建索引成功! 用时"
|
||||
+ TimeUtils.formatTime(System.currentTimeMillis() - start) + "。");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树结构数据
|
||||
* @param excludeCode 排除的Code
|
||||
|
||||
@@ -4,11 +4,17 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.web;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.lang.TimeUtils;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.common.web.CookieUtils;
|
||||
import com.jeesite.modules.cms.entity.Site;
|
||||
import com.jeesite.modules.cms.service.FileTempleteService;
|
||||
import com.jeesite.modules.cms.service.SiteService;
|
||||
import com.jeesite.modules.sys.utils.CorpUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -19,21 +25,14 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.common.web.CookieUtils;
|
||||
import com.jeesite.modules.cms.entity.Site;
|
||||
import com.jeesite.modules.cms.service.FileTempleteService;
|
||||
import com.jeesite.modules.cms.service.SiteService;
|
||||
import com.jeesite.modules.sys.utils.CorpUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 站点表Controller
|
||||
* @author 长春叭哥、ThinkGem
|
||||
* @version 2020-7-24
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/cms/site")
|
||||
@@ -135,6 +134,20 @@ public class SiteController extends BaseController {
|
||||
siteService.delete(site);
|
||||
return renderResult(Global.TRUE, text("删除站点表成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
* @author ThinkGem
|
||||
*/
|
||||
@RequiresPermissions("cms:site:rebuildIndex")
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "rebuildIndex")
|
||||
public String rebuildIndex(Site site) {
|
||||
long start = System.currentTimeMillis();
|
||||
siteService.rebuildIndex(site);
|
||||
return renderResult(Global.TRUE, "重建索引成功! 用时"
|
||||
+ TimeUtils.formatTime(System.currentTimeMillis() - start) + "。");
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择站点
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.List;
|
||||
/**
|
||||
* 网站Controller
|
||||
* @author ThinkGem、三片叶子、长春八哥
|
||||
* @version 2020-7-24
|
||||
* @version 2023-4-10
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${frontPath}")
|
||||
@@ -154,8 +154,8 @@ public class FrontController extends BaseController {
|
||||
else {
|
||||
// 文章模型
|
||||
if ("article".equals(category.getModuleType())) {
|
||||
Page<Article> page = new Page<Article>(pageNo, pageSize);
|
||||
Article searchArticle= new Article(category);
|
||||
Page<Article> page = new Page<>(pageNo, pageSize);
|
||||
Article searchArticle= new Article(category);
|
||||
searchArticle.setPage(page);
|
||||
page = articleService.findPage(searchArticle);
|
||||
model.addAttribute("page", page);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<label class="control-label col-sm-4" title="">
|
||||
<span class="required hide">*</span> ${text('来源')}:<i class="fa icon-question hide"></i></label>
|
||||
<div class="col-sm-8">
|
||||
<#form:radio path="source" dictType="cms_source" class="form-control required" />
|
||||
<#form:radio path="source" dictType="cms_source" defaultValue="2" class="form-control required" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,6 +97,9 @@ $('#dataGrid').dataGrid({
|
||||
}
|
||||
actions.push('<a href="${ctx}/cms/category/delete?categoryCode='+row.categoryCode+'" class="btnList" title="${text("删除栏目表")}" data-confirm="${text("确认要删除该栏目表及所有子栏目表吗?")}" data-deltreenode="'+row.id+'"><i class="fa fa-trash-o"></i></a> ');
|
||||
actions.push('<a href="${ctx}/cms/category/form?parentCode='+row.id+'&site.siteCode=${category.site.siteCode}" class="btnList" title="${text("新增下级栏目表")}"><i class="fa fa-plus-square"></i></a> ');
|
||||
//<% if(hasPermi('cms:category:rebuildIndex')){ %>
|
||||
actions.push('<a href="${ctx}/cms/category/rebuildIndex?categoryCode='+row.categoryCode+'" class="btnList" title="${text("重建该栏目索引")}" data-confirm="${text("确认重建该栏目下文章索引吗")}?"><i class="fa fa-crosshairs"></i></a> ');
|
||||
//<% } %>
|
||||
if (row.status == Global.STATUS_NORMAL){
|
||||
actions.push('<a href="${ctxFront}/list-'+row.categoryCode+'" target="_blank" title="${text("访问栏目")}"><i class="fa fa-globe"></i></a> ');
|
||||
}
|
||||
|
||||
@@ -78,6 +78,9 @@ $('#dataGrid').dataGrid({
|
||||
actions.push('<a href="${ctx}/cms/site/enable?siteCode='+row.siteCode+'" class="btnList" title="${text("启用站点")}" data-confirm="${text("确认要启用该站点吗?")}"><i class="glyphicon glyphicon-ok-circle"></i></a> ');
|
||||
}
|
||||
actions.push('<a href="${ctx}/cms/site/delete?siteCode='+row.siteCode+'" class="btnList" title="${text("删除站点")}" data-confirm="${text("确认要删除该站点吗?")}"><i class="fa fa-trash-o"></i></a> ');
|
||||
//<% if(hasPermi('cms:site:rebuildIndex')){ %>
|
||||
actions.push('<a href="${ctx}/cms/site/rebuildIndex?siteCode='+row.siteCode+'" class="btnList" title="${text("重建该站点索引")}" data-confirm="${text("确认重建该站点文章索引吗")}?"><i class="fa fa-crosshairs"></i></a> ');
|
||||
//<% } %>
|
||||
if (row.status == Global.STATUS_NORMAL){
|
||||
actions.push('<a href="${ctxFront}/index-'+row.siteCode+'" target="_blank" title="${text("访问站点")}"><i class="fa fa-globe"></i></a> ');
|
||||
}
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
<script src="${ctxStatic}/laydate/5.3/laydate.js?${_version}"></script>
|
||||
<style type="text/css">
|
||||
form.search {margin:12px 20px 5px;}
|
||||
form.search input.txt {padding:4px 8px;font-size:16px;width:300px;margin:5px;border:1px solid #bbb;border-radius:3px;}
|
||||
form.search input.txt {padding:4px 8px;font-size:18px;width:300px;margin:5px;border:1px solid #bbb;border-radius:3px;}
|
||||
form.search input.txt.date {width:133px;}
|
||||
form.search .sel {margin:15px 0;padding:10px 5px;border-bottom:1px solid #efefef;font-size:16px;}
|
||||
form.search input.txt:hover, form.search input.txt:focus {outline:none;border:1px solid #4e71f2;}
|
||||
form.search .sel {margin:0 0 15px 0;padding:10px 5px;border-bottom:1px solid #efefef;font-size:18px;}
|
||||
form.search .act {font-weight:bold;}
|
||||
form.search .btn {padding:4px 18px;font-size:16px;margin-top:-3px;margin-right:5px;border:1px solid #bbb;border-radius:3px;}
|
||||
form.search .btn:hover {color:#333;background:#d1d1d1}
|
||||
form.search .btn {padding:4px 18px;font-size:18px;margin-top:-3px;margin-right:5px;border:1px solid #bbb;border-radius:3px;}
|
||||
form.search .btn:hover, form.search .btn:focus {outline:none;color:#333;background:#d1d1d1}
|
||||
dl.search {line-height:25px;border-bottom:1px solid #efefef;margin:10px 20px 15px 20px;}
|
||||
dl.search dt {border-top:1px solid #efefef;padding:13px 5px 5px;font-size:16px;}
|
||||
dl.search dt {border-top:1px solid #efefef;padding:13px 5px 5px;font-size:18px;font-weight:normal;font-family:Arial,sans-serif;}
|
||||
dl.search dt a {color:#0000cc;text-decoration:underline;}
|
||||
dl.search dd {margin:0 5px 13px;font-size:13px;color:#333;word-break:break-all;word-wrap:break-word;}
|
||||
dl.search dd .info, dl.search dd .info a {margin-top:3px;font-size:12px;color:#008000;}
|
||||
dl.search dd {margin:0 5px 13px;font-size:14px;color:#333;word-break:break-all;word-wrap:break-word;}
|
||||
dl.search dd .info, dl.search dd .info a {margin-top:3px;font-size:14px;color:#008000;}
|
||||
dl.search .highlight {color:#DF0037;}
|
||||
.pagination{margin:0 0 10px 10px;}
|
||||
</style>
|
||||
@@ -67,23 +68,28 @@ $(function(){
|
||||
</form>
|
||||
<dl class="search">
|
||||
<#html:if test="${page! != null && (isBlank(t) || t == 'article')}">
|
||||
<#html:foreach items="${page.list}" var="article">
|
||||
<dt><a href="${article.url}" target="_blank">${article.title}</a></dt>
|
||||
<dd>${article.content}
|
||||
<#html:foreach items="${page.list}" var="obj">
|
||||
<dt><a href="${obj.data.url!}" target="_blank">${obj.data.title!}</a></dt>
|
||||
<dd>
|
||||
${obj.text}
|
||||
<div class="info">
|
||||
发布者:${article.createBy} 点击数:${article.hits}
|
||||
发布时间:${article.createDateStr} 更新时间:${article.updateDateStr}
|
||||
<a href="${article.url}" target="_blank">查看全文</a><br/>
|
||||
发布者:${obj.data.createBy!}
|
||||
发布时间:${obj.data.createDate!,dateFormat='yyyy-MM-dd'}
|
||||
更新时间:${obj.data.updateDate!,dateFormat='yyyy-MM-dd'}
|
||||
<a href="${obj.data.url!}" target="_blank">查看全文</a><br/>
|
||||
</div>
|
||||
</dd>
|
||||
</#html:foreach>
|
||||
</#html:if>
|
||||
<#html:if test="${page! != null && t == 'link'}">
|
||||
<#html:forEach items="${page.list}" var="link">
|
||||
<dt><a href="${link.url}" target="_blank">${link.title}</a></dt>
|
||||
<dd><div class="info">
|
||||
发布者:${link.createBy} 发布时间:${link.createDateStr} 更新时间:${link.updateDateStr}
|
||||
<a href="${link.url}" target="_blank">打开链接</a><br/>
|
||||
<#html:forEach items="${page.list}" var="obj">
|
||||
<dt><a href="${obj.data.url!}" target="_blank">${link.title}</a></dt>
|
||||
<dd>
|
||||
<div class="info">
|
||||
发布者:${obj.data.createBy!}
|
||||
发布时间:${link.createDate!,dateFormat='yyyy-MM-dd'}
|
||||
更新时间:${link.updateDate!,dateFormat='yyyy-MM-dd'}
|
||||
<a href="${obj.data.url!}" target="_blank">打开链接</a><br/>
|
||||
</div>
|
||||
</dd>
|
||||
</#html:forEach>
|
||||
|
||||
Reference in New Issue
Block a user