package com.product.admin.service; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.product.admin.config.CmnConst; import com.product.admin.config.SystemCode; import com.product.core.config.CoreConst; import com.product.core.config.ErrorCode; import com.product.util.BaseUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import com.product.common.lang.StringUtils; import com.product.core.cache.DataPoolCacheImpl; import com.product.core.dao.BaseDao; import com.product.core.entity.DataTableEntity; import com.product.core.entity.FieldMetaEntity; import com.product.core.entity.FieldSetEntity; import com.product.core.entity.SQLEntity; import com.product.core.exception.BaseException; import com.product.core.permission.PermissionService; import com.product.core.service.support.AbstractBaseService; import com.product.core.util.SQLParseUtil; import com.product.core.util.SystemParamReplace; /** * 高级参照,查询字段中的字段如果是国际化字段,不能重复 * * @author shicf */ @Component public class PromptService extends AbstractBaseService { /** * 数据查询 ,spring 注入 */ @Autowired public BaseDao baseDao; @Autowired PermissionService permissionService; /** * 获取高级参照条件中的字段key * * @param promptName * @return * @author cheng */ public Set getPromptFilterKey(String promptName) { DataTableEntity dt = DataPoolCacheImpl.getInstance().getCacheData("高级参照配置信息", new String[]{promptName}); if (dt != null && dt.getRows() > 0) { FieldSetEntity fs = dt.getFieldSetEntity(0); if (FieldSetEntity.isEmpty(fs)) { return null; } String promptFilter = fs.getString("filter"); return ReUtil.findAll("(\\~)([\\w]+)(~)", promptFilter, 2, new HashSet<>()); } return null; } public Object getPromptValue(FieldSetEntity fse) throws BaseException { String prompt_name = fse.getString("prompt_name"); // 只有手机端才上传 String language_code = fse.getString(CoreConst.SYSTEM_LANGUAGE_CODE); DataTableEntity dt = DataPoolCacheImpl.getInstance().getCacheData("高级参照配置信息", new String[]{prompt_name}); if (dt != null && dt.getRows() > 0) { FieldSetEntity fs = dt.getFieldSetEntity(0); if (fs != null) { String tableName[] = SQLParseUtil.parsePromptSourceTable(fs.getString(CmnConst.SOURCE_TABLE)); StringBuilder uuids = returnUuids(tableName); String filterbuf = returnFilterbuf(fs, fse); DataTableEntity src = returnData(fs, fse, filterbuf, uuids, tableName); if ("2".equals(fs.getString("display_type")) && !StringUtils.isEmpty(fs.getString("code_field")) && !StringUtils.isEmpty(fs.getString("parent_code_field"))) { return BaseUtil.dataTableToTreeData(src, "prompt_s_code_field", "prompt_s_parent_code_field", null, false); } // 设置高级参照的字段别名 setAlias(src.getMeta(), fs); DataTableEntity data = baseDao.listInternationDataTable(src, language_code); baseDao.loadPromptData(data); return data; } } throw new BaseException(SystemCode.PROMPT_NO_EXIST.getValue(), SystemCode.PROMPT_NO_EXIST.getText()); } private StringBuilder returnUuids(String tableName[]) { StringBuilder uuids = new StringBuilder(); if (tableName.length == 1) { uuids.append(",uuid"); } else { for (int c = 0; c < tableName.length; c++) { String tbas[] = tableName[c].trim().split(" "); if (tbas.length < 2) { throw new BaseException(ErrorCode.SYSTEM_PROMPT_ALIAS_ERROR.getValue(), ErrorCode.SYSTEM_PROMPT_ALIAS_ERROR.getText()); } // 自动添加每个表的uuid uuids.append(",").append(tbas[tbas.length - 1]).append(".uuid uuid").append(c); } } return uuids; } /** * 返回高级参照sql条件执行DataTableEntity * * @param fs * @param fse * @param filterbuf * @param uuids * @param tableName * @return */ private DataTableEntity returnData(FieldSetEntity fs, FieldSetEntity fse, String filterbuf, StringBuilder uuids, String tableName[]) { SQLEntity sql = new SQLEntity(); sql.setTableNames(fs.getString(CmnConst.SOURCE_TABLE)); sql.setFilter(filterbuf); if (fs.getString("select_fields") != null) { // 自动添加uuid,方便 国际化查询 String select_fields = fs.getString("select_fields"); if ("2".equals(fs.getString("display_type"))) { if (uuids.length() > 0) { uuids.append(" ,"); } uuids.append(" " + fs.getString("code_field") + " as prompt_s_code_field, " + fs.getString("parent_code_field") + " as prompt_s_parent_code_field"); } sql.setFields((select_fields + uuids).split(",")); } sql.setOrderBy(fs.getString("orderby")); // 系统参数设置 if (null == fse.getInteger(CoreConst.CPAGE) || null == fse.getInteger(CoreConst.PAGESIZE)) { fse.setValue(CoreConst.PAGESIZE, Integer.MAX_VALUE); fse.setValue(CoreConst.CPAGE, 1); } String sqlstr = SQLParseUtil.createSelectSQL(sql); if (sqlstr != null && tableName.length > 1) { // 多个表 sqlstr = "select * from (" + sqlstr + " ) b "; } return baseDao.listTable(sqlstr, sql.getParas(), fse.getInteger(CoreConst.PAGESIZE), fse.getInteger(CoreConst.CPAGE)); } /** * 获取高级参照表头字段描述 * 用于高级参照选择模态窗 * * @param metaEntity * @return */ public JSONArray getPromptFieldDesc(FieldMetaEntity metaEntity) { JSONArray arry = new JSONArray(); if (metaEntity == null || metaEntity.getReverse_aliasField() == null) { return arry; } Map aliasField = metaEntity.getReverse_aliasField(); for (Map.Entry entry : aliasField.entrySet()) { String key = entry.getKey(); if ("uuid".equals(entry.getKey())) { continue; } if ("view_fields".equals(entry.getKey())) { continue; } if ("value_field".equals(entry.getKey())) { continue; } JSONObject fieldInfo = new JSONObject(); String value = entry.getValue(); if (StringUtils.isEmpty(value)) { continue; } String tableName = value.split("\\.")[0]; String fieldName = value.split("\\.")[1]; DataPoolCacheImpl instance = DataPoolCacheImpl.getInstance(); DataTableEntity tableInfo = instance.getCacheData("所有表信息", new String[]{tableName}); if (tableInfo == null || tableInfo.getFieldSetEntity(0) == null) { return arry; } FieldSetEntity fieldSetEntity = tableInfo.getFieldSetEntity(0); if (fieldSetEntity.getString("uuid") != null) { DataTableEntity fieldsInfo = instance.getCacheData("表字段信息", new String[]{fieldSetEntity.getString("uuid"), fieldName}); if (fieldsInfo != null && fieldsInfo.getFieldSetEntity(0) != null) { FieldSetEntity fs = fieldsInfo.getFieldSetEntity(0); if (fs != null) { DataTableEntity field_description = fs.getSubDataTable("field_show_name"); JSONObject description = new JSONObject(); if (!BaseUtil.dataTableIsEmpty(field_description)) { for (int i = 0; i < field_description.getRows(); i++) { String langaugeCode = field_description.getString(i, CmnConst.LANGUAGE_CODE); description.put(langaugeCode, field_description.getString(i, langaugeCode)); } } fieldInfo.put("prop", key); fieldInfo.put("label", fs.getString("field_show_name")); fieldInfo.put("field_key", tableName + "." + fs.getString("field_name")); arry.add(fieldInfo); } } } } return arry; } /** * 返回高级参照条件 * * @param fs * @param fse * @return */ private String returnFilterbuf(FieldSetEntity fs, FieldSetEntity fse) { StringBuilder filterbuf = new StringBuilder(); String relate_filter = fs.getString("relate_filter"); // 如果是多表,应加上多表关联的条件如:a.x=b.x ---------- 把条件字段进行拆分 // 周杰 2020年12月17日 下午15:27 if (fs.getInteger("is_multiple") == null || fs.getInteger("is_multiple").intValue() == 0 || StringUtils.isEmpty(fs.getString("relate_type"))) { filterbuf.append(relate_filter != null ? relate_filter : ""); } String search_value = fse.getString("~search_value~"); if (!StringUtils.isEmpty(search_value)) { String field = ""; String view_fields = fs.getString("view_fields"); // String value_field = fs.getString("value_field"); String prompt_field = fs.getString("prompt_field"); if (!StringUtils.isEmpty(view_fields)) { field = view_fields; } // if (!StringUtils.isEmpty(value_field)) { // if (!"".equals(field)) { // field += ","; // } // field += value_field; // } boolean mobile = "App".equals(fse.getString("~client_type~")); //app 模糊搜索只搜索view_fields if (!StringUtils.isEmpty(prompt_field) && !mobile) { if (!"".equals(field)) { field += ","; } field += prompt_field; } filterbuf.append(promptAdvancedSearch(search_value, field)); } //如果value_field 不等于空则只查询保存值数据 updatetime 2021年2月22日11:16:42 xupengcheng if (!BaseUtil.strIsNull(fse.getString("value_field"))) { if (filterbuf.length() > 0) { filterbuf = new StringBuilder(); } filterbuf.append(" (" + fs.getString("value_field") + " in ('" + fse.getString("value_field").replace(",", "','") + "')) "); } String filter = fs.getString("filter"); filter = SystemParamReplace.paramReplacePrompt(filter); // 周杰 2020年12月17日 下午15:27 if (!StringUtils.isEmpty(filter)) { // 查询条件中带动态参数值: ~id~ ~name~ filter = replaceFilter(filter, fse); if (filterbuf.length() > 0) { filterbuf.append(" and "); } filterbuf.append("("); filterbuf.append(filter); filterbuf.append(")"); } // 树形结构 returnFilterbufTree(fs, fse, filterbuf); // 特定的字段过滤 returnFilterbufField(fs, filterbuf); return filterbuf.toString(); } public static String promptAdvancedSearch(String searchValue, String fields) { if (StringUtils.isEmpty(searchValue) || StringUtils.isEmpty(fields)) { return ""; } Set fieldSet = new HashSet<>(); fieldSet.addAll(Arrays.asList(fields.split(","))); Iterator iterator = fieldSet.iterator(); StringBuilder filter = new StringBuilder(); while (iterator.hasNext()) { String field = iterator.next(); if (filter.length() > 0) { filter.append(" or "); } filter.append(" (").append(field).append(" like '%").append(searchValue).append("%')"); } filter.insert(0, " ( "); filter.insert(filter.length() - 1, " ) "); return filter.toString(); } /** * 封装特定的字段过滤 * * @param fs * @param filterbuf * @return */ private void returnFilterbufField(FieldSetEntity fs, StringBuilder filterbuf) { if (!StringUtils.isEmpty(fs.getString("org_filter_field")) || !StringUtils.isEmpty(fs.getString("user_filter_field"))) { // 数据过滤 String dataFilter = permissionService.getDataFilter(fs.getString(CmnConst.SOURCE_TABLE), fs.getString("user_filter_field"), fs.getString("org_filter_field")); if (!StringUtils.isEmpty(dataFilter) && filterbuf.length() > 0) { filterbuf.append(" and "); } filterbuf.append(dataFilter); } } /** * 封装高级参照树形结构条件 * * @param fs * @param fse * @param filterbuf * @return */ private void returnFilterbufTree(FieldSetEntity fs, FieldSetEntity fse, StringBuilder filterbuf) { if (fs.getInteger("display_type") != null && fs.getInteger("display_type") == 2) { if (filterbuf.length() > 0) { filterbuf.append(" and "); } if (fs.getInteger("delay_load") == null || fs.getInteger("delay_load") == 0) { filterbuf.append(fs.getString("code_field")).append(" like '") .append((fse.getString("code") == null ? "" : fse.getString("code"))).append("%'"); } else { filterbuf.append(fs.getString("parent_code_field")).append(" ='") .append((fse.getString("code") == null ? "" : fse.getString("code"))).append("'"); } } } /** * 设置高级参照的查询出来的别名字段 * * @param meta 查出来的源数据 * @param configfs 高级参照配置 * @throws BaseException */ private void setAlias(FieldMetaEntity meta, FieldSetEntity configfs) throws BaseException { Map> fielda = configfs.getMeta().getAliasField(); Map> tablea = configfs.getMeta().getAliasTable(); for (Entry> fielda_element : fielda.entrySet()) { List a = fielda_element.getValue(); for (int i = 0; i < a.size(); i++) { meta.addAliasField(fielda_element.getKey(), a.get(i)); } } for (Entry> tablea_element : tablea.entrySet()) { List a = tablea_element.getValue(); for (int i = 0; i < a.size(); i++) { meta.addAliasTable(tablea_element.getKey(), a.get(i)); } } } /** * 对每个字段的别名进行处理 * * @param meta 查询出来的源数据中的meta * @param ctable 配置中的源表 * @param cfield 配置中的字段 * @param alias 配置中的字段别名 * @throws BaseException */ private void processAlias(FieldMetaEntity meta, String ctable, String cfield, String alias) throws BaseException { if (StringUtils.isEmpty(cfield) || meta == null || StringUtils.isEmpty(alias)) return; if (meta.getAliasTable().size() > 0) { int c = cfield.indexOf('.'); if (c > 0) {// 说明有表的别名 String tbas = cfield.substring(0, c);// 表的别名 String fname = cfield.substring(c + 1);// 字段名 Object tableName = meta.getReverse_aliasTable(tbas);// 获取表的真实名称 if (tableName != null && !StringUtils.isEmpty(fname)) { meta.addAliasField(tableName + "." + fname, alias); } else { throw new BaseException(ErrorCode.SYSTEM_PROMPT_FIELD_ALIAS_ERROR.getValue(), ErrorCode.SYSTEM_PROMPT_FIELD_ALIAS_ERROR.getText()); } } else { throw new BaseException(ErrorCode.SYSTEM_PROMPT_FIELD_ALIAS_ERROR.getValue(), ErrorCode.SYSTEM_PROMPT_FIELD_ALIAS_ERROR.getText()); } } else if (!StringUtils.isEmpty(ctable)) { meta.addAliasField(ctable + "." + cfield, alias); } else { meta.addAliasField(cfield, alias); } } /** * @param filter * @return */ private static Map getFilterPara(String filter) { // 按指定模式在字符串查找 String pattern = "~\\w+~"; // 创建 Pattern 对象 Pattern r = Pattern.compile(pattern); // 现在创建 matcher 对象 Matcher m = r.matcher(filter); Map v = new HashMap<>(); // 周杰 2020年12月17日 上午11:16 if (!StringUtils.isEmpty(filter)) { while (m.find()) { String c = m.group(); v.put(c.replace("~", ""), c); } } return v; } private String replaceFilter(String filter, FieldSetEntity fs) throws BaseException { Map f = getFilterPara(filter); if (!f.isEmpty()) { for (Entry entry : f.entrySet()) { if (entry.getKey() != null) { filter = filter.replaceAll(entry.getValue().toString(), "'" + fs.getString(entry.getKey().toString()) + "'"); } } } return filter; } /** * 获取高级参照对应值 * * @param tableName 表 * @param fieldName 字段 * @param showValues,传的是高级参照view_fields的值,多个逗号分隔 * @param ps 业务数据,包含高级参照中需要的动态参数 * @param isCache 是否缓存 * @return 返回的是高级参照 value_field的值,多个逗号分隔 */ public Object getPromptValue(String tableName, String fieldName, String showValues, FieldSetEntity ps, boolean isCache) { if (StringUtils.isEmpty(tableName) || StringUtils.isEmpty(fieldName) || StringUtils.isEmpty(showValues)) { return null; } DataTableEntity dt = DataPoolCacheImpl.getInstance().getCacheData("表字段信息", new String[]{tableName, fieldName}); if (dt == null || dt.getRows() == 0) { return null; } String refer = dt.getFieldSetEntity(0).getString("field_reference"); if (StringUtils.isEmpty(refer)) { return null; } else if ("levelUuid_deptUuid".equals(refer)) { refer = "data-import-dept"; } DataTableEntity rdt = DataPoolCacheImpl.getInstance().getCacheData("高级参照配置信息", new String[]{refer}); if (rdt != null && rdt.getRows() > 0) { //条件中的动态参数替换 String pfilter = returnFilterbuf(rdt.getFieldSetEntity(0), ps); if (isCache) {//先从缓存中取 Object v = DataPoolCacheImpl.getInstance().getPrompt_cache().get(refer + "_" + showValues + "_" + pfilter); if (v != null) return v; } String rtable = rdt.getString(0, "source_table"); String view_fields = rdt.getString(0, "view_fields"); String value_field = rdt.getString(0, "value_field"); int tindex = view_fields.indexOf('.'); String alias = ""; if (tindex > 0) {//说明是多表关联查询,字段前面是表别名 alias = view_fields.substring(0, tindex);//表的别名 rtable = getPromptTableNameByAlias(view_fields, rdt.getString(0, "source_table")); //实际表名 view_fields = view_fields.substring(tindex + 1);//实际view_field } Object o[] = SQLParseUtil.buildQuestionMarkFilter(baseDao.isInternationByTable(rtable) ? "field_value" : view_fields, " in ", showValues); if (o != null && rtable != null) { List paras = (List) o[1]; Object sql = rdt.getFieldSetEntity(0).getObject("promptSQL"); if (sql != null) { SQLEntity s = (SQLEntity) sql; StringBuilder sfilter = new StringBuilder(); if (!StringUtils.isEmpty(pfilter)) { sfilter.append(pfilter);//固定条件 sfilter.append(" and "); } if (baseDao.isInternationByTable(rtable)) {//如果国际化表,通过国际化数据表查询 sfilter.append(StringUtils.isEmpty(alias) ? "" : alias + ".") .append("uuid in (select data_uuid from mrbase_sys_language_cont_values where ") .append(o[0]) .append(" and field_name=? ") .append(" and table_name=? )"); paras.add(view_fields); paras.add(rtable); } else { sfilter.append(o[0].toString()); } StringBuilder b = new StringBuilder(); b.append("select distinct ").append(value_field).append(" from ").append(s.getTableNames()).append(" where ").append(sfilter); DataTableEntity vdt = baseDao.listTable(b.toString(), paras.toArray()); if (vdt != null && vdt.getRows() > 0) { StringBuilder v = new StringBuilder(); int vindex = value_field.indexOf('.');//取值字段如果有别名 if (vindex > 0) { value_field = value_field.substring(vindex + 1);//实际view_field } for (int ri = 0; ri < vdt.getRows(); ri++) { if (v.length() > 0) v.append(","); v.append(vdt.getString(ri, value_field)); } if (isCache) {//先从缓存中取,每个值都要存 DataPoolCacheImpl.getInstance().getPrompt_cache().put(refer + "_" + showValues + "_" + pfilter, v.toString()); } return v.toString(); } } } } return null; } /** * 高级参照中通用 显示字段或取值字段中的表别,取到实际的表名 * * @param viewOrValueField 显示字段或取值字段 * @param source_table 多表关联的表信息 * @return */ public String getPromptTableNameByAlias(String viewOrValueField, String source_table) { int tindex = viewOrValueField.indexOf('.'); String artable = viewOrValueField.substring(0, tindex);//别名 int m = source_table.indexOf(" " + artable + " ");//多表关联中找到别名 if (m < 0) { m = source_table.indexOf(" " + artable + ","); } if (m < 0) { m = source_table.indexOf(" " + artable); } if (m > 0) { String tb = source_table.substring(0, m);//取到表别名前面的字符串,反转后再取到表名 StringBuilder b = new StringBuilder(tb).reverse(); int x = b.indexOf(" "); if (x < 0) { x = b.indexOf(","); } if (x < 0) { x = b.length(); } return new StringBuilder(b.substring(0, x)).reverse().toString();//取到后的表名 } return null; } /** * 获取数据字典存储值 * * @param dictName * @param lable 多个逗号分隔 * @return */ public String getDictValue(String dictName, String lable) { if (StringUtils.isEmpty(dictName) || StringUtils.isEmpty(lable)) { return null; } DataTableEntity dt = DataPoolCacheImpl.getInstance().getCacheData("数据字典配置信息", new String[]{dictName}); //先国际化 DataTableEntity pdt = baseDao.listInternationDataTable(dt, null); StringBuilder b = new StringBuilder(); String ls[] = lable.split(","); for (int i = 0; i < ls.length; i++) { for (int c = 0; c < pdt.getRows(); c++) { FieldSetEntity ff = pdt.getFieldSetEntity(c); if (ff.getSubDataTable("dict_label") != null && ff.getSubDataTable("dict_label").getRows() > 0) { DataTableEntity sub = ff.getSubDataTable("dict_label"); for (int j = 0; j < sub.getRows(); j++) { String v = sub.getString(j, sub.getString(j, "language_code")); if (ls[i].equals(v)) { if (b.length() > 0) b.append(","); b.append(ff.getString("dict_value")); break; } } } } } return b.toString(); } }