后端springboot,前端framemark和bootstrap。
分词搜索不准确,则用postmen插入这一段
curl -X PUT 'http://localhost:9200/cs/_settings?pretty' -H 'Content-Type:application/json' -d '{"index.max_ngram_diff":10,"analysis":{"analyzer":{"ngram_analyzer":{"tokenizer":"ngram_tokenizer"}},"tokenizer":{"ngram_tokenizer":{"type":"ngram","min_gram":1,"max_gram":10,"token_chars":["letter","digit"]}}}}'
ES 和 springboot的版本匹配
ES:
package com.bfr.telinksemifourm.manage.plugin;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bfr.telinksemifourm.manage.config.service.BaseService;
import com.bfr.telinksemifourm.manage.service.ISystemConfigService;
import com.bfr.telinksemifourm.manage.util.MyPage;
import com.bfr.telinksemifourm.shared.model.SystemConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* Created by .
* Copyright (c) 2020, All Rights Reserved.
*
*/
@Component
//@DependsOn("mybatisPlusConfig")
public class ElasticSearchService implements BaseService<RestHighLevelClient> {
@Autowired
private ISystemConfigService systemConfigService;
private Logger log = LoggerFactory.getLogger(ElasticSearchService.class);
private RestHighLevelClient client;
// 索引名
private String name;
public static XContentBuilder topicMappingBuilder;
static {
try {
topicMappingBuilder = JsonXContent.contentBuilder().startObject().startObject("properties")
// .startObject("id")
// .field("type", "integer")
// .endObject()
.startObject("title").field("type", "text").field("analyzer", "ik_max_word").field("index", "true")
.endObject().startObject("content").field("type", "text").field("analyzer", "ik_max_word").field("index",
"true").endObject().endObject().endObject();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public RestHighLevelClient instance() {
if (this.client != null) return client;
try {
SystemConfig systemConfigHost = systemConfigService.selectByKey("elasticsearch_host");
String host = systemConfigHost.getValue();
SystemConfig systemConfigPort = systemConfigService.selectByKey("elasticsearch_port");
String port = systemConfigPort.getValue();
SystemConfig systemConfigName = systemConfigService.selectByKey("elasticsearch_index");
name = systemConfigName.getValue();
if (StringUtils.isEmpty(host) || StringUtils.isEmpty(port)) return null;
client = new RestHighLevelClient(RestClient.builder(new HttpHost(host, Integer.parseInt(port), "http")));
// 判断索引是否存在,不存在创建
if (!this.existIndex()) this.createIndex("topic", topicMappingBuilder);
return client;
} catch (NumberFormatException e) {
log.error(e.getMessage());
return null;
}
}
// 创建索引
public boolean createIndex(String type, XContentBuilder mappingBuilder) {
try {
if (this.instance() == null) return false;
CreateIndexRequest request = new CreateIndexRequest(name);
request.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_shards", 5));
if (mappingBuilder != null) request.mapping(type, mappingBuilder);
CreateIndexResponse response = this.client.indices().create(request, RequestOptions.DEFAULT);
return response.isAcknowledged();
} catch (IOException e) {
log.error(e.getMessage());
return false;
}
}
// 检查索引是否存在
public boolean existIndex() {
try {
if (this.instance() == null) return false;
GetIndexRequest request = new GetIndexRequest();
request.indices(name);
request.local(false);
request.humanReadable(true);
return client.indices().exists(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage());
return false;
}
}
// 删除索引
public boolean deleteIndex() {
try {
if (this.instance() == null) return false;
DeleteIndexRequest request = new DeleteIndexRequest(name);
request.indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
return response.isAcknowledged();
} catch (IOException e) {
log.error(e.getMessage());
return false;
}
}
// 创建文档
public void createDocument(String type, String id, Map<String, Object> source) {
try {
if (this.instance() == null) return;
IndexRequest request = new IndexRequest(name, type, id);
request.source(source);
client.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage());
}
}
// 更新文档
public void updateDocument(String type, String id, Map<String, Object> source) {
try {
if (this.instance() == null) return;
UpdateRequest request = new UpdateRequest(name, type, id);
request.doc(source);
client.update(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage());
}
}
// 删除文档
public void deleteDocument(String type, String id) {
try {
if (this.instance() == null) return;
DeleteRequest request = new DeleteRequest(name, type, id);
client.delete(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage());
}
}
// 批量创建文档
public void bulkDocument(String type, Map<String, Map<String, Object>> sources) {
try {
if (this.instance() == null) return;
BulkRequest requests = new BulkRequest();
Iterator<String> it = sources.keySet().iterator();
int count = 0;
while (it.hasNext()) {
count++;
String next = it.next();
IndexRequest request = new IndexRequest(name, type, next);
request.source(sources.get(next));
requests.add(request);
if (count % 1000 == 0) {
client.bulk(requests, RequestOptions.DEFAULT);
requests.requests().clear();
count = 0;
}
}
if (requests.numberOfActions() > 0) client.bulk(requests, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage());
}
}
// 批量删除文档
public void bulkDeleteDocument(String type, List<String> ids) {
try {
if (this.instance() == null) return;
BulkRequest requests = new BulkRequest();
int count = 0;
for (String id : ids) {
count++;
DeleteRequest request = new DeleteRequest(name, type, id);
requests.add(request);
if (count % 1000 == 0) {
client.bulk(requests, RequestOptions.DEFAULT);
requests.requests().clear();
count = 0;
}
}
if (requests.numberOfActions() > 0) client.bulk(requests, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage());
}
}
/**
* 查询
*
* @param pageNo
* @param pageSize
* @param keyword 要查询的内容
* @param fields 要查询的字段,可以为多个
* @return 分页对象 {@link Page}
*/
public MyPage<Map<String, Object>> searchDocumentEs(Integer pageNo, Integer pageSize, String keyword, String indices, String... fields) {
try {
if (this.instance() == null) return new MyPage<>();
SearchRequest request = new SearchRequest(name);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.multiMatchQuery(keyword, fields));
builder.from((pageNo - 1) * pageSize).size(pageSize);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 总条数
long totalCount = response.getHits().getTotalHits().value;
// 结果集
List<Map<String, Object>> records = Arrays.stream(response.getHits().getHits()).map(hit -> {
Map<String, Object> map = new HashMap<>();
map.put("id", hit.getId());
map.putAll(hit.getSourceAsMap());
return map;
}).collect(Collectors.toList());
MyPage<Map<String, Object>> page = new MyPage<>(pageNo, pageSize);
page.setTotal(totalCount);
page.setRecords(records);
return page;
} catch (IOException e) {
log.error(e.getMessage());
return new MyPage<>();
}
}
/**
* 查询
*
* @param pageNo
* @param pageSize
* @param keyword 要查询的内容
* @param fields 要查询的字段,可以为多个
* @return 分页对象 {@link Page}
*/
public MyPage<Map<String, Object>> searchDocument(Integer pageNo, Integer pageSize, String keyword, String... fields) {
try {
if (this.instance() == null) return new MyPage<>();
SearchRequest request = new SearchRequest(name);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.multiMatchQuery(keyword, fields));
builder.from((pageNo - 1) * pageSize).size(pageSize);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 总条数
long totalCount = response.getHits().getTotalHits().value;
// 结果集
List<Map<String, Object>> records = Arrays.stream(response.getHits().getHits()).map(hit -> {
Map<String, Object> map = new HashMap<>();
map.put("id", hit.getId());
map.putAll(hit.getSourceAsMap());
return map;
}).collect(Collectors.toList());
MyPage<Map<String, Object>> page = new MyPage<>(pageNo, pageSize);
page.setTotal(totalCount);
page.setRecords(records);
return page;
} catch (IOException e) {
log.error(e.getMessage());
return new MyPage<>();
}
}
}
package com.bfr.telinksemifourm.manage.plugin;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bfr.telinksemifourm.manage.mapper.TagMapper;
import com.bfr.telinksemifourm.manage.mapper.TopicMapper;
import com.bfr.telinksemifourm.shared.model.Tag;
import com.bfr.telinksemifourm.shared.model.Topic;
import net.sf.jsqlparser.statement.select.Top;
import org.apache.ibatis.jdbc.Null;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Created by .
* Copyright (c) 2020, All Rights Reserved.
*
*/
@Component
@Aspect
public class ElasticSearchPlugin {
@Autowired
private ElasticSearchService elasticSearchService;
@Autowired
private TopicMapper topicMapper;
@Autowired
private TagMapper tagMapper;
// @Around("com.bfr.telinksemifourm.manage.hook.TopicServiceHook.search()")
public Object search(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object[] args = proceedingJoinPoint.getArgs();
if (elasticSearchService.instance() == null) return proceedingJoinPoint.proceed(args);
return elasticSearchService.searchDocument((Integer) args[0], (Integer) args[1], (String) args[2], "title", "content");
}
/**
* 查询集合
*
* @author zk
* @date 2020/6/23
*/
public Object searchEs(Integer pageNo, Integer pageSize, String keyword) throws Throwable {
if (elasticSearchService.instance() == null) return null;
return elasticSearchService.searchDocumentEs(pageNo, pageSize, keyword, "topicTag",
"title", "content", "comment", "tagList.name");
}
/**
* 保存tag的ES
* @author zxk
* @date 2020/6/23
*/
public void saveTagEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
Map<String, Object> map = new HashMap<>();
map.put("type", "tag");
map.put("id", "");
map.put("title", "");
map.put("content", "");
map.put("comment", "");
map.put("tagList.id", params.get("id"));
map.put("tagList.name", params.get("name"));
elasticSearchService.createDocument("topicTag", "t" + String.valueOf(params.get("id")) , map);
}
}
/**
* 修改ES
* @author zxk
* @date 2020/7/16
*/
public void updateEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
Map<String, Object> map = new HashMap<>();
map.put("type", params.get("type"));
map.put("id", params.get("id"));
map.put("title", params.get("title"));
map.put("content", params.get("content"));
map.put("comment", "");
map.put("tagList.id", "");
map.put("tagList.name", "");
elasticSearchService.updateDocument("topicTag", String.valueOf(params.get("id")) , map);
}
}
/**
* 修改tag的ES
* @author zxk
* @date 2020/6/23
*/
public void updateTagEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
Map<String, Object> map = new HashMap<>();
map.put("type", "tag");
map.put("id", "");
map.put("title", "");
map.put("content", "");
map.put("comment", "");
map.put("tagList.id", params.get("id"));
map.put("tagList.name", params.get("name"));
elasticSearchService.updateDocument("topicTag", "t" + String.valueOf(params.get("id")) , map);
}
}
/**
* 修改faq的ES
* @author zxk
* @date 2020/7/16
*/
public void updateFaqEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
Map<String, Object> map = new HashMap<>();
map.put("type", "faq");
map.put("id", params.get("id"));
map.put("title", params.get("title"));
map.put("content", params.get("content"));
map.put("comment", "");
map.put("tagList.id", "");
map.put("tagList.name", "");
elasticSearchService.updateDocument("topicTag", "f" + String.valueOf(params.get("id")) , map);
}
}
/**
* 保存topic的ES
* @author zxk
* @date 2020/6/23
*/
public void saveTopicEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
Map<String, Object> map = new HashMap<>();
map.put("type", params.get("type"));
map.put("id", params.get("id"));
map.put("title", params.get("title"));
map.put("content", params.get("content"));
map.put("comment", "");
map.put("tagList.id", "");
map.put("tagList.name", "");
elasticSearchService.createDocument("topicTag", String.valueOf(params.get("id")), map);
}
}
/**
* 保存faq的ES
* @author zxk
* @date 2020/7/16
*/
public void saveFaqEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
Map<String, Object> map = new HashMap<>();
map.put("type", "faq");
map.put("id", params.get("id"));
map.put("title", params.get("title"));
map.put("content", params.get("content"));
map.put("comment", "");
map.put("tagList.id", "");
map.put("tagList.name", "");
elasticSearchService.createDocument("topicTag", "f" + String.valueOf(params.get("id")), map);
}
}
/**
* 删除faq的ES
* @author zxk
* @date 2020/7/9
*/
public void deleteFaqEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
elasticSearchService.deleteDocument("topicTag", "f" + String.valueOf(params.get("id")));
}
}
/**
* 删除标签的ES
* @author zxk
* @date 2020/7/9
*/
public void deleteEs(Map<String, Object> params) {
if (elasticSearchService.instance() != null) {
elasticSearchService.deleteDocument("topicTag", "t" + String.valueOf(params.get("id")));
}
}
/**
* 对所有未加索引的帖子进行添加索引
*
* @author zxk
* @date 2020/7/11
*/
public void topicsIndexTimeIsNull() {
if (elasticSearchService.instance() != null) {
List<Topic> topics = topicMapper.selectAllIndexTimeIsNull();
Map<String, Map<String, Object>> sources = topics.stream().collect(Collectors.toMap(
key -> String.valueOf(key.getId()),
value -> {
Map<String, Object> map = new HashMap<>();
map.put("type", "topicTag");
map.put("title", value.getTitle());
map.put("content", value.getContent());
return map;
}
));
elasticSearchService.bulkDocument("topicTag", sources);
}
}
/**
* 对所有未加索引的标签进行添加索引
*
* @author zxk
* @date 2020/7/15
*/
public void tagsIndexTimeIsNull() {
List<Tag> tags = tagMapper.selectAllIndexTimeIsNull();
Map<String, Map<String, Object>> sources = tags.stream().collect(Collectors.toMap(
key -> "t" + String.valueOf(key.getId()),
value -> {
Map<String, Object> map = new HashMap<>();
map.put("type", "tag");
map.put("tagList.id", value.getId());
map.put("tagList.name", value.getName());
return map;
}
));
elasticSearchService.bulkDocument("topicTag", sources);
}
/**
* 对所有已加索引的帖子进行删除索引
*
* @author zxk
* @date 2020/7/11
*/
public void topicsIndexTimeIsNotNull() {
if (elasticSearchService.instance() != null) {
List<Topic> topics = topicMapper.selectAllIndexTimeIsNotNull();
List<String> ids = new ArrayList<>();
for(Topic topic : topics){
ids.add(String.valueOf(topic.getId()));
}
elasticSearchService.bulkDeleteDocument("topicTag", ids);
}
}
/**
* 对所有已加索引的标签进行删除索引
*
* @author zxk
* @date 2020/7/11
*/
public void tagsIndexTimeIsNotNull() {
if (elasticSearchService.instance() != null) {
List<Tag> tags = tagMapper.selectAllIndexTimeIsNotNull();
List<String> ids = new ArrayList<>();
for(Tag tag : tags){
ids.add("t" + tag.getId());
}
elasticSearchService.bulkDeleteDocument("topicTag", ids);
}
}
@After("com.bfr.telinksemifourm.manage.hook.IndexedServiceHook.indexAllTopic()")
public void indexAllTopic() {
if (elasticSearchService.instance() != null) {
List<Topic> topics = topicMapper.selectList(null);
Map<String, Map<String, Object>> sources = topics.stream().collect(Collectors.toMap(
key -> String.valueOf(key.getId()),
value -> {
Map<String, Object> map = new HashMap<>();
map.put("title", value.getTitle());
map.put("content", value.getContent());
return map;
}
));
elasticSearchService.bulkDocument("topicTag", sources);
}
}
@After("com.bfr.telinksemifourm.manage.hook.IndexedServiceHook.indexTopic()")
public void indexTopic(JoinPoint joinPoint) {
if (elasticSearchService.instance() != null) {
Object[] args = joinPoint.getArgs();
Map<String, Object> source = new HashMap<>();
source.put("title", args[1]);
source.put("content", args[2]);
elasticSearchService.createDocument("topic", (String) args[0], source);
}
}
@After("com.bfr.telinksemifourm.manage.hook.IndexedServiceHook.deleteTopicIndex()")
public void deleteTopicIndex(JoinPoint joinPoint) {
if (elasticSearchService.instance() != null) {
elasticSearchService.deleteDocument("topic", (String) joinPoint.getArgs()[0]);
}
}
@After("com.bfr.telinksemifourm.manage.hook.IndexedServiceHook.batchDeleteIndex()")
public void batchDeleteIndex(JoinPoint joinPoint) {
if (elasticSearchService.instance() != null) {
List<Topic> topics = topicMapper.selectList(null);
List<Integer> ids = topics.stream().map(Topic::getId).collect(Collectors.toList());
// elasticSearchService.bulkDeleteDocument("topic", ids);
}
}
}
package com.bfr.telinksemifourm.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bfr.telinksemifourm.manage.mapper.FaqMapper;
import com.bfr.telinksemifourm.manage.mapper.FaqSubjectMapper;
import com.bfr.telinksemifourm.manage.plugin.ElasticSearchPlugin;
import com.bfr.telinksemifourm.manage.service.IFaqService;
import com.bfr.telinksemifourm.manage.service.ISystemConfigService;
import com.bfr.telinksemifourm.manage.util.MyPage;
import com.bfr.telinksemifourm.shared.model.Faq;
import com.bfr.telinksemifourm.shared.model.TopicTag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Transactional
public class FaqService implements IFaqService {
@Autowired
private FaqMapper faqMapper;
@Autowired
private FaqSubjectMapper faqSubjectMapper;
@Autowired
private ISystemConfigService systemConfigService;
@Autowired
private ElasticSearchPlugin searchPlugin;
@Override
public MyPage<Map<String, Object>> selectPageByMap(Integer pageNo, Map map) {
MyPage<Map<String, Object>> iPage = new MyPage<>(pageNo, Integer.parseInt((String) systemConfigService
.selectAllConfig().get("page_size")));
return faqMapper.selectPageByMap(iPage, map);
}
@Override
public Faq selectById(Integer id) {
return faqMapper.selectById(id);
}
@Override
public void saveEntity(Faq faq) {
faqMapper.insert(faq);
}
@Override
public boolean saveFaq(Faq faq) {
if (faqMapper.insert(faq) > 0){
QueryWrapper<Faq> wrapper = new QueryWrapper();
wrapper.lambda().eq(Faq::getTitle, faq.getTitle());
faq = faqMapper.selectOne(wrapper);
Map<String, Object> map = new HashMap<>();
map.put("type", "faq");
map.put("id", faq.getId());
map.put("title", faq.getTitle());
map.put("content", faq.getContent());
map.put("comment", "");
map.put("tagList.id", "");
map.put("tagList.name", "");
searchPlugin.saveFaqEs(map);
return true;
}
return false;
}
@Override
public boolean updateFaq(Faq faq) {
if (faqMapper.updateById(faq) > 0){
Map<String, Object> map = new HashMap<>();
map.put("type", "faq");
map.put("id", faq.getId());
map.put("title", faq.getTitle());
map.put("content", faq.getContent());
searchPlugin.updateFaqEs(map);
return true;
}
return false;
}
@Override
public boolean deleteFaq(Integer id) {
if (faqMapper.deleteById(id) > 0){
Map<String, Object> map = new HashMap<>();
map.put("id", id);
searchPlugin.deleteFaqEs(map);
return true;
}
return false;
}
@Override
public void deleteById(Integer id) {
faqMapper.deleteById(id);
}
@Override
public List<String> selectSubjectByGroup() {
return faqSubjectMapper.selectSubjectByGroup();
}
}
header.ftl:
<#macro header page_tab>
<section class="hero head-top">
<div class="hero-head">
<button class="dis-btn" id="dis-btn" value="展开">
<p></p>
<p></p>
</button>
<div class="grid">
<div class="grid-left" style="min-width: 150px;">
<a href="/" style="display: inline-block;background: url(/static/theme/default/libs/img/logo.svg) no-repeat;
width: 100%;height: 70px;"><#--${site.name!}-->
</a>
</div>
<div class="grid-right" id="grid-cnt">
<#--<div class="column is-narrow">
<span class=" <#if page_tab == "index">active</#if>">
<a href="/" class="">
<i class="fa fa-home"></i> ${i18n.getMessage("index")}
</a>
</span>
<span class=" <#if page_tab == "tags">active</#if>">
<a href="/tags" class="">
<i class="fa fa-tags"></i> ${i18n.getMessage("tag")}
</a>
</span>
</div>-->
<div class="head-input" style="min-width: 250px;" >
<form class="field has-addons" action="/searchpage" onsubmit="return false">
<div class="control is-expanded" >
<input class="input" type="search" name="keyword" placeholder="" id="searchin" value="${keyword!}" aria-label="Search" autocomplete="off" onfocus="showpan1()" onBlur="showpan2()" />
<div class="serch-panel">
<div class="serch-panel-sel">
<!--
<div class="serch-panel-sel-left">
<a class="serch-sel" data-key="group" id="search-group">group</a>
<a class="serch-sel" data-key="content" id="search-content">content</a>
</div>
-->
<div class="serch-panel-sel-right">
<a onclick="searchpage()">${i18n.getMessage("advancedSearch")}</a>
</div>
</div>
<div id="ro-ria3" class="serch-panel-sel">
<#-- <a onclick="searchpage()">${i18n.getMessage("searchTypeTag")}</a>-->
</div>
<div class="serch-cnt">
<div class="serch-res">
<div class="res-user">
<!--
<div>
<i id="res-user" class="fas fa-lock">ewq</i>
</div>
-->
<span>${i18n.getMessage("searchTypeTopic")}</span>
</div>
<!--
<div class="res-body">
<div class="res-title">
</div>
<div class="res-cnt">
</div>
</div>
-->
<div class="res-info" id="ro-ria1">
<!--
<div class="res-info-area">12312312312313123士大夫士大夫士大夫第1</div>
<div class="res-info-area">12312312312313123士大夫士大夫士大夫第1</div>
-->
<!--
<span class="res-info-time">1231231231231231士大夫士大夫士大夫第2</span>
-->
</div>
</div>
<hr style="background-color: #cacaca;">
<div class="serch-res">
<div class="res-user">
<span>${i18n.getMessage("searchTypeFaq")}</span>
</div>
<div class="res-info" id="ro-ria2"></div>
</div>
</div>
</div>
</div>
<div class="control">
<#--<button class="button is-link" type="submit">${i18n.getMessage("search")}</button>-->
<button class="button" type="submit" style="background-color: #92f0a1;"><i class="fas fa-search"></i></button>
</div>
</form>
</div>
<#if _user??>
<div class="grid-item-child-v2">
<div class="grid-right-child2">
<a href="/faq">
<i class="far fa-question-circle"></i>FAQ
</a>
<a href="/resource">
<i class="far fa-question-circle"></i>Resource
</a>
</div>
<div class="field" style="display: grid;margin: 0;">
<div class="control">
<div class="select is-small">
<select id="lang-sel">
<option value="en">English</option>
<option value="zh">简体中文</option>
</select>
</div>
</div>
</div>
<span class=" <#if page_tab == "notification">active</#if>">
<a href="/notifications" class="">
<i class="fas fa-bell border-circle"></i>
<span id="n_count" class="red-dot hide"></span><#--${i18n.getMessage("notification")}-->
</a>
</span>
<span class=" <#if page_tab == "user">active</#if>">
<a href="/user/${_user.username}/" class="">
<i class="fa fa-user border-circle" style="border-color: white"></i> <#--${_user.username}-->
</a>
</span>
<#--<span class=" <#if page_tab == "settings">active</#if>">
<a href="/settings" class="">
<i class="fa fa-cog"></i> ${i18n.getMessage("setting")}
</a>
</span>-->
<span>
<a href="javascript:if(confirm('Logout the system?'))window.location.href='/logout'" class="">
<i class="fa fa-sign-out"></i><#-- ${i18n.getMessage("logout")}-->
</a>
</span>
</div>
<#else>
<div class="grid-item-child">
<div class="grid-right-child2">
<a href="/faq">
<i class="far fa-question-circle"></i>FAQ
</a>
<#--<a href="/resource">Resource</a>-->
</div>
<span class="<#if page_tab == "login">active</#if>">
<a href="/login" >
<i class="fal fa-sign-in"></i>${i18n.getMessage("login")}
</a>
</span>
<span class=" <#if page_tab == "register">active</#if>">
<a href="/registerone" >
<i class="fal fa-user-plus"></i>${i18n.getMessage("register")}
</a>
</span>
<div class="field">
<div class="control">
<div class="select is-small">
<select id="lang-sel">
<option value="en">English</option>
<option value="zh">简体中文</option>
</select>
</div>
</div>
</div>
</div>
</#if>
</div>
</div>
</div>
</section>
<script src="/static/theme/default/js/blockUI.js"></script>
<script>
//遮罩默认设定
$.blockUI.defaults.message = null;
$(document).ajaxStop($.unblockUI);
$(document).ready(function(){
var fourmLang = localStorage.getItem("fourmLang");
if (fourmLang) {
$("#lang-sel").val(fourmLang);
}
$("#dis-btn").click(function() {
$("#grid-cnt").toggle(500,function () {
if(document.getElementById("grid-cnt").style.display=="block"){
document.getElementById("grid-cnt").style.display="grid"
}
});//显示与隐藏的动作切换时间为500ms
});
});
var searchin = document.getElementById('searchin');
//全局的一个变量,可被每次触发的事件函数重新修改赋值
var lastTimeStamp = 0;
searchin.addEventListener('keyup',function(event){
//标记当前事件函数的时间戳
lastTimeStamp = event.timeStamp;
//800ms后比较二者是否还相同(因为只要还有事件触发,lastTimeStamp就会被改写,不再是当前事件函数的时间戳)
setTimeout(function(){
if(lastTimeStamp == event.timeStamp){
console.log("------ lastTimeStamp -- :" + lastTimeStamp);
var searchLen = $("#searchin").val().trim();
check(searchLen);
};
},800);
},false);
function showpan1() {
$(".serch-panel")[0].style.display="grid";
var searchLen = $("#searchin").val().trim();
if (searchLen == ''){
var rrl1 = $("#ro-ria1");
var rrl2 = $("#ro-ria2");
var rrl3 = $("#ro-ria3");
rrl1.empty();
rrl2.empty();
rrl3.empty();
return;
}
check(searchLen);
}
function showpan2() {
setTimeout(function () {
$(".serch-panel")[0].style.display="none";
},200)
}
function check(searchLen) {
console.log("---showPan()---");
$.post({
url: "/api/es/pageList",
data: {"keyword":searchLen},
dataType: 'json',
success: function (data) {
console.log(data);
if (data.code === 200) {
var rrl1 = $("#ro-ria1");
var rrl2 = $("#ro-ria2");
var rrl3 = $("#ro-ria3");
rrl1.empty();
rrl2.empty();
rrl3.empty();
var str1 = "";
var str2 = "";
var str3 = "";
var result = data.detail.records;
for(var i = 0 ; i < result.length ; i++){
if(result[i].type == 'topicTag'){
str1 = str1 + '<div class="res-info-area" idx = " '+ result[i].id + '"><a href="/topic/'+ result[i].id +'">'+ result[i].title +'</a></div>';
}
if(result[i].type == 'faq'){
str2 = str2 + '<div class="res-info-area" idx = " '+ result[i].id + '"><a href="/faq/'+ result[i].id +'">'+ result[i].title +'</a></div>';
}
if(result[i].type == 'tag'){
str3 = str3 + '<a style="margin-right: 1rem;" href="/topic/tag/'+ result[i].name +'">'+ result[i].name +'</a>';
}
}
rrl1.append(str1);
rrl2.append(str2);
rrl3.append(str3);
} else {
}
}
})
}
// $(".serch-panel").hover(
// function () {
// $(".serch-panel")[0].style.display="grid"
// },
// function () {
// $(".serch-panel")[0].style.display="none"
// }
// )
$("#lang-sel").change(function() {
localStorage.setItem("fourmLang", $("#lang-sel option:selected").val());
window.location.href = '/changeLanguage?lang=' + $("#lang-sel option:selected").val();
});
function searchpage() {
var searchin = $("#searchin").val();
window.location.href = "/searchpage?keyword=" + searchin;
}
/*$(document).keydown(function(event){
switch(event.keyCode){
case 13:return false;
}
});
$(function() {
$("input").keypress(function (e) {
var keyCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
if (keyCode == 13) {
for (var i = 0; i < this.form.elements.length; i++) {
if (this == this.form.elements[i]) break;
}
i = (i + 1) % this.form.elements.length;
this.form.elements[i].focus();
return false;
} else {
return true;
}
}
);
});*/
</script>
</#macro>