Merge remote-tracking branch 'origin/master'

master
guoxin 1 year ago
commit a3637f44b8
  1. 47
      dbsql/update/update202308.sql
  2. 2
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/controller/DynamicFormController.java
  3. 20
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/basic/services/DynamicDataService.java
  4. 38
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/basic/services/DynamicFormService.java
  5. 8
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/basic/services/impl/FormInfoServiceImpl.java
  6. 15
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/db/SqlHelper.java
  7. 56
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/db/executor/SqlExecutor.java
  8. 2
      shandan-basedata/src/main/resources/view/dynamicForm/designForm.html
  9. 31
      shandan-basedata/src/main/resources/view/dynamicForm/formList.html
  10. 7
      shandan-bianmu/src/main/java/com/keyware/shandan/bianmu/controller/MetadataController.java
  11. 3
      shandan-bianmu/src/main/resources/application-dev.yml
  12. 2
      shandan-bianmu/src/main/resources/static/js/business/directory/directory.js
  13. 3
      shandan-bianmu/src/main/resources/static/js/business/metadata/edit.js
  14. 14
      shandan-bianmu/src/main/resources/static/js/business/metadata/metadata.js
  15. 66
      shandan-bianmu/src/main/resources/view/business/metadata/metadataEdit.html
  16. 14
      shandan-browser/src/main/java/com/keyware/shandan/browser/controller/BrowserIndexController.java
  17. 5
      shandan-browser/src/main/java/com/keyware/shandan/browser/controller/SearchController.java
  18. 34
      shandan-browser/src/main/java/com/keyware/shandan/browser/entity/SearchConditionVo.java
  19. 34
      shandan-browser/src/main/java/com/keyware/shandan/browser/entity/SearchResultSort.java
  20. 17
      shandan-browser/src/main/java/com/keyware/shandan/browser/service/ExportComponent.java
  21. 41
      shandan-browser/src/main/java/com/keyware/shandan/browser/service/FileSearchService.java
  22. 36
      shandan-browser/src/main/java/com/keyware/shandan/browser/service/MetadataSearchService.java
  23. 3
      shandan-browser/src/main/resources/application-dev.yml
  24. 241
      shandan-browser/src/main/resources/static/js/browser.js
  25. 3
      shandan-browser/src/main/resources/static/js/meta_search.js
  26. 7
      shandan-browser/src/main/resources/static/js/report.js
  27. 56
      shandan-browser/src/main/resources/view/browser.html
  28. 4
      shandan-common/src/main/java/com/keyware/shandan/common/entity/TreeVo.java
  29. 2
      shandan-common/src/main/java/com/keyware/shandan/common/util/TreeUtil.java
  30. 18
      shandan-common/src/main/resources/static/css/common/common.css
  31. 66
      shandan-common/src/main/resources/static/js/common/layui/extend/datalabel.js
  32. 9
      shandan-common/src/main/resources/static/js/common/layui/extend/dict.js
  33. 4
      shandan-common/src/main/resources/view/common/head.html
  34. 5
      shandan-control/src/main/java/com/keyware/shandan/control/config/DynamicFormListener.java
  35. 6
      shandan-control/src/main/resources/application-dev.yml
  36. 3
      shandan-desktop/src/main/resources/application-dev.yml
  37. 9
      shandan-system/src/main/java/com/keyware/shandan/bianmu/controller/MetadataCommonController.java
  38. 10
      shandan-system/src/main/java/com/keyware/shandan/bianmu/entity/DataLabelsVo.java
  39. 18
      shandan-system/src/main/java/com/keyware/shandan/bianmu/entity/DirectoryVo.java
  40. 4
      shandan-system/src/main/java/com/keyware/shandan/bianmu/entity/LabelEntity.java
  41. 19
      shandan-system/src/main/java/com/keyware/shandan/bianmu/mapper/LabelEntityMapper.java
  42. 36
      shandan-system/src/main/java/com/keyware/shandan/bianmu/service/DirectoryTreeService.java
  43. 7
      shandan-system/src/main/java/com/keyware/shandan/bianmu/utils/DirectoryUtil.java
  44. 15
      shandan-system/src/main/java/com/keyware/shandan/frame/aspect/SafetyAspect.java
  45. 2
      shandan-system/src/main/java/com/keyware/shandan/mark/controller/MarkViewController.java
  46. 2
      shandan-system/src/main/java/com/keyware/shandan/mark/services/MarkService.java
  47. 12
      shandan-system/src/main/java/com/keyware/shandan/system/constants/FormTypeEnum.java
  48. 6
      shandan-system/src/main/java/com/keyware/shandan/system/controller/SysFileController.java
  49. 57
      shandan-system/src/main/java/com/keyware/shandan/system/controller/SysFormConfigController.java
  50. 42
      shandan-system/src/main/java/com/keyware/shandan/system/controller/SysTheadConfigController.java
  51. 66
      shandan-system/src/main/java/com/keyware/shandan/system/entity/SysFormConfig.java
  52. 65
      shandan-system/src/main/java/com/keyware/shandan/system/entity/SysTheadConfig.java
  53. 15
      shandan-system/src/main/java/com/keyware/shandan/system/mapper/SysFormConfigMapper.java
  54. 15
      shandan-system/src/main/java/com/keyware/shandan/system/mapper/SysTheadConfigMapper.java
  55. 18
      shandan-system/src/main/java/com/keyware/shandan/system/service/SysFormConfigService.java
  56. 16
      shandan-system/src/main/java/com/keyware/shandan/system/service/SysTheadConfigService.java
  57. 2
      shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysDictServiceImpl.java
  58. 27
      shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysFormConfigServiceImpl.java
  59. 78
      shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysTheadConfigServiceImpl.java
  60. 1
      shandan-system/src/main/resources/mybatis/mapper/bianmu/DirectoryMapper.xml
  61. 2
      shandan-system/src/main/resources/static/css/sys/file/fileView.css
  62. 6
      shandan-system/src/main/resources/static/js/business/datalabels/managerIndex.js
  63. 24
      shandan-system/src/main/resources/static/js/business/directory/dirCommon.js
  64. 2
      shandan-system/src/main/resources/static/js/sys/file/dirUpload.js
  65. 8
      shandan-system/src/main/resources/static/js/sys/file/view.js
  66. 88
      shandan-system/src/main/resources/static/js/sys/form/formConfig.js
  67. 72
      shandan-system/src/main/resources/view/business/metadata/details.html
  68. 8
      shandan-system/src/main/resources/view/sys/dict/dictEdit.html
  69. 189
      shandan-system/src/main/resources/view/sys/file/dirUploadLayer.html
  70. 151
      shandan-system/src/main/resources/view/sys/file/fileEditLayer.html
  71. 53
      shandan-system/src/main/resources/view/sys/file/fileView.html
  72. 57
      shandan-system/src/main/resources/view/sys/form/formConfig.html

@ -0,0 +1,47 @@
-- 目录表增加加载顺序字段
alter table BIANMU.B_DIRECTORY add SORT integer;
comment on column BIANMU.B_DIRECTORY.SORT is '加载顺序';
-- 置标标签表增加加载顺序字段
alter table BIANMU.B_DATA_LABELS add SORT integer;
comment on column BIANMU.B_DATA_LABELS.SORT is '加载顺序';
-- 更新菜单数据
UPDATE BIANMU.SYS_MENU t
SET t.IS_DELETE = '0',
t.MENU_NAME = '表单配置',
t.MENU_PATH = '/sys/form/config/page/index'
WHERE t.MENU_ID = '1525058137475338242';
CREATE TABLE "BIANMU"."SYS_FORM_CONFIG"
(
"ID" INTEGER IDENTITY(1000, 1) NOT NULL,
"FORM_TYPE" INTEGER,
"FIELD_TITLE" VARCHAR2(50),
"SHOW_TITLE" VARCHAR2(50),
"FIELD_TYPE" VARCHAR2(50),
"DEFAULT_VALUE" VARCHAR2(50) DEFAULT '',
"IS_REQUIRED" BIT DEFAULT 0,
"IS_DISABLED" BIT DEFAULT 0,
"IS_SHOW" BIT DEFAULT 1,
"SORT" INTEGER,
"CREATE_USER" VARCHAR2(50),
"CREATE_TIME" TIMESTAMP(6),
"MODIFY_USER" VARCHAR2(50),
"MODIFY_TIME" TIMESTAMP(6),
CLUSTER PRIMARY KEY("ID")
) STORAGE(ON "MAIN", CLUSTERBTR);
COMMENT ON TABLE "BIANMU"."SYS_FORM_CONFIG" IS '系统表单配置表';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."CREATE_TIME" IS '创建时间';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."CREATE_USER" IS '创建人';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."DEFAULT_VALUE" IS '默认值';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."FIELD_TITLE" IS '字段标题';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."FIELD_TYPE" IS '字段类型';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."FORM_TYPE" IS '表单类型:1-资源注册表单,2-文件上传表单';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."ID" IS '主键';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."IS_DISABLED" IS '是否必填:0-非必填,1-必填';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."IS_REQUIRED" IS '是否禁用:0-不禁用,1-禁用';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."IS_SHOW" IS '是否显示';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."MODIFY_TIME" IS '修改时间';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."MODIFY_USER" IS '修改人';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."SHOW_TITLE" IS '显示标题';
COMMENT ON COLUMN "BIANMU"."SYS_FORM_CONFIG"."SORT" IS '显示顺序';

@ -157,7 +157,7 @@ public class DynamicFormController {
* @return 结果
*/
@PostMapping("/api/form/delete")
public Result<Object> deleteFormInfo(int id) {
public Result<Object> deleteFormInfo(int id) throws Exception {
return Result.of(dynamicFormService.delete(id));
}
}

@ -14,6 +14,12 @@ import java.util.*;
@Service
public class DynamicDataService {
private final SqlExecutor sqlExecutor;
public DynamicDataService(SqlExecutor sqlExecutor) {
this.sqlExecutor = sqlExecutor;
}
/**
* 根据ID删除数据
@ -25,7 +31,7 @@ public class DynamicDataService {
*/
public boolean deleteById(FormInfoPo form, Integer id) throws Exception {
QueryParam param = QueryParam.builder().column("ID").eq(id).build();
return SqlExecutor.executeUpdate(SqlHelper.deleteSql(form, param), id);
return sqlExecutor.executeUpdate(SqlHelper.deleteSql(form, param), id);
}
@ -58,7 +64,7 @@ public class DynamicDataService {
// 插入Sql,去除主键列
params.remove("ID");
LinkedHashMap<String, Object> data = new LinkedHashMap<>(params);
return SqlExecutor.executeUpdate(SqlHelper.insertSql(form, data), data.values().toArray());
return sqlExecutor.executeUpdate(SqlHelper.insertSql(form, data), data.values().toArray());
}
/**
@ -75,7 +81,7 @@ public class DynamicDataService {
QueryParam queryParam = QueryParam.builder().column("ID").eq(id).build();
List<Object> paramValues = new ArrayList<>(dataMap.values());
paramValues.addAll(queryParam.getParamValues());
return SqlExecutor.executeUpdate(SqlHelper.updateSql(form, dataMap, queryParam), paramValues.toArray());
return sqlExecutor.executeUpdate(SqlHelper.updateSql(form, dataMap, queryParam), paramValues.toArray());
}
/**
@ -88,7 +94,7 @@ public class DynamicDataService {
*/
public Map<String, Object> getById(FormInfoPo form, @NotNull Integer id) throws Exception {
QueryParam param = QueryParam.builder().column("ID").eq(id).build();
List<Map<String, Object>> list = SqlExecutor.executeQuery(SqlHelper.selectSql(form, param), id);
List<Map<String, Object>> list = sqlExecutor.executeQuery(SqlHelper.selectSql(form, param), id);
if (list == null) {
return null;
}
@ -105,12 +111,12 @@ public class DynamicDataService {
* @throws Exception -
*/
public Page<Map<String, Object>> pageList(FormInfoPo form, QueryParam params) throws Exception {
List<Map<String, Object>> countList = SqlExecutor.executeQuery(SqlHelper.countSql(form, params), params.getParamValues().toArray());
List<Map<String, Object>> countList = sqlExecutor.executeQuery(SqlHelper.countSql(form, params), params.getParamValues().toArray());
long count = 0;
if (countList != null && countList.size() > 0) {
count = (long) countList.get(0).get("COUNT");
}
List<Map<String, Object>> dataList = SqlExecutor.executeQuery(SqlHelper.pageSelectSql(form, params), params.getParamValues().toArray());
List<Map<String, Object>> dataList = sqlExecutor.executeQuery(SqlHelper.pageSelectSql(form, params), params.getParamValues().toArray());
Page<Map<String, Object>> page = new Page<>(params.getPage(), params.getPageSize(), count);
page.setRecords(dataList);
return page;
@ -124,6 +130,6 @@ public class DynamicDataService {
* @throws Exception
*/
public List<Map<String, Object>> list(FormInfoPo form) throws Exception {
return SqlExecutor.executeQuery(SqlHelper.selectSql(form, null));
return sqlExecutor.executeQuery(SqlHelper.selectSql(form, null));
}
}

@ -3,6 +3,7 @@ package com.keyware.shandan.dynacmicform.core.basic.services;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.keyware.shandan.common.util.DateUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.core.DynamicFormEventListener;
import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
@ -12,6 +13,7 @@ import com.keyware.shandan.dynacmicform.core.db.parser.TableInfoParser;
import com.keyware.shandan.dynacmicform.core.db.pojo.Table;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@ -21,11 +23,14 @@ import java.util.List;
@Slf4j
@Service
public class DynamicFormService {
private final SqlExecutor sqlExecutor;
private final FormInfoService formInfoService;
private final DynamicFormEventListener dynamicFormEventListener;
public DynamicFormService(FormInfoService formInfoService, DynamicFormEventListener dynamicFormEventListener) {
public DynamicFormService(SqlExecutor sqlExecutor,
FormInfoService formInfoService,
DynamicFormEventListener dynamicFormEventListener) {
this.sqlExecutor = sqlExecutor;
this.formInfoService = formInfoService;
this.dynamicFormEventListener = dynamicFormEventListener;
}
@ -37,12 +42,13 @@ public class DynamicFormService {
* @return boolean
* @throws Exception 异常
*/
@Transactional(rollbackFor = Exception.class)
public boolean saveForm(FormInfoPo form) throws Exception {
FormInfoPo oldForm = formInfoService.getById(form.getId());
Table table = TableInfoParser.parseTable(form);
if (oldForm == null) {
String sql = SqlHelper.createSql(table);
SqlExecutor.execute(sql);
String sql = SqlHelper.tableCreateSql(table);
sqlExecutor.execute(sql);
} else {
Table oldTable = TableInfoParser.parseTable(oldForm);
List<String> alterSqlList = SqlHelper.alterTableDropColumnSql(oldTable, table);
@ -51,7 +57,7 @@ public class DynamicFormService {
alterSqlList.addAll(SqlHelper.alterTableAddColumnSql(oldTable, table));
alterSqlList.addAll(SqlHelper.commentTableSql(oldTable, table));
alterSqlList.addAll(SqlHelper.commentColumnSql(oldTable, table));
SqlExecutor.executeBatch(alterSqlList);
sqlExecutor.executeBatch(alterSqlList);
}
if (StringUtils.isBlank(form.getQueryConfig())) {
generateQueryConfig(form);
@ -65,18 +71,30 @@ public class DynamicFormService {
}
/**
* 删除表单信息
* 删除表单信息逻辑删除并对实际数据表进行重命名备份
*
* @param id
* @return
*/
public boolean delete(Integer id) {
@Transactional(rollbackFor = Exception.class)
public boolean delete(Integer id) throws Exception {
FormInfoPo form = formInfoService.getById(id);
if (form != null) {
// 对原始表结构进行重命名备份
Table table = TableInfoParser.parseTable(form);
String newName = table.getName() + "_BACKUP_" + DateUtil.getFormatNowDate("yyyyMMddHHmmss");
String sql = SqlHelper.tableRenameSql(table.getName(), newName);
sqlExecutor.execute(sql);
// 更新表名后进行逻辑删除
form.setFormId(newName);
formInfoService.updateById(form);
boolean ok = formInfoService.removeById(id);
if (ok) {
dynamicFormEventListener.onDrop(form);
if (!ok) {
throw new RuntimeException("表单信息删除异常");
}
return ok;
}
dynamicFormEventListener.onDrop(form);
return true;
}
/**

@ -5,6 +5,8 @@ import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
import com.keyware.shandan.dynacmicform.core.basic.mapper.FormInfoMapper;
import com.keyware.shandan.dynacmicform.core.basic.services.FormInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
@ -15,4 +17,10 @@ public class FormInfoServiceImpl extends ServiceImpl<FormInfoMapper, FormInfoPo>
public boolean removeById(Serializable id) {
return super.removeById(id);
}
/*@Override
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
public boolean saveOrUpdate(FormInfoPo entity) {
return super.saveOrUpdate(entity);
}*/
}

@ -1,6 +1,7 @@
package com.keyware.shandan.dynacmicform.core.db;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
@ -23,7 +24,7 @@ public class SqlHelper {
* @param table
* @return
*/
public static String createSql(Table table) {
public static String tableCreateSql(Table table) {
StringBuilder sqlBuilder = new StringBuilder("CREATE TABLE ");
sqlBuilder.append("\"").append(table.getName()).append("\" (");
@ -46,13 +47,17 @@ public class SqlHelper {
return sqlBuilder.toString();
}
public static String tableRenameSql(String oldTableName, String newTableName) {
return StrUtil.format("alter table \"{}\" rename to \"{}\"", oldTableName, newTableName);
}
/**
* 修改表的sql
*
* @param columns 修改的列集合
* @return
*/
public static List<String> alterSql(Map<String, List<Column>> columns) {
public static List<String> tableAlterSql(Map<String, List<Column>> columns) {
List<String> alterSqlList = new ArrayList<>();
return alterSqlList;
@ -64,10 +69,8 @@ public class SqlHelper {
* @param table
* @return
*/
public static String dropSql(Table table) {
StringBuilder sqlBuilder = new StringBuilder();
return sqlBuilder.toString();
public static String tableDropSql(Table table) {
return "DROP TABLE \"" + table.getName() + "\"";
}
/**

@ -6,8 +6,10 @@ import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.config.spring.ContextHelper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.Reader;
@ -15,19 +17,24 @@ import java.sql.Date;
import java.sql.*;
import java.util.*;
@Component
public class SqlExecutor {
private static final Logger log = LoggerFactory.getLogger(SqlExecutor.class);
private final SqlSession sqlSession;
public SqlExecutor(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
/**
* 检查SQL是否可以正常执行
*
* @param sql sql
* @return boolean
*/
public static boolean validateQuery(String sql) {
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
public boolean validateQuery(String sql) {
try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
ResultSet rs = stmt.executeQuery();
rs.close();
log.debug("==> {}", sql);
@ -38,15 +45,15 @@ public class SqlExecutor {
}
}
public static boolean execute(String sql) throws Exception {
public boolean execute(String sql) throws Exception {
if (StringUtils.isEmpty(sql)) {
return false;
}
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
log.debug("==> SQL: " + sql);
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
try {
Connection conn = sqlSession.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
return stmt.execute();
} catch (Exception e) {
log.error("执行sql查询异常: " + sql, e);
@ -61,15 +68,15 @@ public class SqlExecutor {
* @return
* @throws SQLException
*/
public static int[] executeBatch(Collection<String> sqlList) throws SQLException {
public int[] executeBatch(Collection<String> sqlList) throws SQLException {
int[] count = new int[sqlList.size()];
if (sqlList.isEmpty()) {
return count;
}
SqlSessionFactory sqlSessionFactory = getSessionFactory();
PreparedStatement stmt = null;
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection()) {
try {
Connection conn = getConnection();
conn.setAutoCommit(false);
for (String sql : sqlList) {
if (StringUtils.hasText(sql)) {
@ -102,12 +109,11 @@ public class SqlExecutor {
* @return boolean
* @throws Exception -
*/
public static boolean executeUpdate(String sql, Object... params) throws Exception {
public boolean executeUpdate(String sql, Object... params) throws Exception {
if (StringUtils.isEmpty(sql)) {
return false;
}
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
log.debug("==> SQL: " + sql);
// 替换单个?参数为多个,用于拼接IN参数
if (params != null && params.length > 0) {
@ -116,7 +122,9 @@ public class SqlExecutor {
log.warn("更新参数集合数量过多, size={},请检查调用是否合理!", params.length);
}
}
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
try {
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
@ -137,12 +145,11 @@ public class SqlExecutor {
* @param sql
* @return
*/
public static List<Map<String, Object>> executeQuery(String sql, Object... params) throws Exception {
public List<Map<String, Object>> executeQuery(String sql, Object... params) throws Exception {
if (StringUtils.isBlank(sql)) {
return null;
}
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
log.debug("==> SQL: " + sql);
// 替换单个?参数为多个,用于拼接IN参数
if (params != null && params.length > 0) {
@ -151,7 +158,9 @@ public class SqlExecutor {
log.warn("查询参数集合数量过多, size={},请检查调用是否合理!", params.length);
}
}
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
try {
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
@ -186,13 +195,8 @@ public class SqlExecutor {
}
}
private static SqlSessionFactory getSessionFactory() {
SqlSessionFactory sqlSessionFactory = ContextHelper.getBean(SqlSessionFactory.class);
if (sqlSessionFactory == null) {
log.warn("无法获取SqlSessionFactory实例,SQL将不被执行。");
throw new RuntimeException("获取SqlSessionFactory实例异常");
}
return sqlSessionFactory;
private Connection getConnection() throws SQLException {
return sqlSession.getConfiguration().getEnvironment().getDataSource().getConnection();
}
private static String clobRsConvert(Clob clob) {

@ -62,7 +62,7 @@
postRequest(`${ctx}/dynamic-form/api/form/save`, params).then(res => {
if (res.flag) {
temp_data = params;
showOkMsg('保存成功');
saveCallback && saveCallback();
} else {
showErrorMsg(res.msg)
}

@ -14,10 +14,12 @@
<div id="form-list-table" lay-filter="form-list-table"></div>
<script type="text/html" id="table-head-toolbar">
<div class="btn-comp">
<button type="button" class="layui-btn layui-btn-sm layui-btn-warm" lay-event="newDesign">设计表单</button>
<button type="button" class="layui-btn layui-btn-sm layui-btn-warm" lay-event="newDesign">设计表单
</button>
</div>
<div class="search-comp">
<input class="layui-input" type="text" id="searchText" name="searchText" placeholder="请输入表单名称进行查询"/>
<input class="layui-input" type="text" id="searchText" name="searchText"
placeholder="请输入表单名称进行查询"/>
<button type="button" class="layui-btn layui-btn-sm" lay-event="query">查 询</button>
</div>
</script>
@ -79,7 +81,7 @@
openFormConfigLayer(id);
break;
case 'delete':
formDelete(id)
formDelete(data)
break;
}
}
@ -97,10 +99,21 @@
*/
function openFormDesignPage(id) {
openMaxLayer(`${ctx}/dynamic-form/view/form/design?formId=${id}`, {
success: function(layero, index){
let iframeWin = window[layero.find('iframe')[0]['name']];
iframeWin.saveCallback = function(){
formListTable.reload();
showOkMsg('保存成功');
layer.closeAll();
}
},
cancel: function (index, layerObj) {
let iframeWin = window[layerObj.find('iframe')[0]['name']];
if (iframeWin.isChange()) {
layer.confirm('关闭窗口将不会保存更改的内容,是否继续关闭?', {title: '关闭表单设计器', btn: ['关闭', '取消']}, function () {
layer.confirm('关闭窗口将不会保存更改的内容,是否继续关闭?', {
title: '关闭表单设计器',
btn: ['关闭', '取消']
}, function () {
layer.closeAll();
})
} else {
@ -132,10 +145,14 @@
/**
* 删除表单
* @param id
* @param data
*/
function formDelete(id) {
layer.confirm('是否删除该表单?', {title: '删除确认', btn: ['删除', '取消']}, function (layIndex) {
function formDelete(data) {
const {id, formId} = data;
layer.confirm(`将同时删除以下数据库表:<br/><label style="color: orange">${formId}</label><br/>是否继续删除?`, {
title: '删除确认',
btn: ['删除', '取消']
}, function (layIndex) {
postRequest(`${ctx}/dynamic-form/api/form/delete`, {id}).then(res => {
layer.close(layIndex);
res.flag ? showOkMsg('删除成功') : showErrorMsg(res.msg);

@ -13,8 +13,11 @@ import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.enums.SecretLevel;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.system.entity.SysFile;
import com.keyware.shandan.system.entity.SysFormConfig;
import com.keyware.shandan.system.service.SysFileService;
import com.keyware.shandan.system.service.SysFormConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@ -46,6 +49,9 @@ public class MetadataController extends BaseController<MetadataService, Metadata
@Autowired
private DataLabelsService labelsService;
@Autowired
private SysFormConfigService formConfigService;
@GetMapping("/")
public ModelAndView index(ModelAndView mov) {
mov.setViewName("business/metadata/metadata");
@ -93,6 +99,7 @@ public class MetadataController extends BaseController<MetadataService, Metadata
public ModelAndView edit(ModelAndView mav) {
mav.setViewName("business/metadata/metadataEdit");
mav.addObject("LabelConfigSet", labelsService.formConfigList());
mav.addObject("metadataFormConfig", formConfigService.listByFormType(FormTypeEnum.metadataEditForm));
return mav;
}

@ -50,4 +50,5 @@ project:
# 日志级别
logging:
level:
root: debug
com.keyware: debug

@ -297,6 +297,8 @@ function startRender() {
},
});
}else{
showErrorMsg('数据表不支持下载');
}
})
}

@ -276,9 +276,10 @@ layui.use(['form', 'layer', 'editPage', 'laytpl', 'laydate', 'element', 'table',
layui.dict.setData('dict-secret-level', data);
}
console.info(new Date().getTime())
//日期选择器
laydate.render({
elem: '#collectionTime',
elem: 'input[name="collectionTime"]',
type: 'datetime',
value: new Date(),
format: "yyyy-MM-dd HH:mm:ss"

@ -12,8 +12,11 @@ layui.use(['layer', 'listPage', 'form', 'dict'], function () {
let height = $(document).height();
height = height < 650 ? height : height * 0.8;
let where = {metadataName: '', reviewStatus: '', useStatus: ''};
const fieldMap = new Map()
METADATA_FORM_CONFIG.forEach(conf=>fieldMap.set(conf.fieldName, conf));
console.info(fieldMap);
const listPage = layui.listPage.init({
deleteUrl: `${ctx}/business/metadata/delete`,
table: {
@ -27,23 +30,26 @@ layui.use(['layer', 'listPage', 'form', 'dict'], function () {
{
field: 'metadataName',
title: '数据名称',
hide: !fieldMap.get('metadataName').isShow,
templet: data => `<lable style="font-weight: ${data.hasMark ? 'bold' : 'italic'};">${data.metadataName}</lable>`
},
{field: 'metadataComment', title: '中文注释'},
{field: 'metadataComment', title: '中文注释',hide: fieldMap.get('metadataName').isShow},
{
field: 'secretLevel',
title: '密级',
hide: !fieldMap.get('secretLevel').isShow,
templet: data => layui.dict.getDictDesc('secret_level', data.secretLevel)
},
{field: 'themeTask', title: '主题任务'},
{field: 'themeTask', title: '主题任务', hide: !fieldMap.get('themeTask').isShow},
{
field: 'dataFrom',
title: '数据来源',
hide: !fieldMap.get('dataFrom').isShow,
width: 100,
templet: data => layui.dict.getDictDesc('data_source', data.dataFrom)
},
{field: 'collectionTime', title: '任务时间', width: 180, align: 'center'},
{field: 'collectionTime', title: '任务时间', width: 180, align: 'center',hide: !fieldMap.get('collectionTime').isShow},
{
field: 'used', title: '关联状态', width: 120, align: 'center', templet: (data) => {
if (data.used) {

@ -34,47 +34,28 @@
<div class="layui-form-item">
<div id="metadataTablesTab"><label style="color: red">* 请先选择数据表</label></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据名称</label>
<div class="layui-input-block">
<input type="hidden" name="metadataComment">
<input type="text" name="metadataName" autocomplete="off" placeholder="数据名称"
class="layui-input" lay-verify="required" readonly>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任务时间</label>
<div class="layui-input-block">
<input type="text" id="collectionTime" name="collectionTime" placeholder="任务时间"
class="layui-input" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据来源</label>
<div class="layui-input-block">
<div dict-component="select" dict-type="data_source" dict-name="dataFrom"
id="dict-data-form"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据类型</label>
<div class="layui-input-block">
<div dict-component="select" dict-type="data_type" dict-name="dataType"
id="dict-data-type"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据密级</label>
<div class="layui-form-item" th:each="field,iterStat : ${metadataFormConfig}" th:if="${field.isShow}">
<label th:if="${field.isRequired}" class="layui-form-label">
<label style="color: red">*</label>
<label th:text="${field.showTitle}">*</label>
</label>
<label th:if="${!field.isRequired}" class="layui-form-label" th:text="${field.showTitle}"></label>
<div class="layui-input-block">
<div dict-component="radio" dict-type="secret_level" dict-name="secretLevel"
id="dict-secret-level"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">主题任务</label>
<div class="layui-input-block">
<input type="text" name="themeTask" autocomplete="off" placeholder="主题任务"
class="layui-input">
<input type="hidden" name="metadataComment" th:if="${field.fieldName == 'metadataName'}">
<!-- 文本框输入框类型 -->
<input class="layui-input" type="text" autocomplete="off"
th:if="${field.fieldType == 'input' || field.fieldType == 'date'}"
th:name="${field.fieldName}"
th:disabled="${field.isDisabled}"
th:placeholder="${field.showTitle}"
th:lay-verify="${field.isRequired ? 'required' : ''}">
<!-- 数据字典类型 -->
<div dict-component="select"
th:if="${field.fieldType == 'dict'}"
th:disabled="${field.isDisabled}"
th:dict-type="${field.dictType}"
th:dict-name="${field.fieldName}"
th:id="${'dict-'+field.fieldName}"></div>
</div>
</div>
<div class="layui-form-item" th:each="labelSet, iterState:${LabelConfigSet}">
@ -89,7 +70,9 @@
</div>
<div class="layui-form-item other-label-item">
<label class="layui-form-label"><a class="label-type choose-data add-other" id="addOtherLabelBtn">添加</a>其他标签</label>
<div class="layui-input-block label-set-component other-label" th:data-field-title="其他标签"></div>
<div class="layui-input-block other-label-item">
<div class="label-set-component other-label" th:data-field-title="其他标签"></div>
</div>
</div>
<!-- 隐藏域 -->
<input type="text" name="id" hidden="hidden"/>
@ -147,6 +130,5 @@
{{# } }}
</script>
<!-- js -->
<script th:src="@{/js/business/mark/markTag.js}"></script>
<script th:src="@{/js/business/metadata/edit.js}"></script>
</html>

@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.keyware.shandan.bianmu.entity.MetadataBasicVo;
import com.keyware.shandan.bianmu.service.DirPermissionService;
import com.keyware.shandan.bianmu.service.DirectoryService;
import com.keyware.shandan.bianmu.service.MetadataService;
import com.keyware.shandan.common.enums.SystemTypes;
import com.keyware.shandan.common.util.RsaUtil;
@ -13,11 +12,12 @@ import com.keyware.shandan.datasource.entity.DBTableColumnVo;
import com.keyware.shandan.frame.config.security.SecurityUtil;
import com.keyware.shandan.system.entity.SysSetting;
import com.keyware.shandan.system.entity.SysUser;
import com.keyware.shandan.system.service.SysFileService;
import com.keyware.shandan.system.service.SysTheadConfigService;
import com.keyware.shandan.system.service.SysUserService;
import com.keyware.shandan.system.utils.SysSettingUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@ -39,9 +39,6 @@ import java.util.List;
@RequestMapping("/")
public class BrowserIndexController {
@Autowired
private DirectoryService directoryService;
@Autowired
private MetadataService metadataService;
@ -49,10 +46,10 @@ public class BrowserIndexController {
private SysUserService sysUserService;
@Autowired
private SysFileService sysFileService;
private DirPermissionService permissionService;
@Autowired
private DirPermissionService permissionService;
private SysTheadConfigService theadConfigService;
@Value("${project.cors-lib-search:#}")
private String corsLibSearchUrl;
@ -90,10 +87,11 @@ public class BrowserIndexController {
}
@GetMapping("/browser")
public ModelAndView browser(ModelAndView mov) {
public ModelAndView browser(ModelAndView mov, Authentication auth) {
mov.setViewName("browser");
SysSetting bianmuSetting = SysSettingUtil.getSysSetting(SystemTypes.BIANMU.name());
mov.addObject("bianmuServer", bianmuSetting.getSysAddress());
mov.addObject("theadConfig", theadConfigService.listByCreateUser(auth.getName()));
return mov;
}

@ -10,6 +10,7 @@ import com.keyware.shandan.bianmu.entity.MetadataBasicVo;
import com.keyware.shandan.bianmu.service.MetadataService;
import com.keyware.shandan.browser.entity.PageVo;
import com.keyware.shandan.browser.entity.SearchConditionVo;
import com.keyware.shandan.browser.entity.SearchResultSort;
import com.keyware.shandan.browser.service.*;
import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.util.FileDownload;
@ -138,10 +139,10 @@ public class SearchController {
*/
@AppLog(operate = "文件全文检索查询")
@GetMapping("/full/file")
public Result<Object> searchFile(PageVo page, String search, String metaId) {
public Result<Object> searchFile(PageVo page, String search, String metaId, SearchResultSort sort) {
try {
return Result.of(fileSearchService.searchFile(page, search, metaId));
return Result.of(fileSearchService.searchFile(page, search, metaId, sort));
} catch (IOException e) {
e.printStackTrace();
return Result.of(null, false, "Elasticsearch 请求异常");

@ -10,7 +10,6 @@ import org.elasticsearch.search.sort.SortOrder;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -35,7 +34,7 @@ public class SearchConditionVo extends PageVo implements Serializable {
//搜索条件集合
private List<Item> conditions = new ArrayList<>();
// 排序
private Sort sort = new Sort();
private SearchResultSort sort = new SearchResultSort();
//排序字段
@Deprecated
private String sortFiled;
@ -113,35 +112,4 @@ public class SearchConditionVo extends PageVo implements Serializable {
return " " + logicJoin + " \"" + table + "\".\"" + fieldName + "\" " + logicJudgement + " " + fieldValue;
}
}
/**
* 排序
*/
@Getter
@Setter
public static class Sort {
//排序字段
private String field;
//排序方式
private String sort;
public String getField() {
return " " + field;
}
public String getSort() {
return " " + sort;
}
/**
* @return order by sql语句
*/
public String getOrderBy() {
return isEmpty() ? Strings.EMPTY : " order by" + getField() + " " + getSort();
}
public boolean isEmpty() {
return StringUtils.isBlankAny(this.field, this.sort);
}
}
}

@ -0,0 +1,34 @@
package com.keyware.shandan.browser.entity;
import com.keyware.shandan.common.util.StringUtils;
import joptsimple.internal.Strings;
import lombok.Getter;
import lombok.Setter;
/**
* 排序
*
* @author GuoXin
* @date 2023/8/29
*/
@Getter
@Setter
public class SearchResultSort {
//排序字段
private String field;
//排序方式
private String sort;
/**
* @return order by sql语句
*/
public String getOrderBy() {
return isEmpty() ? Strings.EMPTY : " order by " + getField() + " " + getSort();
}
public boolean isEmpty() {
return StringUtils.isBlankAny(this.field, this.sort);
}
}

@ -21,14 +21,12 @@ import com.keyware.shandan.system.service.SysFileService;
import com.keyware.shandan.system.utils.SysSettingUtil;
import lombok.AllArgsConstructor;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ExportComponent {
private final String exportId;
@ -107,9 +105,8 @@ public class ExportComponent {
JSONObject col = (JSONObject) json;
String comment = col.getString("comment");
String colName = col.getString("columnName");
String name = StringUtils.hasTextByDefault(comment, colName);
colNameList.add(colName);
return name;
return colName + (StringUtils.hasText(comment) ? "[" + comment + "]" : "");
}).toList();
// 添加第一行
@ -118,7 +115,13 @@ public class ExportComponent {
// 遍历数据
datas.forEach(data -> {
// 遍历字段列名,获取对应数据并拼接成列的集合
List<String> cells = StreamUtil.as(colNameList).map(col -> data.get(col).toString()).toList();
List<String> cells = colNameList.stream().map(col -> {
Object value = data.get(col);
if (value == null) {
return "";
}
return String.valueOf(value);
}).collect(Collectors.toList());
rowList.add(cells);
});
@ -189,7 +192,7 @@ public class ExportComponent {
private void delete(String path) {
File file = new File(path);
if(file.exists()){
if (file.exists()) {
file.delete();
}
}

@ -1,12 +1,16 @@
package com.keyware.shandan.browser.service;
import cn.hutool.core.util.ReflectUtil;
import com.keyware.shandan.bianmu.entity.DirectoryVo;
import com.keyware.shandan.bianmu.enums.ReviewStatus;
import com.keyware.shandan.bianmu.service.DirectoryService;
import com.keyware.shandan.browser.entity.PageVo;
import com.keyware.shandan.browser.entity.SearchResultSort;
import com.keyware.shandan.common.constants.DirConstant;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.entity.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
@ -17,10 +21,15 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@ -30,6 +39,7 @@ import java.util.List;
* @author Administrator
* @since 2021/12/21
*/
@Slf4j
@Service
public class FileSearchService {
@ -38,13 +48,13 @@ public class FileSearchService {
@Autowired
private DirectoryService directoryService;
public PageVo searchFile(PageVo page, String text, String metaId) throws IOException {
public PageVo searchFile(PageVo page, String text, String metaId, SearchResultSort sort) throws IOException {
SearchRequest request = Requests.searchRequest("shandan");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(page.getPage() * page.getSize() - page.getSize()).size(page.getSize());
BoolQueryBuilder builder = QueryBuilders.boolQuery();
if(!DirConstant.DIR_ROOT_ID.equals(metaId)){
if (!DirConstant.DIR_ROOT_ID.equals(metaId)) {
List<String> ids = new ArrayList<>();
ids.add(metaId);
ids.addAll(getChildrenByDirId(metaId));
@ -75,13 +85,38 @@ public class FileSearchService {
highlightBuilder.preTags("<label style=\"color:red\">").postTags("</label>").field("*");
highlightBuilder.forceSource(true);
searchSourceBuilder.query(builder).highlighter(highlightBuilder);
// 设置排序
if (!sort.isEmpty()) {
String sortField = sort.getField();
// 使用反射获取文件实体类中字段上的注解设置的字段类型
Field field = ReflectUtil.getField(SysFile.class, sortField);
if (field != null) {
org.springframework.data.elasticsearch.annotations.Field fieldAnno = field.getAnnotation(org.springframework.data.elasticsearch.annotations.Field.class);
if(fieldAnno.type() != FieldType.Text
&& fieldAnno.type() != FieldType.Object
&& fieldAnno.type() != FieldType.Auto
&& fieldAnno.type() != FieldType.Nested
&& fieldAnno.type() != FieldType.Ip
&& fieldAnno.type() != FieldType.Attachment){
if(fieldAnno.type() == FieldType.Keyword){
sortField = sortField.concat(".keyword");
}
searchSourceBuilder.sort(sortField, SortOrder.fromString(sort.getSort()));
}else {
log.error("不支持的排序类型:{}:{}", sortField, fieldAnno.type());
}
}
}
request.source(searchSourceBuilder);
// 设置排序
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
return PageVo.ofSearchHits(response.getHits(), page);
}
private List<String> getChildrenByDirId(String dirId){
private List<String> getChildrenByDirId(String dirId) {
DirectoryVo dir = directoryService.getById(dirId);
return StreamUtil.as(directoryService.childrenLists(dir, ReviewStatus.SUBMITTED)).map(DirectoryVo::getId).toList();
}

@ -1,5 +1,7 @@
package com.keyware.shandan.browser.service;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.keyware.shandan.bianmu.entity.DirectoryResource;
@ -10,14 +12,17 @@ import com.keyware.shandan.bianmu.mapper.DirectoryResourceMapper;
import com.keyware.shandan.bianmu.service.DirectoryService;
import com.keyware.shandan.browser.entity.PageVo;
import com.keyware.shandan.browser.entity.SearchConditionVo;
import com.keyware.shandan.browser.entity.SearchResultSort;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Administrator
@ -81,22 +86,33 @@ public class MetadataSearchService {
}
break;
case "markTag":
String tagText = item.getFieldValue();
List<String> tags = Arrays.asList(tagText.split(","));
StringBuilder existsSql = new StringBuilder("select 1 from MARK_RECORD MR where MR.ENTITY_ID = V_DIRECTORY_RESOURCE.ID and ( 1 = 1 ");
tags.forEach(tagItem -> {
if (StringUtils.hasText(tagItem)) {
String[] arr = tagItem.split("-");
existsSql.append(" and MR.MARK_VALUE like '%").append(arr[1]).append("%' ");
}
});
existsSql.append(")");
String tagIds = item.getFieldValue();
List<String> ids = Arrays.asList(tagIds.split(","));
if (ids.size() > 0) {
StringBuilder existsSql = new StringBuilder("select 1 from (select ENTITY_ID, WM_CONCAT(LABEL_ID) LABEL_IDS from B_DATA_LABEL_ENTITY DLN where DLN.ENTITY_ID = V_DIRECTORY_RESOURCE.ID group by ENTITY_ID) tmp1");
List<String> andSqlList = ids.stream().map(id -> "tmp1.LABEL_IDS like '%" + id + "%'").collect(Collectors.toList());
existsSql.append(" where ").append(String.join(" and ", andSqlList));
wrapper.exists(existsSql.toString());
}
break;
default:
}
});
});
// 排序设置
SearchResultSort sort = condition.getSort();
if(sort != null && sort.getSort() != null ){
// 通过反射获取资源类字段注解中的数据库表相关的列名
Field field = ReflectUtil.getField(DirectoryResource.class, sort.getField().trim());
if(field != null){
TableField tableField = field.getAnnotation(TableField.class);
if(tableField != null && StringUtils.hasText(tableField.value())){
queryWrapper.orderBy(true, sort.getSort().equalsIgnoreCase("asc"), tableField.value());
}
}
}
return queryWrapper;
}

@ -50,4 +50,5 @@ project:
logging:
level:
root: debug
com.keyware: debug

@ -8,15 +8,16 @@
*/
// 目录树数据缓存
const dirCache = new Map();
layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'dropdown', 'laydate', 'dict'], function () {
layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'dropdown', 'laydate', 'dict', 'datalabel'], function () {
const listPage = layui.listPage,
form = layui.form,
element = layui.element,
laydate = layui.laydate,
globalTree = layui.globalTree;
let metaListTable, dirFileTable, tagSelector, tags = [], unchecked_tags = [], conditions = [];
globalTree = layui.globalTree,
DataLabel = layui.datalabel;
let metaListTable, dirFileTable, tagSelector, tags = [], conditions = [];
const unchecked_tags = new Set();
// 初始化
initDirectoryTree();
@ -133,26 +134,27 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
url: `${ctx}/search/metadata/all/page/${id}`,
height: 'full-110',
method: 'post',
defaultToolbar: [{
title: '导出' //标题
, layEvent: 'export' //事件名,用于 toolbar 事件中使用
, icon: 'layui-icon-export' //图标类名
}],
autoSort: false,
defaultToolbar: [
{title: '导出', layEvent: 'export', icon: 'layui-icon-export'},
{title: '列表配置', layEvent: 'theadSet', icon: 'layui-icon-cols'}
],
request: {pageName: 'page', limitName: 'size'},
limit: 30,
cols: [[
{field: 'id', title: 'ID', hide: true},
{field: 'resourceName', title: '数据名称', width: 300},
{field: 'resourceComment', title: '中文注释/描述'},
{field: 'directoryPath', title: '资源路径'},
{field: 'themeTask', title: '主题任务', hide: true},
{field: 'resourceName', title: '数据名称', width: 300, sort: true},
{field: 'resourceComment', title: '中文注释/描述', sort: true},
{field: 'directoryPath', title: '资源路径', sort: true},
{field: 'themeTask', title: '主题任务', hide: true, sort: true},
{
field: 'dataSource',
title: '数据来源',
width: 160,
templet: (data) => DICT.getText("data_source", data.dataSource) || data.dataSource || ''
templet: (data) => DICT.getText("data_source", data.dataSource) || data.dataSource || '',
sort: true
},
{field: 'taskTime', title: '任务时间', width: 180, align: 'center'},
{field: 'taskTime', title: '任务时间', width: 180, align: 'center', sort: true},
{field: 'modifyTime', title: '注册时间', width: 160, align: 'center', hide: true},
{fixed: 'right', title: '操作', toolbar: '#rowToolBar', width: 100, align: 'center'}
]],
@ -171,6 +173,15 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
}
},
});
metaListTable.gtable.on('sort', function (data) {
const {field, type} = data;
let sort = type;
if (!sort || sort === 'null') {
sort = undefined;
}
metaListTable.where.sort = {field: field.trim(), sort: sort}
beginSearch();
})
metaListTable.addTableRowEvent('export', function (obj) {
if (id === DIR_ROOT_ID) {
showErrorMsg('不允许导出根目录数据');
@ -206,6 +217,8 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
openMaxLayerWithURL(`${ctx}/search/meta/${obj.id}`)
}
})
new THeadSetLayer(metaListTable, layui);
}
function initFileSearchTable(id) {
@ -218,32 +231,42 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
url: `${ctx}/search/full/file?metaId=${id}`,
height: 'full-110',
request: {pageName: 'page', limitName: 'size'},
defaultToolbar: [
{title: '列表配置', layEvent: 'theadSet', icon: 'layui-icon-cols'}
],
autoSort: false,
limit: 30,
method: 'get',
cols: [[
{field: 'id', title: 'ID', hide: true},
{field: 'fileName', title: '文件名称', minWidth: 300, fixed: 'left'},
{
field: 'source',
title: '文件来源',
minWidth: 160,
sort: true,
templet: data => DICT.getText('data_source', data.source) || data.source || ''
},
{field: 'taskCode', title: '任务代号', minWidth: 160},
{field: 'taskCode', title: '任务代号', sort: true, minWidth: 160},
{
field: 'taskNature',
title: '任务性质',
minWidth: 160,
sort: true,
templet: data => DICT.getText('task_nature', data.taskNature) || data.taskNature || ''
},
{field: 'troopCode', title: '部队代号', minWidth: 160},
{field: 'missileNumber', title: '导弹编号', minWidth: 160},
{field: 'equipmentModel', title: '装备型号', minWidth: 160},
{field: 'troopCode', title: '部队代号', sort: true, minWidth: 160},
{field: 'missileNumber', title: '导弹编号', sort: true, minWidth: 160},
{field: 'equipmentModel', title: '装备型号', sort: true, minWidth: 160},
{
field: 'targetNumber',
title: '目标/靶标类型',
minWidth: 160,
sort: true,
templet: data => DICT.getText('target_type', data.targetNumber) || data.targetNumber || ''
},
{field: 'entryStaff', title: '录入人员', minWidth: 160},
{field: 'inputDate', title: '收文时间', width: 160, align: 'center'},
{field: 'entryStaff', title: '录入人员', sort: true, minWidth: 160},
{field: 'inputDate', title: '收文时间', sort: true, width: 160, align: 'center'},
{field: 'remark', title: '文件描述', width: 300},
{field: 'text', title: '文件内容', width: 300},
{fixed: 'right', title: '操作', toolbar: '#fileRowToolBar', width: 100, align: 'center'}
@ -251,10 +274,23 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
},
});
dirFileTable.gtable.on('sort', function (data) {
const {field, type} = data;
let sort = type;
if (!sort || sort === 'null') {
sort = undefined;
}
dirFileTable.table.where.field = field.trim();
dirFileTable.table.where.sort = sort;
dirFileTable.reloadTable({table: dirFileTable.table})
})
// 查看按钮监听
dirFileTable.addTableRowEvent('details-file', function (obj) {
openMaxLayerWithURL(`${ctx}/sys/file/view?fileId=${obj.id}`)
})
new THeadSetLayer(dirFileTable, layui);
}
/**
@ -273,15 +309,13 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
$('#condition-div').slideToggle(100, 'linear', conditionSlideToggle)
});
if (!tagSelector) {
tagSelector = new MarkerSelector('#mark-selector-input');
}
tagSelector.bindBtnEvent()
tagSelector.onOkBtn(data => {
tags = data
setMarkTagInputValue();
});
$('#mark-selector-input').on('click', function () {
DataLabel.openChooseDialog(null, null, null, true).then((labels) => {
tags = labels || [];
setMarkTagInputValue();
})
})
// 监听标签点击事件
element.on('tab(condition-tab)', function (data) {
// 点击后移除选中样式
@ -296,6 +330,9 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
// 监听条件标签删除事件
element.on('tabDelete(condition-tab)', function (data) {
let key = $(this).parent().data('key');
if (key === 'markTag') {
tags = [];
}
let formVal = form.val('search-form');
formVal[key] = '';
form.val('search-form', formVal);
@ -310,7 +347,7 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
$('#condition-clear-btn').on('click', function () {
$('#searchKeyInput').val('');
tags = [];
unchecked_tags = [];
unchecked_tags.clear();
conditions = [];
beginSearch();
});
@ -342,9 +379,7 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
function setMarkTagInputValue() {
let temp = [];
for (let tag of tags) {
let arr = tag.split('-');
let text = tag.replace(arr[0] + '-' + arr[1] + '-', '');
temp.push(text);
temp.push(tag.title);
}
$('#mark-selector-input').val(temp.join(', '));
}
@ -370,7 +405,7 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
let htm = '';
conditions = [];
for (let key in formVal) {
if (key == 'searchKeyInput') continue;
if (key === 'searchKeyInput') continue;
let fieldName = key, fieldValue = formVal[key], logicJudgement;
// 如果fieldName是条件下拉框,则跳过
if (fieldName.startsWith('logic-') || fieldName === 'directoryId' || fieldName === 'metadataId') continue;
@ -397,11 +432,11 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
condition = '包含';
}
if (fieldName == 'secretLevel') {
if (fieldName === 'secretLevel') {
hasText = $(`select[name="secretLevel"] option[value="${fieldValue}"]`).text();
} else if (fieldName == 'dataFrom') {
} else if (fieldName === 'dataFrom') {
hasText = $(`select[name="dataFrom"] option[value="${fieldValue}"]`).text();
} else if (fieldName == 'dataType') {
} else if (fieldName === 'dataType') {
hasText = $(`select[name="dataType"] option[value="${fieldValue}"]`).text();
}
conditions.push({fieldName, fieldValue, logicJudgement})
@ -409,40 +444,29 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
}
}
let temp = [];
let tag_htm = '';
for (let tag of tags) {
let tag_arr = tag.split('-');
let tag_type = tag_arr[1], tag_text = tag_arr[2], temp_tags = temp[tag_type];
if (!temp_tags) {
temp_tags = []
}
temp_tags.push({id: tag_arr[0], text: tag_text});
temp[tag_type] = temp_tags;
}
for (let type in temp) {
let tag_type = type, tag_items = temp[type], tag_htm = '';
for (let item of tag_items) {
let val = item.id + '-' + item.text, checked = 'checked';
if (unchecked_tags.includes(val)) {
let checked = 'checked';
if (unchecked_tags.has(tag.id + '')) {
checked = '';
}
tag_htm += `<input type="checkbox" title="${item.text}" value="${val}" ${checked} lay-skin="primary">`;
tag_htm += `<input type="checkbox" title="${tag.title}" value="${tag.id}" ${checked} lay-skin="primary">`;
}
htm += `<li data-key="markTag">${tag_type}${tag_htm}</li>`;
if (tag_htm) {
htm += `<li data-key="markTag">置标标签:${tag_htm}</li>`;
}
$('#condition-tab ul').html(htm);
element.render('tab');
$('#condition-tab ul li[data-key="markTag"] i').remove();
$('#condition-tab ul li[data-key="markTag"] i').css({'margin-left': '-10px'});
form.render('checkbox');
$('li[data-key="markTag"] .layui-form-checkbox').on('click', function () {
let val = $(this).prev().val(), index = unchecked_tags.indexOf(val);
if (!$(this).hasClass('layui-form-checked')) {
unchecked_tags.push(val);
} else if (index > -1) {
unchecked_tags.splice(index, 1)
let val = $(this).prev().val();
if (unchecked_tags.has(val)) {
unchecked_tags.delete(val);
} else {
unchecked_tags.add(val);
}
beginSearch();
})
@ -453,7 +477,6 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
}
}
function beginSearch() {
setMarkTagsValue()
metaListTable.where.conditions = conditions;
@ -492,3 +515,97 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop
});
}
})
/**
* 表格表头配置组件
*/
class THeadSetLayer {
constructor(pageTable, lay) {
this.layer = lay.layer;
this.form = lay.form;
this.gtable = lay.gtable;
this.pageTable = pageTable;
this.id = pageTable.id + 'Set';
this.pageTable.addTableRowEvent('theadSet', () => this.show())
}
show() {
const {layer, pageTable, id} = this;
layer.open({
id: id + 'Layer',
title: '数据列表配置',
type: 1,
area: ['1000px', '700px'],
shadeClose: true,
maxmin: false,
anim: 0,
content: `<table id="${id}" lay-filter="${id}"></table>`,
btn: ['保存', '取消'],
success: () => {
this._renderInnerTable();
},
yes: (layerIndex) => {
this._saveTheadSet().then(() => {
pageTable.reloadTable();
layer.close(layerIndex);
})
}
});
}
_renderInnerTable() {
const {gtable, form, id} = this;
gtable.init({
id,
data: [...sourceTableConfigMap.values()],
method: 'get',
toolbar: false,
height: 'full-310',
page: false,
cols: [[
{field: 'id', hide: true},
{field: 'colName', title: '列名'},
{field: 'colTitle', title: '列标题', edit: 'text'},
{field: 'colSort', title: '列顺序', edit: 'text'},
{field: 'colWidth', title: '列宽度', edit: 'text'},
{
field: 'isSort',
title: '是否允许排序',
templet: (data) => renderSwitch('isSort', data)
},
{
field: 'isShow',
title: '是否显示',
templet: (data) => renderSwitch('isShow', data)
}
]],
});
gtable.on(`edit(${id})`, ({field, value, data}) => {
sourceTableConfigMap.get(data.id)[field] = value;
})
// 监听switch按钮
form.on(`switch(${id}-switch)`, ({elem}) => {
const id = $(elem).attr('id'), name = $(elem).attr('name');
const value = sourceTableConfigMap.get(id)[name];
sourceTableConfigMap.get(id)[name] = !value;
});
function renderSwitch(colName, data) {
const dataId = data.id, value = data[colName];
return `<input type="checkbox" id="${dataId}" name="${colName}" value="${value}" title="是|否" lay-skin="switch" lay-filter="${id}-switch" ${value ? 'checked' : ''} />`
}
}
_saveTheadSet() {
return new Promise(resolve => {
Util.post(`/sys/thead/config/api/save`, {params: JSON.stringify([...sourceTableConfigMap.values()])}).then(res=>{
if(res.flag){
showOkMsg('保存成功')
}else{
showErrorMsg2('保存失败:'+res.msg)
}
})
resolve();
})
}
}

@ -36,6 +36,7 @@ layui.use(['dropdown', 'gtable', 'laydate', 'form'], function () {
cols: [cols],
limit: 20,
toolbar: '#table-title',
request:{pageName: 'page', limitName: 'size'},
defaultToolbar: ['filter', 'print', 'exports', {
title: '统计报表',
layEvent: 'tong-ji',
@ -194,7 +195,7 @@ layui.use(['dropdown', 'gtable', 'laydate', 'form'], function () {
let id = $(this).data('id');
$condition_list.find(`li[id="li_${id}"]`).remove();
$condition_list.find(`li:first a[name="${LOGIC_JOIN}"]`).addClass("layui-hide").data('value', 'and');
if ($condition_list.find('li').length == 0) {
if ($condition_list.find('li').length === 0) {
$condition_list.find('p.condition-none').removeClass('layui-hide');
}
});

@ -63,7 +63,7 @@ ReportComponent.prototype.openEchartsConfigLayer = function () {
$('#echartsConfigForm').parent().css('overflow', 'visible')
},
yes: function (index) {
_this.requestData(()=> layer.close(index));
_this.requestData(() => layer.close(index));
}
});
}
@ -203,12 +203,15 @@ ReportComponent.prototype.validate = function (formVal) {
if (!formVal.aggregationType) {
showErrorMsg('请设置聚合方式');
return;
} else {
}
if ((formVal.aggregationType == 'sum' || formVal.aggregationType == 'avg') && !formVal.fieldY) {
showErrorMsg('请设置聚合字段');
return;
}
if(formVal.aggregationType == 'count' && !formVal.fieldY){
formVal.fieldY = formVal.fieldX;
}
return true;
}

@ -11,6 +11,18 @@
<link rel="stylesheet" th:href="@{/css/browser.css}"/>
<script th:inline="javascript">
const bus_type = 0;
const resourceTableId = 'browser_resource_table',
fileTableId = 'browser_file_table',
theadConfig = /*[[${theadConfig}]]*/ [];
const sourceTableConfigMap = new Map(), fileTableConfigMap = new Map();
theadConfig.forEach(item => {
if (item.tableId === resourceTableId) {
sourceTableConfigMap.set(item.id, item);
} else if (item.tableId === fileTableId) {
fileTableConfigMap.set(item.id, item);
}
});
</script>
</head>
<body onselectstart="return false">
@ -79,18 +91,23 @@
<div class="current-position">当前位置:<label></label></div>
<table class="layui-hide" id="dirMetadataTable" lay-filter="dirMetadataTable"></table>
<script type="text/html" id="tableToolBar">
<div class="layui-form" lay-filter="search-form" style="display: flex;flex-direction: column;">
<div class="layui-btn-container" style="display: flex; justify-content: flex-start; margin-bottom: 0">
<div class="layui-form" lay-filter="search-form"
style="display: flex;flex-direction: column;">
<div class="layui-btn-container"
style="display: flex; justify-content: flex-start; margin-bottom: 0">
<div style="position: unset;">
<input type="text" id="searchKeyInput" name="searchKeyInput"
autocomplete="off"
placeholder="请输入关键字查询" class="layui-input layui-btn-sm">
<button class="layui-btn layui-btn-sm" id="begin-search-btn" lay-event="query">查询</button>
<button class="layui-btn layui-btn-sm" id="begin-search-btn"
lay-event="query">查询
</button>
</div>
<div style="position: unset;">
<button class="layui-btn layui-btn-primary layui-border-green"
style="border: 0"
id="condition-btn">更多条件<i class="layui-icon layui-icon-down"></i>
id="condition-btn">更多条件<i
class="layui-icon layui-icon-down"></i>
</button>
<button class="layui-btn layui-btn-primary layui-border-green"
style="border: 0;padding:0;margin:0"
@ -106,7 +123,8 @@
<div class="layui-input-inline">
<input type="text" id="input-date-begin" name="inputDate"
autocomplete="off"
class="layui-input input-date c-input" placeholder="选择日期范围"/>
class="layui-input input-date c-input"
placeholder="选择日期范围"/>
</div>
</div>
<div class="layui-inline">
@ -117,7 +135,8 @@
<option value="nq">不等于</option>
<!--<option value="like">包含</option>-->
</select>
<div dict-component="select" dict-type="data_source" dict-name="dataFrom" id="dict-data-form"></div>
<div dict-component="select" dict-type="data_source"
dict-name="dataFrom" id="dict-data-form"></div>
</div>
</div>
<div class="layui-inline">
@ -128,11 +147,13 @@
<option value="nq">不等于</option>
<!--<option value="like">包含</option>-->
</select>
<div dict-component="select" dict-type="data_type" dict-name="dataType" id="dict-data-type"></div>
<div dict-component="select" dict-type="data_type"
dict-name="dataType" id="dict-data-type"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" label-name="secretLevel">数据密级</label>
<label class="layui-form-label"
label-name="secretLevel">数据密级</label>
<div class="layui-input-inline"
style="width: 80px;height: 38px; margin-right: -1px;">
<select name="logic-secretLevel" lay-verify="select-condition">
@ -142,14 +163,16 @@
<option value="lt">小于</option>
</select>
</div>
<div dict-component="select" dict-type="secret_level" dict-name="secretLevel" id="dict-secret-level"></div>
<div dict-component="select" dict-type="secret_level"
dict-name="secretLevel" id="dict-secret-level"></div>
</div>
<div class="layui-inline">
<label class="layui-form-label" label-name="mark">置标标签</label>
<div class="layui-input-inline mark-selector" style="width: 340px;">
<div class="layui-unselect layui-form-select">
<div class="layui-select-title">
<input placeholder="请选择" id="mark-selector-input" readonly
<input placeholder="请选择" id="mark-selector-input"
readonly
type="text" class="layui-input layui-unselect">
<i class="layui-edge"></i>
</div>
@ -157,13 +180,15 @@
</div>
</div>
</div>
<div class="layui-form-item" style="justify-content: center; align-items: center">
<div class="layui-form-item"
style="justify-content: center; align-items: center">
<button class="layui-btn layui-border-green"
style="height: 20px;line-height: 16px; color: #FFFFFF !important;margin-right: 10px; padding: 0 10px"
onclick="$(`#condition-btn`).click()">确定
</button>
<button class="layui-btn layui-btn-primary layui-border-green"
style="border: 0;padding:0;margin:0;height: 16px;line-height: 16px;" id="condition-cancel-btn">取消
style="border: 0;padding:0;margin:0;height: 16px;line-height: 16px;"
id="condition-cancel-btn">取消
</button>
</div>
</div>
@ -180,7 +205,8 @@
</div>-->
</div>
</div>
<div id="mengban" style="width: 100%; display: none; height: 100%; position: fixed; top:0px; left: 0px; background: #0C0C0C47; z-index: 1"></div>
<div id="mengban"
style="width: 100%; display: none; height: 100%; position: fixed; top:0px; left: 0px; background: #0C0C0C47; z-index: 1"></div>
</script>
<script type="text/html" id="rowToolBar">
<div class="layui-btn-container">
@ -204,7 +230,8 @@
</script>
<script type="text/html" id="fileRowToolBar">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-xs remove-link" lay-event="details-file">查看</button>
<button class="layui-btn layui-btn-xs remove-link" lay-event="details-file">查看
</button>
</div>
</script>
</div>
@ -219,7 +246,6 @@
<!-- js -->
<script th:replace="common/head::static-foot"></script>
<script th:src="@{/js/business/mark/markTag.js}"></script>
<script th:src="@{/js/marker_selector.js}"></script>
<script th:src="@{/js/browser.js}"></script>
<script th:src="@{/js/view.js}"></script>
<script type="text/javascript">

@ -57,6 +57,10 @@ public class TreeVo implements Serializable {
* 选中状态
*/
private String checked = "0";
/**
* 加载顺序
*/
private int sort;
/**
* 节点原始数据
*/

@ -5,6 +5,7 @@ import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.text.Collator;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@ -29,6 +30,7 @@ public class TreeUtil {
.filter(node -> (node.getParentId().equals(parentId)))
// 给子节点设置子节点
.peek(child -> child.setChildren(buildDirTree(nodes, child.getId())))
.sorted(Comparator.comparingInt(TreeVo::getSort))
.toList();
}

@ -291,3 +291,21 @@ fieldset a, fieldset a:hover{
top: 0;
font-size: 20px;
}
.dynamic-form{
display: flex;
max-width: 100%;
flex-flow: wrap;
}
.dynamic-form .layui-form-item{
display: flex;
justify-content: center;
width: calc(50% - 20px);
margin-left: 10px;
}
.dynamic-form .layui-form-label{
width: 100px;
}
.dynamic-form .layui-input-block{
margin-left: 0;
flex: 1;
}

@ -14,7 +14,7 @@ layui.define(['globalTree'], function (exports) {
labelId = newLabel.id;
label = newLabel.titlePathWithSelf;
}
if(label && label !== '/'){
if (label && label !== '/') {
label = label.endsWith("/") ? label.substring(0, label.length - 1) : label;
let temp = {
entityId,
@ -59,9 +59,9 @@ layui.define(['globalTree'], function (exports) {
}
setData(data) {
if(data){
if (data) {
let path = data.label.replace(this.fixedTitlePath, '');
if(path !== '/'){
if (path !== '/') {
this.newLabel = {id: data.labelId, titlePathWithSelf: path}
}
this.render();
@ -118,8 +118,7 @@ layui.define(['globalTree'], function (exports) {
function addEventListen() {
$elem.find('.choose-data').on('click', function () {
let labelId = $(this).data('labelId') || 0;
labelId = labelId === 'undefined' ? 0 : labelId;
chooseLabelData(labelId, fixedTitlePath, labelIdPath).then(data => {
chooseLabelData(labelId, labelIdPath).then(data => {
component.newLabel = data;
renderLabelElement(component);
});
@ -136,7 +135,18 @@ layui.define(['globalTree'], function (exports) {
}
}
function chooseLabelData(labelId, titlePath, idPath) {
/**
* 显示置标标签选择窗口
* @param labelId {String} 上级置标标签ID为空则查询所有
* @param idPath {String} 上级标签的id路径用于默认勾选和设置为不可选
* @param chooseIds {String | String[]} 默认选中的ID集合逗号拼接的数组或者字符数组
* @param multiple {Boolean} 多选
* @returns {Promise<Object>}
*/
function chooseLabelData(labelId, idPath, chooseIds, multiple) {
if (!labelId || labelId === 'undefined') {
labelId = 0;
}
return new Promise(resolve => {
layer.open({
type: 1,
@ -160,17 +170,27 @@ layui.define(['globalTree'], function (exports) {
all: true,
cache: true,
checkbar: true,
checkbarType: 'only',
checkbarType: multiple ? 'no-all' : 'only',
scroll: '#label-tree',
done: function () {
let _chooseIds = [];
if (disableIds.length > 0) {
treeObj.chooseDataInit(disableIds.join(','));
_chooseIds.concat(disableIds);
treeObj.setDisabledNodes(disableIds.join(','));
}
if (chooseIds) {
_chooseIds.concat(Array.isArray(chooseIds) ? chooseIds : chooseIds.split(','));
}
treeObj.chooseDataInit(disableIds.join(','));
$('#layerCancel').on('click', () => layer.close(index));
$('#layerOk').on('click', () => {
if (treeObj.chooseNodes && treeObj.chooseNodes.length > 0) {
resolve && resolve(treeObj.chooseNodes[0].basicData);
const nodes = treeObj.chooseNodes;
if (nodes && nodes.length > 0) {
let return_data = nodes.map(node => node.basicData);
if (!multiple) {
resolve(return_data[0]);
}
resolve(return_data);
layer.close(index);
} else {
showErrorMsg('请选择一条数据')
@ -182,7 +202,21 @@ layui.define(['globalTree'], function (exports) {
if (disableIds.length > 0) {
treeObj.chooseDataInit(disableIds.join(','));
}
const chooseNodes = treeObj.chooseNodes;
if (!multiple) {
treeObj.chooseNodes = nodes;
} else {
const nodeMap = new Map();
const choosePids = nodes.map(n => n.id);
// 如果包含选中节点中包含上下级关系,则在选中节点中去掉上级节点
for(const node of nodes){
if(nodeMap.has(node.parentId)){
nodeMap.delete(node.parentId);
}
nodeMap.set(node.id, node)
}
treeObj.chooseNodes = [...nodeMap.values()];
}
}
}
});
@ -215,9 +249,9 @@ layui.define(['globalTree'], function (exports) {
});
}
function addOtherLabel(value) {
let template = `<div class="layui-input-block label-set-component other-label" th:data-field-title="其他标签"></div>`;
$('.other-label-item').append(template);
function addOtherLabel(value, readonly) {
let template = `<div class="label-set-component other-label ${readonly?'read-only':''}" th:data-field-title="其他标签"></div>`;
$('.other-label-item.layui-input-block').append(template);
let cid = _KEY + _CACHE.size,
component = new Component(cid, $('.label-set-component.other-label:last'));
@ -238,15 +272,16 @@ layui.define(['globalTree'], function (exports) {
function setData(dataArr = []) {
for (let data of dataArr) {
let find = false;
let find = false, readonly = false;
for (let component of _CACHE.values()) {
readonly = component.isReadOnly();
if (data.fieldTitle !== '其他标签' && data.fieldTitle === component.fieldTitle) {
component.setData(data);
find = true;
}
}
if (!find) {
addOtherLabel(data);
addOtherLabel(data, readonly);
}
}
}
@ -256,6 +291,7 @@ layui.define(['globalTree'], function (exports) {
const _exports = {
getData: (entityId, entityType) => _CACHE.getData(entityId, entityType),
setData,
openChooseDialog: chooseLabelData
};
exports('datalabel', _exports)
})

@ -52,6 +52,7 @@ layui.define(['form'], function (exports) {
data = '';// 选中的数据
change;// 数据改变后的回调函数
readonly;// 是否只读
disabled; // 是否禁用
width;// 宽度
constructor(type, options) {
@ -82,7 +83,8 @@ layui.define(['form'], function (exports) {
this.change = options.onchange || function () {
};
this.readonly = options.readonly;
this.width = options.width || 'fit-content';
this.disabled = options.disabled;
this.width = options.width || '100%';
// 开始渲染
this.render();
@ -249,7 +251,7 @@ layui.define(['form'], function (exports) {
}
let nodes_html = nodes.join('');
return `<select id="${_this.id}" name="${_this.name}" lay-filter="${_this.id}">${nodes_html}</select>`;
return `<select id="${_this.id}" name="${_this.name}" lay-filter="${_this.id}" ${_this.readonly ? 'readonly="readonly"' : ''} ${_this.disabled ? 'disabled="disabled"' : ''}>${nodes_html}</select>`;
}
/**
@ -304,11 +306,12 @@ layui.define(['form'], function (exports) {
type = _elem.attr('dict-type'),
dictType = _elem.attr('dict-component'),
readonly = _elem.attr('readonly'),
disabled = _elem.attr('disabled'),
data = _elem.attr('data'),
width = _elem.attr('dict-width'),
formFilter = getFormElementFilter(_elem);
let option = {elem, id, name, type, formFilter, readonly, data, width};
let option = {elem, id, name, type, formFilter, readonly, disabled, data, width};
new DictComponent(dictType, option)
});
}

@ -34,6 +34,10 @@
USER_ROLES.push(role.roleName);
}
}
// 表单配置
const METADATA_FORM_CONFIG = /*[[${metadataFormConfig}]]*/ [];
const FILEUPLOAD_FORM_CONFIG = /*[[${uploadFormConfig}]]*/ [];
</script>
<!-- 引入公用库 -->

@ -7,8 +7,11 @@ import com.keyware.shandan.system.entity.SysMenu;
import com.keyware.shandan.system.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Component
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
public class DynamicFormListener implements DynamicFormEventListener {
@Autowired
@ -21,7 +24,7 @@ public class DynamicFormListener implements DynamicFormEventListener {
menu.setMenuId(form.getId().toString());
menu.setParentMenu(parentMenu);
menu.setMenuParentId(parentMenu.getMenuId());
menu.setMenuName(form.getFormName() + "管理");
menu.setMenuName(form.getFormName());
menu.setMenuPath("/dynamic-data/view/data/list/" + form.getId());
menu.setSystem(parentMenu.getSystem());
menu.setMenuParentName(parentMenu.getMenuName());

@ -25,10 +25,6 @@ spring:
rest:
uris: http://192.168.134.128:9200
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
security:
oauth2:
client:
@ -51,4 +47,4 @@ project:
logging:
level:
root: debug
com.keyware: debug

@ -48,7 +48,6 @@ security:
user-authorization-uri: ${oauth.server.proxy}/oauth/authorize
resource:
user-info-uri: ${oauth.server.internal}/oauth/user/info
logging:
level:
root: debug
com.keyware: debug

@ -1,6 +1,7 @@
package com.keyware.shandan.bianmu.controller;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.keyware.shandan.bianmu.entity.DirectoryResource;
import com.keyware.shandan.bianmu.entity.DirectoryVo;
@ -12,6 +13,9 @@ import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.datasource.entity.DBTableColumnVo;
import com.keyware.shandan.datasource.entity.DataSourceVo;
import com.keyware.shandan.datasource.service.DataSourceService;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.system.entity.SysFormConfig;
import com.keyware.shandan.system.service.SysFormConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -50,6 +54,9 @@ public class MetadataCommonController {
@Autowired
private DataLabelsService labelsService;
@Autowired
private SysFormConfigService formConfigService;
/**
* 数据资源详细信息页面
*
@ -74,6 +81,8 @@ public class MetadataCommonController {
mav.addObject("exampleList", exampleData.getRecords());
mav.addObject("LabelConfigSet", labelsService.formConfigList());
mav.addObject("metadataFormConfig", formConfigService.listByFormType(FormTypeEnum.metadataEditForm));
return mav;
}

@ -3,7 +3,6 @@ package com.keyware.shandan.bianmu.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.keyware.shandan.common.entity.BaseEntity;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.utils.StringUtil;
import lombok.*;
import java.util.Date;
@ -74,6 +73,13 @@ public class DataLabelsVo extends BaseEntity {
@OrderBy(isDesc = false, sort = 1)
private Boolean isLabel;
/**
* 渲染顺序
*/
@TableField(value = "SORT")
@OrderBy(isDesc = false)
private Integer sort;
/**
* 创建时间
*/
@ -91,7 +97,7 @@ public class DataLabelsVo extends BaseEntity {
return "";
}
public String getTitlePathWithSelf(){
public String getTitlePathWithSelf() {
if (StringUtils.hasText(titlePath)) {
return titlePath + title + "/";
}

@ -130,21 +130,9 @@ public class DirectoryVo extends BaseEntity {
@OrderBy(isDesc = false)
private Date createTime;
/**
* 所属部门对象
*/
/*@TableField(exist = false)
private SysOrg org;*/
@TableField(exist = false)
private String modifyUserName;
/**
* 是否有子级
*/
/*@TableField(exist = false)
private Boolean hasChild;*/
/**
* 子级目录
*/
@ -157,6 +145,12 @@ public class DirectoryVo extends BaseEntity {
@TableField(exist = false)
private boolean applyChild;
/**
* 目录顺序
*/
@TableField(value = "SORT")
private Integer sort;
/**
* 创建人名称
*/

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.keyware.shandan.common.util.MD5Util;
import lombok.*;
import org.apache.ibatis.annotations.One;
import org.springframework.util.StringUtils;
import java.io.Serializable;
@ -42,6 +43,9 @@ public class LabelEntity implements Serializable {
@TableField("LABEL")
private String label;
@TableField(exist = false)
private DataLabelsVo data;
public String getId() {
if (StringUtils.hasText(id)) {
return id;

@ -2,9 +2,9 @@ package com.keyware.shandan.bianmu.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.keyware.shandan.bianmu.entity.LabelEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.*;
import java.io.Serializable;
import java.util.List;
/**
@ -14,6 +14,21 @@ import java.util.List;
@Mapper
public interface LabelEntityMapper extends BaseMapper<LabelEntity> {
@Override
@Results(id="all_result_map", value = {
@Result(id = true, column = "ID", property = "id"),
@Result(column = "ENTITY_ID", property = "entityId"),
@Result(column = "ENTITY_TYPE", property = "entityType"),
@Result(column = "LABEL_ID", property = "labelId"),
@Result(column = "FIELD_TITLE", property = "fieldTitle"),
@Result(column = "LABEL", property = "label"),
@Result(column = "LABEL_ID", property = "data", one = @One(select = "com.keyware.shandan.bianmu.mapper.DataLabelsMapper.selectById"))
})
@Select("SELECT * FROM B_DATA_LABEL_ENTITY WHERE ID = #{id}")
LabelEntity selectById(Serializable id);
@ResultMap(value = {"all_result_map"})
@Select("SELECT * FROM B_DATA_LABEL_ENTITY WHERE ENTITY_ID = #{entityId}")
List<LabelEntity> selectByEntityId(String entityId);
}

@ -53,15 +53,41 @@ public class DirectoryTreeService {
if (StringUtils.hasText(pid)) {
parentDir = directoryService.getById(pid);
}
// 获取子级节点
List<DirectoryVo> directoryList = getDirectoryList(parentDir, allChild, hasMetadata, busType);
// 审核状态
ReviewStatus status = StringUtils.hasText(reviewStatus) ? ReviewStatus.valueOf(reviewStatus) : null;
// 当前用户
SysUser user = SecurityUtil.getLoginSysUser();
// 根据权限类型获取权限范围内的数据的ID集合
Set<String> permisDis = "write".equals(permis) ? dirPermissionService.getByWritePermis(user) : dirPermissionService.getByReadPermis(user);
// 判断权限范围
List<DirectoryVo> permisDirectoryList = StreamUtil.as(directoryList).filter(dir -> {
if (status == null) {
return permisDis.contains(dir.getId());
if (dir.getDirectoryType() == DirectoryType.FILE
|| dir.getDirectoryType() == DirectoryType.LINK_FILE
|| dir.getDirectoryType() == DirectoryType.METADATA
|| dir.getDirectoryType() == DirectoryType.LINK_METADATA) {
return true;
}
return dir.getReviewStatus() == status && permisDis.contains(dir.getId());
if (dir.getReviewStatus() == status || status == null) {
boolean permisAllow = permisDis.contains(dir.getId());
if (permisAllow) {
return true;
}
// 如果权限不允许,则需要判断当前节点的所有子级节点是否有允许的目录,如果有则需要返回到前端的树组件中
Set<String> childrenIds = getDirectoryList(dir, true, false, busType)
.stream()
.map(DirectoryVo::getId)
.collect(Collectors.toSet());
for (String id : childrenIds) {
if (permisDis.contains(id)) {
return true;
}
}
return false;
}
return false;
}).toList();
DirectoryParentBuilder dpb = new DirectoryParentBuilder(directoryList, permisDirectoryList);
@ -87,9 +113,9 @@ public class DirectoryTreeService {
*/
private List<DirectoryVo> getDirectoryList(DirectoryVo parentDir, boolean allChild, boolean hasResource, int busType) {
QueryWrapper<DirectoryVo> wrapper = new QueryWrapper<>();
if(parentDir == null){
if (parentDir == null) {
wrapper.eq("ID", "ROOT");
}else {
} else {
wrapper.in(!hasResource, "DIRECTORY_TYPE", DirectoryType.DIRECTORY, DirectoryType.LINK_DIR).eq("IS_BASIC_DIR", busType);
if (parentDir != null) {
if (allChild) {

@ -29,13 +29,14 @@ public class DirectoryUtil {
tree.setType("DIRECTORY");
tree.setPath(dir.getDirectoryPath());
tree.setBasicData(dir);
if(dir.getDirectoryType() == DirectoryType.FILE || dir.getDirectoryType() == DirectoryType.LINK_FILE){
tree.setSort(dir.getSort() == null ? Integer.MAX_VALUE : dir.getSort());
if (dir.getDirectoryType() == DirectoryType.FILE || dir.getDirectoryType() == DirectoryType.LINK_FILE) {
tree.setIconClass("dtree-icon-normal-file");
tree.setLast(true);
}else if(dir.getDirectoryType() == DirectoryType.METADATA || dir.getDirectoryType() == DirectoryType.LINK_METADATA){
} else if (dir.getDirectoryType() == DirectoryType.METADATA || dir.getDirectoryType() == DirectoryType.LINK_METADATA) {
tree.setIconClass("dtree-icon-sort");
tree.setLast(true);
}else{
} else {
tree.setLast(false);
}
}

@ -6,8 +6,10 @@ import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.util.*;
import com.keyware.shandan.frame.config.security.SecurityUtil;
import com.keyware.shandan.frame.properties.CustomProperties;
import com.keyware.shandan.system.entity.SysFormConfig;
import com.keyware.shandan.system.entity.SysRole;
import com.keyware.shandan.system.entity.SysUser;
import com.keyware.shandan.system.service.SysFormConfigService;
import com.keyware.shandan.system.service.SysRoleService;
import com.keyware.shandan.system.utils.SysSettingUtil;
import lombok.extern.slf4j.Slf4j;
@ -25,7 +27,9 @@ import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* AES + RSA 加解密AOP处理
@ -44,6 +48,9 @@ public class SafetyAspect {
@Autowired
private SysRoleService sysRoleService;
@Autowired
private SysFormConfigService formConfigService;
/**
* Pointcut 切入点
*/
@ -80,7 +87,7 @@ public class SafetyAspect {
Object result = joinPoint.proceed(AspectUtil.parseJoinPointArgs(joinPoint, request));
//执行方法之前解密,且只拦截post请求
if ("post".equalsIgnoreCase(request.getMethod()) && !ServletFileUpload.isMultipartContent(request)) {
if ("post".equalsIgnoreCase(request.getMethod()) && !ServletFileUpload.isMultipartContent(request) && StringUtils.hasText(publicKey)) {
// 返回之前对结果进行加密
//每次响应之前随机获取AES的key,加密data数据
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@ -121,6 +128,10 @@ public class SafetyAspect {
}
//展示用户角色
modelAndView.addObject("userRole", userRoles.get(index));
List<SysFormConfig> formConfigList = formConfigService.list();
modelAndView.addObject("metadataFormConfig", formConfigList.stream().filter(conf -> conf.getFormType() == 1).collect(Collectors.toList()));
modelAndView.addObject("uploadFormConfig", formConfigList.stream().filter(conf -> conf.getFormType() == 2).collect(Collectors.toList()));
setStaticResourceAddress(request, modelAndView);
}
return result;

@ -1,6 +1,6 @@
package com.keyware.shandan.mark.controller;
import com.keyware.shandan.mark.constant.FormTypeEnum;
import com.keyware.shandan.system.constants.FormTypeEnum;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@ -1,7 +1,7 @@
package com.keyware.shandan.mark.services;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.keyware.shandan.mark.constant.FormTypeEnum;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.mark.pojo.FormMark;
import com.keyware.shandan.mark.pojo.MarkRecord;
import com.keyware.shandan.mark.pojo.MarkType;

@ -1,5 +1,6 @@
package com.keyware.shandan.mark.constant;
package com.keyware.shandan.system.constants;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -16,16 +17,19 @@ public enum FormTypeEnum {
/**
* 数据资源注册表单
*/
metadataEditForm("数据资源注册表单"),
metadataEditForm(1,"数据资源注册表单"),
/**
* 文件上传表单
*/
fileUploadForm("文件上传表单"),
fileUploadForm(2, "文件上传表单"),
/**
* 文件夹上传表单
*/
@Deprecated
dirUploadForm("文件夹上传表单");
dirUploadForm(3, "文件夹上传表单");
@EnumValue
private final Integer value;
/**
* 描述

@ -8,10 +8,12 @@ import com.keyware.shandan.common.controller.BaseController;
import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.util.FileDownload;
import com.keyware.shandan.frame.properties.CustomProperties;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.system.entity.SysFile;
import com.keyware.shandan.system.entity.SysFileChunk;
import com.keyware.shandan.system.entity.SysSetting;
import com.keyware.shandan.system.service.SysFileService;
import com.keyware.shandan.system.service.SysFormConfigService;
import com.keyware.shandan.system.service.SysSettingService;
import com.keyware.shandan.system.utils.FileChunkUploadUtil;
import org.apache.tomcat.util.http.ResponseUtil;
@ -57,12 +59,16 @@ public class SysFileController extends BaseController<SysFileService, SysFile, S
@Autowired
private DataLabelsService labelsService;
@Autowired
private SysFormConfigService formConfigService;
@GetMapping("/layer")
public ModelAndView fileUploadLayer(ModelAndView mav) {
mav.setViewName("sys/file/fileUploadLayer");
mav.addObject("LabelConfigSet", labelsService.formConfigList());
mav.addObject("uploadFormConfig", formConfigService.listByFormType(FormTypeEnum.fileUploadForm));
return mav;
}

@ -0,0 +1,57 @@
package com.keyware.shandan.system.controller;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.system.entity.SysFormConfig;
import com.keyware.shandan.system.service.SysFormConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
/**
* 系统表单配置模块前端控制类
*
* @author GuoXin
* @date 2023/8/23
*/
@Slf4j
@RestController
@RequestMapping("/sys/form/config")
public class SysFormConfigController {
private final SysFormConfigService formConfigService;
public SysFormConfigController(SysFormConfigService formConfigService) {
this.formConfigService = formConfigService;
}
@GetMapping("/page/index")
public ModelAndView indexPage(ModelAndView mav) {
mav.setViewName("sys/form/formConfig");
return mav;
}
@GetMapping("/api/get/{id}")
public Result<SysFormConfig> getById(@PathVariable String id) {
return Result.of(formConfigService.getById(id));
}
@GetMapping("/api/list/{formType}")
public Result<List<SysFormConfig>> list(@PathVariable String formType) {
QueryWrapper<SysFormConfig> query = new QueryWrapper<>();
query.eq("FORM_TYPE", formType);
return Result.of(formConfigService.list(query));
}
@PostMapping(value = "/api/save")
public Result<Object> save(String params) {
JSONArray jsonArray = JSONUtil.parseArray(params);
List<SysFormConfig> list = jsonArray.toList(SysFormConfig.class);
return Result.of(formConfigService.saveOrUpdateBatch(list));
}
}

@ -0,0 +1,42 @@
package com.keyware.shandan.system.controller;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.entity.SysTheadConfig;
import com.keyware.shandan.system.service.SysTheadConfigService;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 前端数据表格表头配置前端控制器
*
* @author GuoXin
* @date 2023/8/30
*/
@RestController
@RequestMapping("/sys/thead/config")
public class SysTheadConfigController {
private final SysTheadConfigService theadConfigService;
public SysTheadConfigController(SysTheadConfigService theadConfigService) {
this.theadConfigService = theadConfigService;
}
@PostMapping(value = "/api/save")
public Result<Object> save(String params, Authentication auth) {
JSONArray jsonArray = JSONUtil.parseArray(params);
List<SysTheadConfig> list = jsonArray.toList(SysTheadConfig.class);
list.forEach(item->{
if(!StringUtils.hasText(item.getId())){
item.genId(auth.getName());
}
});
return Result.of(theadConfigService.saveOrUpdateBatch(list));
}
}

@ -0,0 +1,66 @@
package com.keyware.shandan.system.entity;
import com.baomidou.mybatisplus.annotation.OrderBy;
import com.keyware.shandan.common.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 系统表单配置实体类
*
* @author GuoXin
* @date 2023/8/23
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysFormConfig extends BaseEntity {
private static final long serialVersionUID = 6628747783449277117L;
/**
* 主键
*/
private Integer id;
/**
* 表单类型1-资源注册表单2-文件上传表单
*/
private Integer formType;
/**
* 字段名
*/
private String fieldName;
/**
* 字段显示标题
*/
private String showTitle;
/**
* 字段类型
*/
private String fieldType;
/**
* 数据字典类型只有当fieldType为"dict"时才有效
*/
private String dictType;
/**
* 默认值
*/
private String defaultValue;
/**
* 是否必填0-非必填1-必填
*/
private Boolean isRequired;
/**
* 是否禁用0-不禁用1-禁用
*/
private Boolean isDisabled;
/**
* 是否禁用0-不禁用1-禁用
*/
private Boolean isShow;
/**
* 显示顺序
*/
@OrderBy(isDesc = false)
private Integer sort;
}

@ -0,0 +1,65 @@
package com.keyware.shandan.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.keyware.shandan.common.entity.BaseEntity;
import com.keyware.shandan.common.util.MD5Util;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 前端数据表格表头配置实体类
*
* @author GuoXin
* @date 2023/8/30
*/
@Data
@Builder
@EqualsAndHashCode(callSuper = true)
@TableName("SYS_THEAD_CONFIG")
public class SysTheadConfig extends BaseEntity {
private static final long serialVersionUID = 1480474706145625172L;
/**
* 主键
*/
@TableId(type = IdType.INPUT)
private String id;
/**
* 数据表ID对应前端页面上的layui中table组件的id
*/
private String tableId;
/**
* 列名
*/
private String colName;
/**
* 列标题
*/
private String colTitle;
/**
* 列顺序
*/
@OrderBy(isDesc = false, sort = 2)
private Integer colSort;
/**
* 列宽度
*/
private String colWidth;
/**
* 是否显示
*/
@OrderBy(sort = 1)
private Boolean isShow;
/**
* 是否允许排序
*/
private Boolean isSort;
public void genId(String userName) {
this.id = MD5Util.getMD5(tableId + colName + userName);
}
}

@ -0,0 +1,15 @@
package com.keyware.shandan.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.keyware.shandan.system.entity.SysFormConfig;
import org.apache.ibatis.annotations.Mapper;
/**
* 系统表单配置数据库操作映射
*
* @author GuoXin
* @date 2023/8/23
*/
@Mapper
public interface SysFormConfigMapper extends BaseMapper<SysFormConfig> {
}

@ -0,0 +1,15 @@
package com.keyware.shandan.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.keyware.shandan.system.entity.SysTheadConfig;
import org.apache.ibatis.annotations.Mapper;
/**
* 前端数据表格表头配置数据库操作映射接口
*
* @author GuoXin
* @date 2023/8/30
*/
@Mapper
public interface SysTheadConfigMapper extends BaseMapper<SysTheadConfig> {
}

@ -0,0 +1,18 @@
package com.keyware.shandan.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.system.entity.SysFormConfig;
import java.util.List;
/**
* 系统表单配置服务接口类
*
* @author GuoXin
* @date 2023/8/23
*/
public interface SysFormConfigService extends IService<SysFormConfig> {
List<SysFormConfig> listByFormType(FormTypeEnum formTypeEnum);
}

@ -0,0 +1,16 @@
package com.keyware.shandan.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.keyware.shandan.system.entity.SysTheadConfig;
import java.util.List;
/**
* 前端数据表格表头配置数据库操作接口
*
* @author GuoXin
* @date 2023/8/30
*/
public interface SysTheadConfigService extends IService<SysTheadConfig> {
List<SysTheadConfig> listByCreateUser(String userId);
}

@ -33,7 +33,7 @@ public class SysDictServiceImpl extends BaseServiceImpl<SysDictMapper, SysDict,
return Result.of(null, false, "字典名称已存在");
}
}
entity.setDictCode(entity.getDictName());
entity.setDictCode(entity.getDictValue());
// entity.setDictValue(entity.getDictName());
boolean ok = super.saveOrUpdate(entity);
if(ok){

@ -0,0 +1,27 @@
package com.keyware.shandan.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.system.entity.SysFormConfig;
import com.keyware.shandan.system.mapper.SysFormConfigMapper;
import com.keyware.shandan.system.service.SysFormConfigService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 系统表单配置服务实现类
*
* @author GuoXin
* @date 2023/8/23
*/
@Service
public class SysFormConfigServiceImpl extends ServiceImpl<SysFormConfigMapper, SysFormConfig> implements SysFormConfigService {
@Override
public List<SysFormConfig> listByFormType(FormTypeEnum formTypeEnum) {
QueryWrapper<SysFormConfig> query = new QueryWrapper<>();
query.eq("FORM_TYPE", formTypeEnum.getValue());
return list(query);
}
}

@ -0,0 +1,78 @@
package com.keyware.shandan.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.entity.SysTheadConfig;
import com.keyware.shandan.system.mapper.SysTheadConfigMapper;
import com.keyware.shandan.system.service.SysTheadConfigService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* 前端数据表格表头配置数据库操作接口实现类
*
* @author GuoXin
* @date 2023/8/30
*/
@Service
public class SysTheadConfigServiceImpl extends ServiceImpl<SysTheadConfigMapper, SysTheadConfig> implements SysTheadConfigService {
static final String resourceTableId = "browser_resource_table", fileTableId = "browser_file_table";
static List<SysTheadConfig> defaultConfig = new ArrayList<>();
static {
SysTheadConfig.SysTheadConfigBuilder builder = SysTheadConfig.builder();
// 初始化综合浏览系统资源查询数据表表头默认配置
defaultConfig.add(builder.tableId(resourceTableId).colName("resourceName").colTitle("资源名称").colSort(1).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("resourceComment").colTitle("资源注释").colSort(2).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("directoryPath").colTitle("目录路径").colSort(3).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("themeTask").colTitle("主题任务").colSort(4).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("dataSource").colTitle("数据来源").colSort(5).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("taskTime").colTitle("任务时间").colSort(6).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("dataType").colTitle("数据类型").colSort(7).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("secretLevel").colTitle("数据密级").colSort(8).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(resourceTableId).colName("resourceType").colTitle("资源类型").colSort(9).colWidth("100").isShow(true).isSort(false).build());
// 初始化综合浏览系统文件全文检索数据表表头默认配置
defaultConfig.add(builder.tableId(fileTableId).colName("fileName").colTitle("文件名称").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("fileType").colTitle("文件类型").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("fileSize").colTitle("文件大小").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("remark").colTitle("文件描述").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("exerciseData").colTitle("是否演训数据").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("entryStaff").colTitle("录入人员").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("equipmentModel").colTitle("装备型号").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("inputDate").colTitle("任务时间").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("source").colTitle("文件来源").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("taskCode").colTitle("任务代号").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("taskNature").colTitle("任务性质").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("troopCode").colTitle("部队代号").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("targetNumber").colTitle("目标/靶标类型").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("missileNumber").colTitle("导弹编号").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("themeTask").colTitle("主题任务").colSort(9).colWidth("100").isShow(true).isSort(false).build());
defaultConfig.add(builder.tableId(fileTableId).colName("secretLevel").colTitle("文件密级").colSort(9).colWidth("100").isShow(true).isSort(false).build());
}
@Override
public List<SysTheadConfig> listByCreateUser(String userId) {
if (StringUtils.hasText(userId)) {
LambdaQueryWrapper<SysTheadConfig> query = new LambdaQueryWrapper<>();
query.eq(SysTheadConfig::getCreateUser, userId);
List<SysTheadConfig> list = list(query);
if (list.size() == 0) {
// 为默认数据生成包含用户主键的ID
defaultConfig.forEach(conf -> conf.genId(userId));
return defaultConfig;
}
return list;
}
return Collections.emptyList();
}
@Override
public boolean saveOrUpdateBatch(Collection<SysTheadConfig> entityList, int batchSize) {
return super.saveOrUpdateBatch(entityList, batchSize);
}
}

@ -14,6 +14,7 @@
<result column="OWNER" property="owner"/>
<result column="OWNER_ID" property="ownerId"/>
<result column="OWNER_TYPE" property="ownerType"/>
<result column="SORT" property="sort"/>
<result column="CREATE_USER" property="createUser"/>
<result column="CREATE_TIME" property="createTime"/>
<result column="MODIFY_USER" property="modifyUser"/>

@ -51,6 +51,8 @@ ul.file-viewer-tab li:hover {
}
.file-property .field-name{
width: 70px;
text-align: right;
padding-right: 10px;
}
.file-property .field-value{
flex: 1;

@ -289,6 +289,12 @@ layui.use(['layer', 'form', 'gtable', 'globalTree'], function () {
<input class="layui-input" type="text" name="title" value="${data.title || ''}" maxlength="50" placeholder="请输入${titleName}名称" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline" style="width: calc(100% - 30px); margin:15px 15px 0 15px">
<label style="color: #555;">顺序</label>
<input class="layui-input" name="sort" value="${data.sort || '0'}" lay-verify="number" autocomplete="false" maxlength="230" placeholder="请输入加载顺序" />
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline" style="width: calc(100% - 30px); margin:15px 15px 0 15px">
<label style="color: #555;">备注</label>

@ -117,11 +117,15 @@ function openDirectoryEditLayer(data, callback, view) {
</div>
<a lay-submit lay-filter="directoryEditForm" id="directoryEditFormSubmit" style=""></a>
</div>
<div class="layui-inline" style="width: calc(100% - 30px); margin:15px 15px 0 15px">
<div class="layui-inline" style="width: calc(63% - 30px); margin:15px 15px 0 15px">
<label style="color: #555">目录创建人</label><span style="color: #000" >${data.createUserName || user.userName}</span>
<input type="hidden" name="createUserName" value="${data.createUserName || user.userName}" />
<input type="hidden" name="createUser" value="${data.createUser || user.userId}" />
</div>
<div class="layui-inline" style="width: calc(37% - 40px); margin:15px 15px 0 15px">
<label style="color: #555">目录顺序</label>
<input class="layui-input" type="text" name="sort" value="${data.sort}" style="width: 60px"/>
</div>
</div>
</div>`,
success: function () {
@ -137,12 +141,12 @@ function openDirectoryEditLayer(data, callback, view) {
click: dirOwnerChangeCallback
});
layui.dict.render();
if(!data || !data.secretLevel){
if (!data || !data.secretLevel) {
data['secretLevel'] = 0;
}
layui.dict.setData('dict-secret-level', data)
$('div.dict-component').css({'margin-top': '5px', 'width': '380px', 'margin-left': '4px'})
if(view){
if (view) {
layui.dict.setReadonly();
}
// 目录成员管理事件
@ -166,7 +170,9 @@ function openDirectoryEditLayer(data, callback, view) {
applyChildCheckbox(isEdit);
},
yes: function (index) {
if(view){return;}
if (view) {
return;
}
saveDirectory(index, callback);
}
})
@ -174,10 +180,16 @@ function openDirectoryEditLayer(data, callback, view) {
function saveDirectory(index, callback) {
form.on('submit(directoryEditForm)', function ({elem, field}) {
if(field.secretLevel > user.secretLevel){
layer.alert('禁止上传超过自身涉密等级的文件,您的涉密等级为【'+ DICT.getText('secret_level', user.secretLevel) +'】', {icon:2})
if (field.secretLevel > user.secretLevel) {
layer.alert('禁止上传超过自身涉密等级的文件,您的涉密等级为【' + DICT.getText('secret_level', user.secretLevel) + '】', {icon: 2})
return;
}
if (isNaN(parseInt(field.sort))) {
layer.alert('目录顺序只能为数字');
return;
}
// 转换数据类型
field.basicDir = field.basicDir === '1';
// 如果是基础数据目录,则自动为提交状态

@ -131,7 +131,7 @@ layui.use(['layer', 'uploader', 'element', 'form', 'laydate', 'dict', 'datalabel
function bindDatetimePlugins() {
//日期选择器
laydate.render({
elem: '#input-data',
elem: 'input[name="inputDate"]',
format: "yyyy-MM-dd HH:mm:ss",
type: 'datetime',
value: new Date(),

@ -9,6 +9,9 @@
layui.use(['layer', 'laytpl', 'dropdown', 'carousel', 'form', 'datalabel'], function () {
for (let col in file) {
switch (col) {
case 'secretLevel':
$(`label[name="${col}"]`).text(DICT.getText('secret_level', file[col]));
break;
case 'taskNature':
$(`label[name="${col}"]`).text(DICT.getText('task_nature', file[col]));
break;
@ -26,7 +29,10 @@ layui.use(['layer', 'laytpl', 'dropdown', 'carousel', 'form', 'datalabel'], func
}
}
break;
case 'secretLevel':
case 'exerciseData':
$(`label[name="${col}"]`).text(file[col] == 0 ? '否' : '是');
break;
case '':
$(`label[name="${col}"]`).text(DICT.getText('secret_level', file[col]));
break;
default:

@ -0,0 +1,88 @@
class FormConfigComponent {
constructor(formType, elemId, lay) {
this.formType = formType;
this.elemId = elemId;
this.lay = lay;
this.dataMap = new Map();
this.renderTable();
}
renderTable() {
const {lay, formType, elemId} = this, {form, gtable} = lay;
gtable.init({
id: elemId,
url: `${ctx}/sys/form/config/api/list/${formType}`,
method: 'get',
toolbar: '#tableTool',
height: 'full-125',
page: false,
cols: [[
{field: 'id', hide: true},
{field: 'fieldName', title: '字段名'},
{field: 'showTitle', title: '显示的标题', edit: 'text'},
{field: 'fieldType', title: '字段类型', hide: true},
{field: 'dictType', title: '数据字典', hide: true},
{field: 'defaultValue', title: '默认值', edit: 'text', hide: true},
{
field: 'isRequired',
title: '是否必填',
templet: (data) => renderSwitch('isRequired', data)
},
{
field: 'isDisabled',
title: '是否禁用',
templet: (data) => renderSwitch('isDisabled', data)
},
{
field: 'isShow',
title: '是否显示',
templet: (data) => renderSwitch('isShow', data)
},
{field: 'sort', title: '显示顺序', edit: 'text'}
]],
done: (res) => this.tableLoadDoneListen(res),
onToolBarTable: ({event, config})=> {
if(event === 'save'){
const datas = [...this.dataMap.values()];
Util.post(`/sys/form/config/api/save`, {params: JSON.stringify(datas)}).then(res=>{
if(res.flag){
showOkMsg('保存成功')
}else{
showErrorMsg2('保存失败:'+res.msg)
}
})
}
}
});
gtable.on(`edit(${elemId})`, ({field, value, data}) => {
this.dataMap.get(data.id)[field] = value;
})
// 监听switch按钮
form.on(`switch(${elemId}-switch)`, (data) => this.switchChangeListen(data));
function renderSwitch(fieldName, data) {
const id = data.id, value = data[fieldName];
return `<input type="checkbox" id="${id}" name="${fieldName}" value="${value}" title="是|否" lay-skin="switch" lay-filter="${elemId}-switch" ${value ? 'checked' : ''} />`
}
}
tableLoadDoneListen(res) {
if (res.flag) {
res.records.map(record => this.dataMap.set(record.id + '', record));
}
}
switchChangeListen({elem}) {
const id = $(elem).attr('id'), name = $(elem).attr('name');
const value = this.dataMap.get(id)[name];
this.dataMap.get(id)[name] = !value;
}
}
layui.use(['form', 'gtable', 'dropdown', 'element'], function () {
const metadataForm = new FormConfigComponent(1, 'metadataFormTable', layui);
const fileUploadForm = new FormConfigComponent(2, 'fileUploadFormTable', layui);
});

@ -47,56 +47,40 @@
<div class="layui-tab-item layui-show">
<div class="layui-form" lay-filter="details-form">
<div class="layui-form-item">
<label class="layui-form-label">数据名称</label>
<label class="layui-form-label">数据表注释</label>
<div class="layui-input-block">
<input type="text" readonly class="layui-input" name="metadataName"
th:value="${detailsData.metadataName}">
<input class="layui-input" type="text" readonly th:value="${detailsData.metadataComment}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">中文注释</label>
<div class="layui-input-block">
<input type="text" readonly class="layui-input" name="metadataComment"
th:value="${detailsData.metadataComment}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据密级</label>
<div class="layui-input-block">
<div dict-component="select" readonly dict-type="secret_level"
dict-name="secretLevel" th:data="${detailsData.secretLevel}"
id="dict-secret-level"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">主题任务</label>
<div class="layui-input-block">
<input type="text" readonly class="layui-input" name="themeTask"
th:value="${detailsData.themeTask}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据类型</label>
<div class="layui-input-block">
<div dict-component="select" readonly dict-type="data_type" dict-name="dataType"
th:data="${detailsData.dataType}" id="dict-data-type"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据来源</label>
<div class="layui-form-item" th:each="field,iterStat : ${metadataFormConfig}" th:if="${field.isShow}">
<label class="layui-form-label" th:text="${field.showTitle}">字段名称</label>
<div class="layui-input-block">
<div dict-component="select" readonly dict-type="data_source"
dict-name="dataFrom" th:data="${detailsData.dataFrom}"
id="dict-data-form"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任务时间</label>
<div class="layui-input-block">
<input type="text" readonly class="layui-input" name="collectionTime"
th:value="${#dates.format(detailsData.collectionTime, 'yyyy-MM-dd HH:mm:ss')}">
<input type="hidden" name="metadataComment" th:if="${field.fieldName == 'metadataName'}">
<!-- 文本输入框-文本类型 -->
<input class="layui-input" type="text" readonly
th:if="${field.fieldType == 'input'}"
th:name="${field.fieldName}"
th:value="${detailsData[field.fieldName]}">
<!-- 文本输入框-日期类型 -->
<input class="layui-input" type="text" readonly
th:if="${field.fieldType == 'date'}"
th:name="${field.fieldName}"
th:value="${#dates.format(detailsData[field.fieldName], 'yyyy-MM-dd HH:mm:ss')}">
<!-- 文本输入框-文本域类型 -->
<textarea class="layui-textarea" readonly
th:if="${field.fieldType == 'textarea'}"
th:name="${field.fieldName}"
th:text="${detailsData[field.fieldName]}"></textarea>
<!-- 数据字典类型 -->
<div dict-component="select" readonly="readonly"
th:if="${field.fieldType == 'dict'}"
th:dict-type="${field.dictType}"
th:dict-name="${field.fieldName}"
th:data="${detailsData[field.fieldName]}"
th:id="${'dict-'+field.fieldName}"></div>
</div>
</div>
<div class="layui-form-item" th:each="labelSet, iterState:${LabelConfigSet}">
<label class="layui-form-label" th:text="${labelSet.fieldTitle}">标签类型</label>
<div class="layui-input-block label-set-component read-only"

@ -29,6 +29,14 @@
class="layui-input" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">字典值</label>
<div class="layui-input-block">
<input type="text" name="dictValue" autocomplete="off" placeholder="字典值"
th:value="${dict.dictValue}"
class="layui-input" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">排序</label>
<div class="layui-input-block">

@ -8,32 +8,10 @@
<!-- 样式 -->
<link th:href="@{/css/common/contianer.css}" rel="stylesheet" type="text/css"/>
<style>
.layui-form-item {
display: flex;
justify-content: center;
}
.layui-form-label {
width: 90px;
}
.layui-inline {
width: 50%;
}
.layui-form-item .layui-input-inline {
width: calc(100% - 130px);
margin-right: 10px;
}
.webuploader-pick {
width: auto !important;
}
.layui-card-body {
padding: 10px 10px;
line-height: 24px;
}
.layui-layer-loading .layui-layer-loading1 {
height: 37px !important;
@ -49,7 +27,6 @@
background-color: #FFF;
border-top: 1px solid #eee;
}
.star-mark{color: red; display: none}
</style>
</head>
@ -60,111 +37,58 @@
<div style="overflow: hidden; flex: 1">
<div class="layui-upload" id="uploader-table"></div>
</div>
<div class="layui-form" lay-filter="file-form"
style="border: 1px solid #eee; padding-top:15px; margin-bottom: 50px;">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span style="color: red">*</span>文件密级</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="secret_level" dict-name="secretLevel"
dict-width="100%" id="dict-secret-level"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">是否演训数据</label>
<div class="layui-input-inline">
<input class="layui-input" type="radio" name="exerciseData" value="0" title="否" checked lay-filter="exerciseData"/>
<input class="layui-input" type="radio" name="exerciseData" value="1" title="是" lay-filter="exerciseData"/>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>任务时间</label>
<div class="layui-input-inline">
<input class="layui-input" id="input-data" name="inputDate" type="text">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">录入人员</label>
<div class="layui-input-inline" th:object="${@securityUtil.getLoginSysUser()}">
<input class="layui-input" name="entryStaff" type="text" readonly
th:value="*{userName}">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>文件来源</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="data_source" dict-name="source"
dict-width="100%" id="dict-data-form"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">目标/靶标类型</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="target_type" dict-name="targetNumber"
dict-width="100%" id="dict-target-type"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>任务代号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="task_code" dict-name="taskCode"
dict-width="100%" id="dict-task-code"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>任务性质</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="task_nature" dict-name="taskNature"
dict-width="100%" id="dict-task-nature"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>部队代号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="troop_code" dict-name="troopCode"
dict-width="100%" id="dict-troop-code"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>装备型号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="equipment_model" dict-name="equipmentModel"
dict-width="100%" id="dict-equipment-model"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">导弹编号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="missile_number" dict-name="missileNumber"
dict-width="100%" id="dict-missile-number"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">主题任务</label>
<div class="layui-input-inline">
<input class="layui-input" name="themeTask" type="text">
</div>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label" style="margin-left: -10px;">文件描述</label>
<div class="layui-input-block" style="width:calc(100% - 130px);margin-left: 0">
<textarea class="layui-textarea" name="remark"></textarea>
</div>
</div>
<div class="layui-form-item" th:each="labelSet, iterState:${LabelConfigSet}">
<div class="layui-form dynamic-form" lay-filter="file-form"
style="border: 1px solid #eee; padding-top:15px; margin-bottom: 50px;"
th:object="${@securityUtil.getLoginSysUser()}">
<div class="layui-form-item"
th:each="field,iterStat : ${uploadFormConfig}"
th:if="${field.isShow}"
th:style="${field.fieldType == 'textarea' ? 'width: calc(100% - 30px);' : ''}"
th:with="username=*{userName}">
<label th:if="${field.isRequired}" class="layui-form-label">
<label style="color: red">*</label>
<label th:text="${field.showTitle}">*</label>
</label>
<label th:if="${!field.isRequired}" class="layui-form-label" th:text="${field.showTitle}"></label>
<div class="layui-input-block">
<!-- 文本框类型 -->
<input class="layui-input" type="text" autocomplete="off"
th:if="${field.fieldType == 'input' || field.fieldType == 'date'}"
th:name="${field.fieldName}"
th:value="${field.fieldName=='entryStaff'?username:''}"
th:disabled="${field.isDisabled}"
th:placeholder="${field.showTitle}"
th:lay-verify="${field.isRequired ? 'required' : ''}">
<!-- 文本域类型 -->
<textarea class="layui-textarea" type="text" autocomplete="off"
th:if="${field.fieldType == 'textarea'}"
th:name="${field.fieldName}"
th:disabled="${field.isDisabled}"
th:placeholder="${field.showTitle}"
th:lay-verify="${field.isRequired ? 'required' : ''}"></textarea>
<th:block th:if="${field.fieldType == 'radio' && field.isShow}">
<input class="layui-inline" type="radio"
th:each="exp, stat : ${#strings.listSplit(field.dictType, ';')}"
th:with="tmp=${#strings.arraySplit(exp, '-')}, value=${tmp[0]}, title=${tmp[1]}, checked=${#arrays.length(tmp)==3?tmp[2]:false}"
th:name="${field.fieldName}"
th:value="${value}"
th:title="${title}"
th:checked="${checked}"
/>
</th:block>
<!-- 数据字典类型 -->
<div dict-component="select"
th:if="${field.fieldType == 'dict'}"
th:disabled="${field.isDisabled}"
th:dict-type="${field.dictType}"
th:dict-name="${field.fieldName}"
th:id="${'dict-'+field.fieldName}"></div>
</div>
</div>
<div class="layui-form-item" style="width: 100%" th:each="labelSet, iterState:${LabelConfigSet}">
<label class="layui-form-label" th:text="${labelSet.fieldTitle}">标签类型</label>
<div class="layui-input-block label-set-component"
<div class="layui-input-block">
<div class="label-set-component"
th:data-id="${labelSet.id}"
th:data-field-title="${labelSet.fieldTitle}"
th:data-label-id="${labelSet.labelId}"
@ -173,11 +97,12 @@
th:data-label-title-path="${labelSet.labelTitlePath}"
style="width:calc(100% - 120px);margin-left: 0"></div>
</div>
<div class="layui-form-item other-label-item">
<label class="layui-form-label"><a class="label-type choose-data add-other"
id="addOtherLabelBtn">添加</a>其他标签</label>
<div class="layui-input-block label-set-component other-label" th:data-field-title="其他标签"
style="width:calc(100% - 120px);margin-left: 0"></div>
</div>
<div class="layui-form-item other-label-item" style="width: 100%">
<label class="layui-form-label"><a class="label-type choose-data add-other" id="addOtherLabelBtn">添加</a>其他标签</label>
<div class="layui-input-block other-label-item">
<div class="label-set-component other-label" th:data-field-title="其他标签"></div>
</div>
</div>
</div>
<div class="bottom-btns">

@ -15,10 +15,6 @@
.layui-form-item .layui-input-inline {
width: 260px;
}
.label-set-component{
margin-left: 120px;
}
.star-mark{color: red; display: none}
</style>
<script th:inline="javascript">
const file = /*[[${file}]]*/ {};
@ -34,7 +30,7 @@
<div class="layui-upload">
<h2 th:text="${file.fileName}" style="margin-bottom: 10px;"></h2>
</div>
<form class="layui-form" id="file-form" lay-filter="file-form" style="border: 1px solid #eee; padding-top:15px">
<form class="layui-form dynamic-form" id="file-form" lay-filter="file-form" style="border: 1px solid #eee; padding-top:15px">
<input type="hidden" name="id">
<input type="hidden" name="fileName">
<input type="hidden" name="entityId">
@ -48,94 +44,56 @@
<input type="hidden" name="currentChunkIndex">
<input type="hidden" name="MD5">
<input type="hidden" name="isFirst">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span style="color: red">*</span>文件密级</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="secret_level" dict-name="secretLevel"
dict-width="100%" id="dict-secret-level"></div>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">是否演训数据</label>
<div class="layui-input-inline">
<input class="layui-input" type="radio" name="exerciseData" value="0" title="否" checked lay-filter="exerciseData"/>
<input class="layui-input" type="radio" name="exerciseData" value="1" title="是" lay-filter="exerciseData"/>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">录入人员</label>
<div class="layui-input-inline">
<input class="layui-input" name="entryStaff" type="text" readonly>
</div>
<label class="layui-form-label"><span class="star-mark">*</span>任务时间</label>
<div class="layui-input-inline">
<input class="layui-input" id="input-data" name="inputDate" type="text">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>文件来源</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="data_source" dict-name="source"
dict-width="100%" id="dict-data-form"></div>
</div>
<label class="layui-form-label">目标/靶标类型</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="target_type" dict-name="targetNumber"
dict-width="100%" id="dict-target-type"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>任务代号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="task_code" dict-name="taskCode"
dict-width="100%" id="dict-task-code"></div>
</div>
<label class="layui-form-label"><span class="star-mark">*</span>任务性质</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="task_nature" dict-name="taskNature"
dict-width="100%" id="dict-task-nature"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label"><span class="star-mark">*</span>部队代号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="troop_code" dict-name="troopCode"
dict-width="100%" id="dict-troop-code"></div>
</div>
<label class="layui-form-label"><span class="star-mark">*</span>装备型号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="equipment_model" dict-name="equipmentModel"
dict-width="100%" id="dict-equipment-model"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">导弹编号</label>
<div class="layui-input-inline">
<div dict-component="select" dict-type="missile_number" dict-name="missileNumber"
dict-width="100%" id="dict-missile-number"></div>
</div>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">文件描述</label>
<div class="layui-input-block" style="margin-left: 120px; width:640px;">
<textarea class="layui-textarea" name="remark"></textarea>
</div>
</div>
<div class="layui-form-item" th:each="labelSet, iterState:${LabelConfigSet}">
<div class="layui-form-item"
th:each="field,iterStat : ${uploadFormConfig}"
th:if="${field.isShow}"
th:style="${field.fieldType == 'textarea' ? 'width: calc(100% - 30px);' : ''}"
th:with="username=*{userName}">
<label th:if="${field.isRequired}" class="layui-form-label">
<label style="color: red">*</label>
<label th:text="${field.showTitle}">*</label>
</label>
<label th:if="${!field.isRequired}" class="layui-form-label" th:text="${field.showTitle}"></label>
<div class="layui-input-block">
<!-- 文本框类型 -->
<input class="layui-input" type="text" autocomplete="off"
th:if="${field.fieldType == 'input' || field.fieldType == 'date'}"
th:name="${field.fieldName}"
th:value="${field.fieldName}"
th:disabled="${field.isDisabled}"
th:placeholder="${field.showTitle}"
th:readonly="${field.fieldName == 'inputDate' || field.fieldName == 'entryStaff'}"
th:lay-verify="${field.isRequired ? 'required' : ''}">
<!-- 文本域类型 -->
<textarea class="layui-textarea" type="text" autocomplete="off"
th:if="${field.fieldType == 'textarea'}"
th:name="${field.fieldName}"
th:disabled="${field.isDisabled}"
th:placeholder="${field.showTitle}"
th:lay-verify="${field.isRequired ? 'required' : ''}"></textarea>
<th:block th:if="${field.fieldType == 'radio' && field.isShow}">
<input class="layui-inline" type="radio"
th:each="exp, stat : ${#strings.listSplit(field.dictType, ';')}"
th:with="tmp=${#strings.arraySplit(exp, '-')}, value=${tmp[0]}, title=${tmp[1]}, checked=${#arrays.length(tmp)==3?tmp[2]:false}"
th:name="${field.fieldName}"
th:value="${value}"
th:title="${title}"
th:checked="${checked}"
/>
</th:block>
<!-- 数据字典类型 -->
<div dict-component="select"
th:if="${field.fieldType == 'dict'}"
th:disabled="${field.isDisabled}"
th:dict-type="${field.dictType}"
th:dict-name="${field.fieldName}"
th:id="${'dict-'+field.fieldName}"></div>
</div>
</div>
<div class="layui-form-item" style="width: 100%" th:each="labelSet, iterState:${LabelConfigSet}">
<label class="layui-form-label" th:text="${labelSet.fieldTitle}">标签类型</label>
<div class="layui-input-block label-set-component"
<div class="layui-input-block">
<div class="label-set-component"
th:data-id="${labelSet.id}"
th:data-field-title="${labelSet.fieldTitle}"
th:data-label-id="${labelSet.labelId}"
@ -143,12 +101,15 @@
th:data-label-id-path="${labelSet.labelIdPath}"
th:data-label-title-path="${labelSet.labelTitlePath}"></div>
</div>
<div class="layui-form-item other-label-item">
</div>
<div class="layui-form-item" style="width: 100%">
<label class="layui-form-label"><a class="label-type choose-data add-other" id="addOtherLabelBtn">添加</a>其他标签</label>
<div class="layui-input-block label-set-component other-label" th:data-field-title="其他标签"></div>
<div class="layui-input-block other-label-item">
<div class="label-set-component other-label" th:data-field-title="其他标签"></div>
</div>
</div>
<button class="layui-btn layui-btn-sm" id="btn_submit"
style="position: absolute; left: -50px; height: 0; border:0">
style="width: 100%;position: absolute; left: -50px; height: 0; border:0">
</button>
</form>
</div>

@ -8,6 +8,11 @@
<!-- 样式 -->
<link th:href="@{/css/common/contianer.css}" rel="stylesheet" type="text/css"/>
<link th:href="@{/css/sys/file/fileView.css}" rel="stylesheet" type="text/css"/>
<style>
.layui-input-block{
margin-left: 0;
}
</style>
<script th:inline="javascript">
const file = /*[[${fileData}]]*/ {};
const fileViewUrl = /*[[${fileViewUrl}]]*/ '';
@ -35,45 +40,13 @@
<label class="field-name">文件名称</label>
<label class="field-value" name="fileName"></label>
</div>
<div class="file-property">
<label class="field-name">文件密级</label>
<label class="field-value" name="secretLevel"></label>
</div>
<div class="file-property">
<label class="field-name">录入人员</label>
<label class="field-value" name="entryStaff"></label>
</div>
<div class="file-property">
<label class="field-name">导弹编号</label>
<label class="field-value" name="missileNumber"></label>
</div>
<div class="file-property">
<label class="field-name">目标/靶标类型</label>
<label class="field-value" name="targetNumber"></label>
</div>
<div class="file-property">
<label class="field-name">文件来源</label>
<label class="field-value" name="source"></label>
</div>
<div class="file-property">
<label class="field-name">目标性质</label>
<label class="field-value" name="taskNature"></label>
</div>
<div class="file-property">
<label class="field-name">部队代号</label>
<label class="field-value" name="troopCode"></label>
</div>
<div class="file-property">
<label class="field-name">装备型号</label>
<label class="field-value" name="equipmentModel"></label>
</div>
<div class="file-property">
<label class="field-name">任务时间</label>
<label class="field-value" th:text="${file_inputDate}"></label>
</div>
<div class="file-property">
<label class="field-name">文件描述</label>
<label class="field-value" name="remark"></label>
<div class="file-property"
th:each="field,iterStat : ${uploadFormConfig}"
th:if="${field.isShow}"
th:style="${field.fieldType == 'textarea' ? 'width: calc(100% - 30px);' : ''}"
th:with="username=*{userName}">
<label class="field-name" th:text="${field.showTitle}">文件名称</label>
<label class="field-value" th:name="${field.fieldName}" th:value="${field.fieldName}"></label>
</div>
<div class="file-property" th:each="labelSet, iterState:${LabelConfigSet}">
<label class="field-name" th:text="${labelSet.fieldTitle}">标签类型</label>
@ -87,7 +60,7 @@
</div>
<div class="file-property">
<label class="field-name">其他标签</label>
<div class=" other-label-item read-only"></div>
<div class="other-label-item layui-input-block read-only"></div>
</div>
<div class="layui-form-item" style="display: flex; flex-direction: column;">
<input type="hidden" name="id">

@ -0,0 +1,57 @@
<!DOCTYPE html>
<!--解决idea thymeleaf 表达式模板报红波浪线-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<!-- 引入公用部分 -->
<script th:replace="common/head::static"></script>
<!-- 样式 -->
<link th:href="@{/css/common/contianer.css}" rel="stylesheet" type="text/css"/>
<script th:inline="javascript">
const FormTypeEnum = /*[[${FormTypeEnum}]]*/ {};
</script>
</head>
<body>
<div class="layui-row">
<!---->
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-header layui-hide"></div>
<div class="layui-card-body">
<div class="layui-tab layui-tab-brief" lay-filter="form-config-tab">
<ul class="layui-tab-title">
<li class="layui-this" data-form-type="1">数据资源注册表单</li>
<li data-form-type="2">文件上传表单</li>
</ul>
<div class="layui-tab-content" style="padding: 0">
<div class="layui-tab-item layui-show">
<table class="layui-hide" id="metadataFormTable"
lay-filter="metadataFormTable"></table>
</div>
<div class="layui-tab-item">
<table class="layui-hide" id="fileUploadFormTable"
lay-filter="fileUploadFormTable"></table>
</div>
<script type="text/html" id="tableTool">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="save">保存修改</button>
</div>
</script>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<!-- js -->
<script th:replace="common/head::static-foot"></script>
<script th:src="@{/js/sys/form/formConfig.js}"></script>
<script>
const sizeInit = () => {
$(".layui-card-body").height(window.innerHeight - 43 - 40 - 20);
}
window.onresize = sizeInit;
sizeInit();
</script>
</html>