许鹏程
2025-01-20 d334dfae15726489656d582c8f9356ef02d0686a
src/main/java/com/product/lucene/service/LuceneService.java
@@ -12,6 +12,7 @@
import com.product.lucene.util.FileUtils;
import com.product.util.BaseUtil;
import com.product.util.UnifySQLSymbol;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.IndexWriter;
@@ -32,6 +33,9 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * 文件检索
@@ -50,11 +54,11 @@
   @Autowired
   private SearcherManager searcherManager;
   /**
    * 创建索引
    *
    *
    * @param fse
    * @throws IOException
    */
@@ -63,7 +67,7 @@
      File file = (File) fse.getObject("file"); // 获取附件
      // 获取全文检索配置
      FieldSetEntity fseConfig = baseDao.getFieldSetEntityByFilter(CmnConst.PRODUCT_SYS_DOCUMENT_SEARCH, "function_uuid=?", new Object[] { function_uuid }, false);
      FieldSetEntity fseConfig = baseDao.getFieldSetEntityByFilter(CmnConst.PRODUCT_SYS_DOCUMENT_SEARCH, "function_uuid=?", new Object[]{function_uuid}, false);
      if (fseConfig == null)
         return;
      String table_uuid = fseConfig.getString(CmnConst.TABLE_NAME);
@@ -109,7 +113,7 @@
   /**
    *    文档检索
    *
    *
    * @param fse
    * @return
    * @throws Exception
@@ -118,22 +122,21 @@
   public JSONObject searchProduct(FieldSetEntity fse) throws Exception {
      // 刷新IndexSearcher实例
      searcherManager.maybeRefresh();
      // 获取安全的IndexSearcher实例
      // 创建IndexSearcher实例
      IndexSearcher indexSearcher = null;
      // 文档信息汇总
      List<JSONObject> jsonTotal = new ArrayList<>();
      List<JSONObject> listJsonFile = new ArrayList<>();
      Long totalCount = 0L;
      try {
         // 获取安全的IndexSearcher实例
         indexSearcher = searcherManager.acquire();
         // 获取条件查询结果
         Query finalQuery = searchFilterParse(fse);
         // 获取高亮匹配器
         Highlighter highlighter = highlighterParse(finalQuery);
         // 分页查询文档
         TopDocs topDocs = searchByPage(fse.getInteger(CoreConst.CPAGE), fse.getInteger(CoreConst.PAGESIZE),
               indexSearcher, finalQuery);
@@ -143,52 +146,72 @@
         for (int i = 0; i < hits.length; i++) {
            // 获取检索命中的文档信息
            Document doc = indexSearcher.doc(hits[i].doc);
            String fileUUID = doc.get(CoreConst.UUID);
            String functionUUID = doc.get(CoreConst.FUNCTION_UUID);
            String fileName = doc.get(CmnConst.FILE_NAME);
            String fileContent = doc.get(CmnConst.FILE_CONTENT);
            JSONObject json = new JSONObject();
            if (!StringUtils.isEmpty(functionUUID)) {
               getConfig(json, functionUUID, fileUUID);
            JSONObject jsonFile = new JSONObject();
            jsonFile.put(CmnConst.FILE_UUID, doc.get(CoreConst.UUID));
            jsonFile.put(CoreConst.FUNCTION_UUID, doc.get(CoreConst.FUNCTION_UUID));
            if (!StringUtils.isEmpty(doc.get(CoreConst.FUNCTION_UUID))) {
               FieldSetEntity fs = BaseUtil.getSingleInfoByCache("所有功能", new String[]{jsonFile.getString(CoreConst.FUNCTION_UUID)});
               if (FieldSetEntity.isEmpty(fs)) {
                  //找不到功能重新根据表名查找
                  //清空
                  jsonFile.remove(CoreConst.FUNCTION_UUID);
               }
            }
            json.put(CoreConst.FUNCTION_UUID, doc.get(CoreConst.FUNCTION_UUID));
            if (StringUtils.isEmpty(jsonFile.get(CoreConst.FUNCTION_UUID))) {
               //查询功能信息
               String sql = "SELECT * FROM product_sys_functions where table_uuid =(select uuid from product_sys_datamodel_table where table_name=?) limit 1";
               FieldSetEntity fseFunction = baseDao.getFieldSetBySQL(sql, new String[]{doc.get(CmnConst.TABLE_NAME)}, false);
               if (fseFunction != null) {
                  jsonFile.put(CoreConst.FUNCTION_UUID, fseFunction.getString(CoreConst.UUID));
                  //回写功能信息到文档信息中
                  doc.add(new StoredField(CoreConst.FUNCTION_UUID, fseFunction.getString(CoreConst.UUID)));
                  indexWriter.updateDocument(new Term(CoreConst.UUID, doc.get(CoreConst.UUID)), doc);
               }
            }
            // 文件名增加高亮显示
            String fileName = doc.get(CmnConst.FILE_NAME);
            String file_name = highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_NAME,
                  CmnConst.FILE_NAME);
                  fileName);
            if (StringUtils.isEmpty(file_name)) {
               file_name = fileName;
            }
            // 文件内容增加高亮显示
            String fileContent = doc.get(CmnConst.FILE_CONTENT);
            String file_content = highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_CONTENT,
                  fileContent);
            if (StringUtils.isEmpty(file_content)) {
               file_content = fileContent;
            }
            json.put("file_uuid", fileUUID);
            json.put("function_uuid", functionUUID);
            json.put(CmnConst.FILE_NAME, file_name);
            json.put(CmnConst.FILE_CONTENT, file_content);
            jsonTotal.add(json);
            jsonFile.put(CmnConst.FILE_NAME, file_name);
            jsonFile.put(CmnConst.FILE_CONTENT, file_content);
            listJsonFile.add(jsonFile);
         }
      } finally {
         // 关闭实例资源
         searcherManager.release(indexSearcher);
      }
      // 创建返回信息对象
      JSONObject jsonReturn = new JSONObject();
      getFileInfo(jsonTotal);
      jsonReturn.put(CmnConst.TOTALCOUNT, totalCount);
      jsonReturn.put(CmnConst.DATA, jsonTotal);
      if (listJsonFile.size() > 0) {
         // 获取文档展示信息
         getFileInfo(listJsonFile);
         jsonReturn.put(CmnConst.DATA, listJsonFile);
      }
      return jsonReturn;
   }
   /**
    *    解析查询条件
    * @param fse
    * @return
    * @throws ParseException
    */
   public Query searchFilterParse(FieldSetEntity fse) throws ParseException   {
   public Query searchFilterParse(FieldSetEntity fse) throws ParseException {
      // 上传人
      String uploadUser = fse.getString("upload_user");
      String startDate = fse.getString("start_date");
@@ -197,7 +220,7 @@
      // 创建查询条件
      BooleanQuery.Builder boolQuery = new BooleanQuery.Builder();
      // 上传人过滤
      if (!BaseUtil.strIsNull(uploadUser)) {
         Query uploaderQuery = new TermQuery(new Term("upload_user", uploadUser));
@@ -220,13 +243,13 @@
      // 关键词过滤
      if (!BaseUtil.strIsNull(searchKey)) {
         QueryParser queryParser = new MultiFieldQueryParser(
               new String[] { CmnConst.FILE_NAME, CmnConst.FILE_CONTENT }, new SmartChineseAnalyzer());
               new String[]{CmnConst.FILE_NAME, CmnConst.FILE_CONTENT}, new SmartChineseAnalyzer());
         Query query = queryParser.parse(searchKey);
         boolQuery.add(query, BooleanClause.Occur.MUST);
      }
      return boolQuery.build();
   }
   /**
    *    查询文件高亮匹配器
    * @param finalQuery
@@ -235,7 +258,7 @@
   public Highlighter highlighterParse(Query finalQuery) {
      // 高亮格式
      SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(CmnConst.HIGHLIGHT_BEFORE,
         CmnConst.HIGHLIGHT_AFTER);
            CmnConst.HIGHLIGHT_AFTER);
      // 高亮匹配器
      Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(finalQuery));
      Fragmenter fragmenter = new SimpleFragmenter(100);
@@ -243,24 +266,26 @@
      return highlighter;
   }
   /**
    *    获取文档展示信息
    * @param listJsonFile
    */
   public void getFileInfo(List<JSONObject> listJsonFile) {
        StringBuilder sql = new StringBuilder();
      for (int i = 0; i < listJsonFile.size(); i++) {
         JSONObject jsonFile = listJsonFile.get(i);
         if (i > 0) {
            sql.append("UNION ALL \n");
         }
         sql.append("SELECT \n");
         sql.append(" A.uuid,A.attachment_data_table,A.attachment_data_field,D.user_name AS upload_user,A.created_utc_datetime AS upload_date, \n");
         sql.append(" B.org_fields,B.user_fields,B.title_field,B.time_field \n");
         sql.append("FROM product_sys_attachments A \n");
         sql.append("LEFT JOIN product_sys_document_search B ON B.table_name = A.attachment_data_table \n");
         sql.append("LEFT JOIN product_sys_functions C ON C.uuid = B.function_uuid \n");
         sql.append("LEFT JOIN product_sys_users D ON D.user_id = A.created_by \n");
         sql.append("WHERE A.uuid = '").append(jsonFile.get("file_uuid")).append("' \n");
      }
      DataTableEntity dtConfig = baseDao.listTable(sql.toString(), new Object[] {});
      StringBuilder sql = new StringBuilder();
      Set<String> fileUuids = listJsonFile.stream().map(jsonFile -> jsonFile.getString(CmnConst.FILE_UUID)).collect(Collectors.toSet());
      sql.append("SELECT \n");
      sql.append(" A.uuid,A.attachment_data_table,A.attachment_data_field,DATE_FORMAT(A.created_utc_datetime,'%Y-%m-%d') AS upload_date, \n");
      sql.append(" B.org_fields,B.user_fields,B.title_field,B.time_field, \n");
      sql.append(" C.uuid AS function_uuid,C.function_name,D.user_name AS upload_user ");
      sql.append("FROM product_sys_attachments A \n");
      sql.append(" JOIN product_sys_datamodel_table as " + UnifySQLSymbol.getSymbol("table") + " on A.attachment_data_table=" + UnifySQLSymbol.getSymbol("table") + ".table_name \n");
      sql.append("LEFT JOIN product_sys_document_search B ON B.table_name = " + UnifySQLSymbol.getSymbol("table") + ".uuid \n");
      sql.append("LEFT JOIN product_sys_functions C ON C.uuid = B.function_uuid \n");
      sql.append("LEFT JOIN product_sys_users D ON D.user_id = A.created_by \n");
      sql.append("WHERE ").append(BaseUtil.buildQuestionMarkFilter("A.uuid", fileUuids.size(), true));
      // 获取文档附件、配置信息
      DataTableEntity dtConfig = baseDao.listTable(sql.toString(), fileUuids.toArray());
      if (!BaseUtil.dataTableIsEmpty(dtConfig)) {
         StringBuilder sqlService = new StringBuilder();
         for (int i = 0; i < dtConfig.getRows(); i++) {
@@ -271,31 +296,47 @@
            sqlService.append("SELECT \n");
            sqlService.append(" A.uuid, \n");
            sqlService.append(" B.uuid AS service_uuid, \n");
            sqlService.append(" A.upload_user, A.upload_date, \n");
            sqlService.append(" A.upload_user, A.upload_date, A.function_uuid, A.function_name, \n");
            sqlService.append(" ").append(fseConfig.getString(CmnConst.TITLE_FIELD)).append(" AS service_title, \n");
            sqlService.append(" ").append(fseConfig.getString(CmnConst.TIME_FIELD)).append(" AS service_time \n");
            sqlService.append("FROM ( \n");
            sqlService.append(" SELECT \n");
            sqlService.append("  '").append(fseConfig.getString(CoreConst.UUID)).append("' AS uuid, \n");
            sqlService.append("  '").append(fseConfig.getString(CmnConst.UPLOAD_USER)).append("' AS upload_user, \n");
            sqlService.append("  '").append(fseConfig.getString(CmnConst.UPLOAD_DATE)).append("' AS upload_date \n");
            sqlService.append("  '").append(fseConfig.getString(CmnConst.UPLOAD_DATE)).append("' AS upload_date, \n");
            sqlService.append("  '").append(fseConfig.getString(CoreConst.FUNCTION_UUID)).append("' AS function_uuid, \n");
            sqlService.append("  '").append(fseConfig.getString(CoreConst.FUNCTION_NAME)).append("' AS function_name \n");
            sqlService.append(") A \n");
            sqlService.append("LEFT JOIN ").append(fseConfig.getString("attachment_data_table")).append(" B \n");
            sqlService.append("LEFT JOIN ").append(fseConfig.getString(CmnConst.ATTACHMENT_DATA_TABLE)).append(" B \n");
            sqlService.append("ON B.").append(fseConfig.getString(CmnConst.ATTACHMENT_DATA_FIELD)).append(" LIKE '%").append(fseConfig.getUUID()).append("%' \n");
         }
         DataTableEntity dtService = baseDao.listTable(sqlService.toString(), new Object[] {});
         // 获取文档业务数据信息
         DataTableEntity dtService = baseDao.listTable(sqlService.toString(), new Object[]{});
         if (!BaseUtil.dataTableIsEmpty(dtService)) {
            Map<String, FieldSetEntity> map = dtService.getData().stream()
                  .collect(Collectors.toMap(
                        fseService -> fseService.getUUID(),
                        fseService -> fseService
                  ));
            for (int i = 0; i < listJsonFile.size(); i++) {
               JSONObject jsonFile = listJsonFile.get(i);
               FieldSetEntity fseService = map.get(jsonFile.get(CmnConst.FILE_UUID));
               if (fseService != null) {
                  jsonFile.put(CoreConst.FUNCTION_NAME, fseService.getString(CoreConst.FUNCTION_NAME));
                  jsonFile.put(CoreConst.FUNCTION_UUID, fseService.getString(CoreConst.FUNCTION_UUID));
                  jsonFile.put(CmnConst.UPLOAD_USER, fseService.getString(CmnConst.UPLOAD_USER));
                  jsonFile.put(CmnConst.UPLOAD_DATE, fseService.getString(CmnConst.UPLOAD_DATE));
                  jsonFile.put(CmnConst.SERVICE_UUID, fseService.getString(CmnConst.SERVICE_UUID));
                  jsonFile.put(CmnConst.SERVICE_TITLE, fseService.getString(CmnConst.SERVICE_TITLE));
                  jsonFile.put(CmnConst.SERVICE_TIME, fseService.getString(CmnConst.SERVICE_TIME));
               }
            }
         }
      }
   }
   /**
    * 获取文档检索配置信息(权限,功能名称,跳转按钮)
    *
    * @param json          检索文件对应信息
    * @param function_uuid 所属功能UUID
    * @param service_uuid  附件UUID
    */
   public void getConfig(JSONObject json, String function_uuid, String uuid) {
   public JSONObject permission(String uuid, String function_uuid) {
      JSONObject json = new JSONObject();
      StringBuilder searchConfigSql = new StringBuilder();
      searchConfigSql.append("SELECT \n");
      searchConfigSql.append(" A.uuid,A.function_uuid,A.function_button_uuid,A.table_name, \n");
@@ -307,15 +348,17 @@
      searchConfigSql.append("WHERE A.function_uuid=?");
      // 获取文档检索配置(功能,跳转按钮)
      FieldSetEntity fseConfig = baseDao.getFieldSetEntityBySQL(searchConfigSql.toString(), new Object[] { function_uuid },
            false);
      FieldSetEntity fseConfig = baseDao.getFieldSetEntityBySQL(searchConfigSql.toString(), new Object[]{function_uuid}, false);
      if (fseConfig != null) {
         // 获取跳转按钮 并 判断跳转权限
         String buttonName = fseConfig.getString(CoreConst.BUTTON_NAME);
         if (BaseUtil.strIsNull(buttonName)) {
            json.put(CmnConst.IS_PERSSION, 2);
            json.put(CmnConst.IS_PERSSION, 1);
            json.put("permission_msg", "数据配置-该文档配置不支持跳转");
            return json;
         } else {
            json.put(CmnConst.IS_PERSSION, 0);
            json.put(CmnConst.SKIPBUTTON, fseConfig.getString(CoreConst.BUTTON_NAME));
         }
@@ -325,7 +368,6 @@
         // 获取附件信息,结合数据权限字段,生成原数据的过滤SQL
         FieldSetEntity fseAttachment = baseDao.getFieldSetEntity(CmnConst.PRODUCT_SYS_ATTACHMENTS, uuid, false);
         baseDao.loadPromptData(fseAttachment);
         if (fseAttachment != null) {
            StringBuilder filter = new StringBuilder();
            filter.append(fseAttachment.getString(CmnConst.ATTACHMENT_DATA_FIELD));
@@ -350,21 +392,19 @@
            // 获取原数据
            FieldSetEntity fseService = baseDao.getFieldSetEntityByFilter(
                  fseAttachment.getString(CmnConst.ATTACHMENT_DATA_TABLE), filter.toString(),
                  new Object[] { uuid }, false);
                  new Object[]{uuid}, false);
            if (fseService == null) {
               // 获取无权限过滤的原数据
               FieldSetEntity fseService2 = baseDao.getFieldSetEntityByFilter(
                     fseAttachment.getString(CmnConst.ATTACHMENT_DATA_TABLE),
                     fseAttachment.getString(CmnConst.ATTACHMENT_DATA_FIELD) + "=?", new Object[] { uuid },
                     fseAttachment.getString(CmnConst.ATTACHMENT_DATA_FIELD) + "=?", new Object[]{uuid},
                     false);
               if (fseService2 == null) {
                  json.put(CmnConst.TITLE, "业务数据不存在");
                  json.put(CmnConst.IS_PERSSION, 1);
                  json.put("permission_msg", "数据异常-业务数据不存在");
                  json.put(CmnConst.IS_PERSSION, 2);
               } else {
                  json.put(CmnConst.SERVICE_UUID, fseService2.getString(CoreConst.UUID));
                  json.put(CmnConst.DATE_TIME, fseService2.getString(fseConfig.getString(CmnConst.TIME_FIELD)));
                  json.put(CmnConst.TITLE, fseService2.getString(fseConfig.getString(CmnConst.TITLE_FIELD)));
                  json.put(CmnConst.IS_PERSSION, 0);
                  json.put("permission_msg", "数据策略-此文档您没有查看权限");
                  json.put(CmnConst.IS_PERSSION, 3);
               }
            } else {
@@ -373,36 +413,35 @@
               if ("e4fa2c88-88a4-4ef4-9020-ebbe0440b4cf".equals(function_uuid)) {
                  if (!SpringMVCContextHolder.getCurrentUserId()
                        .equals(fseService.getString(CoreConst.CREATED_BY))) {
                     json.put(CmnConst.IS_PERSSION, 0);
                     json.put("permission_msg", "文档权限策略-此文档您没有查看权限");
                     json.put(CmnConst.IS_PERSSION, 4);
                  }
               } else if ("01513ff6-c758-4384-b861-e58dfe146fdd".equals(function_uuid)) {
                  // 获取单位文档所属目录权限
                  FieldSetEntity fseDirectRight = baseDao.getFieldSetByFilter(
                        CmnConst.PRODUCT_OA_DIRECTORY_RIGHTS, "directory_uuid=?",
                        new Object[] { fseService.getString(CmnConst.DIRECTORY_UUID) }, false);
                        new Object[]{fseService.getString(CmnConst.DIRECTORY_UUID)}, false);
                  if (fseDirectRight == null) {
                     json.put(CmnConst.IS_PERSSION, 0);
                     json.put("permission_msg", "文档权限策略-此文档您没有查看权限");
                     json.put(CmnConst.IS_PERSSION, 4);
                  } else {
                     boolean succ = BaseUtil.multipleTypeConcat(fseDirectRight.getString(CmnConst.STORAGE_UUID),
                           SpringMVCContextHolder.getCurrentUserId());
                     if (!succ) {
                        json.put(CmnConst.IS_PERSSION, 0);
                        json.put("permission_msg", "文档权限策略-此文档您没有查看权限");
                        json.put(CmnConst.IS_PERSSION, 4);
                     }
                  }
               }
               json.put(CmnConst.SERVICE_UUID, fseService.getString(CoreConst.UUID));
               json.put(CmnConst.DATE_TIME, fseService.getString(fseConfig.getString(CmnConst.TIME_FIELD)));
               json.put(CmnConst.TITLE, fseService.getString(fseConfig.getString(CmnConst.TITLE_FIELD)));
            }
            json.put(CoreConst.FUNCTION_NAME, fseConfig.getString(CoreConst.FUNCTION_NAME));
            json.put(CoreConst.CREATED_BY, fseAttachment.getString(CoreConst.CREATED_BY));
         }
      }
      return json;
   }
   /**
    * 文件检索查询分页
    *
    *
    * @param cpage    当前页
    * @param pagesize 每页大小
    * @param searcher 查询器
@@ -430,7 +469,7 @@
   /**
    * 根据附件uuid删除索引
    *
    *
    * @param uuid
    * @throws IOException
    */