ES做个笔记

后端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>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值