瀏覽代碼

Merge branch 'develop' of http://112.74.196.215:3000/wangzaijun/data-daq into develop

wangzaijun 7 月之前
父節點
當前提交
338d20e6c7
共有 65 個文件被更改,包括 5747 次插入25 次删除
  1. 21 1
      service-base/pom.xml
  2. 148 0
      service-base/src/main/java/com/simuwang/base/common/conts/Constants.java
  3. 14 0
      service-base/src/main/java/com/simuwang/base/common/conts/EmailFieldConst.java
  4. 102 0
      service-base/src/main/java/com/simuwang/base/common/page/PageDomain.java
  5. 85 0
      service-base/src/main/java/com/simuwang/base/common/page/TableDataInfo.java
  6. 56 0
      service-base/src/main/java/com/simuwang/base/common/page/TableSupport.java
  7. 228 0
      service-base/src/main/java/com/simuwang/base/common/result/AjaxResult.java
  8. 87 0
      service-base/src/main/java/com/simuwang/base/common/text/CharsetKit.java
  9. 1007 0
      service-base/src/main/java/com/simuwang/base/common/text/Convert.java
  10. 218 0
      service-base/src/main/java/com/simuwang/base/common/util/DateUtils.java
  11. 34 0
      service-base/src/main/java/com/simuwang/base/common/util/PageUtils.java
  12. 219 0
      service-base/src/main/java/com/simuwang/base/common/util/ServletUtils.java
  13. 71 0
      service-base/src/main/java/com/simuwang/base/common/util/SqlUtil.java
  14. 629 0
      service-base/src/main/java/com/simuwang/base/common/util/StringUtil.java
  15. 15 0
      service-base/src/main/java/com/simuwang/base/mapper/CompanyEmailConfigMapper.java
  16. 18 0
      service-base/src/main/java/com/simuwang/base/mapper/CompanyInformationMapper.java
  17. 24 0
      service-base/src/main/java/com/simuwang/base/mapper/FundInfomationMapper.java
  18. 17 0
      service-base/src/main/java/com/simuwang/base/mapper/FundReportFrequencyMapper.java
  19. 70 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/CompanyEmailConfigDO.java
  20. 70 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/CompanyEmailSendHistoryDO.java
  21. 205 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/CompanyInformationDO.java
  22. 144 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/FundInformationDO.java
  23. 70 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/FundReportFrequencyDO.java
  24. 70 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysConfigDO.java
  25. 86 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysDictDataDO.java
  26. 66 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysDictTypeDO.java
  27. 99 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysMenuDO.java
  28. 72 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysRoleDO.java
  29. 24 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysRoleMenuDO.java
  30. 92 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysUserDO.java
  31. 25 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/SysUserRole.java
  32. 8 11
      service-base/src/main/java/com/simuwang/base/pojo/dto/EmailFundNavDTO.java
  33. 40 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/CompanyEmailConfigVO.java
  34. 48 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/CompanyEmailSendHistoryVO.java
  35. 46 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/FundInformationVO.java
  36. 34 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/FundReportFrequencyVO.java
  37. 38 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/SysConfigVO.java
  38. 42 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/SysDictDataVO.java
  39. 26 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/SysDictTypeVO.java
  40. 66 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/SysMenuVO.java
  41. 56 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/SysRoleVO.java
  42. 67 0
      service-base/src/main/java/com/simuwang/base/pojo/vo/SysUserVO.java
  43. 53 0
      service-base/src/main/resources/mapper/CompanyInformationMapper.xml
  44. 77 0
      service-base/src/main/resources/mapper/FundInformationMapper.xml
  45. 34 0
      service-base/src/main/resources/mapper/FundReportFrequencyMapper.xml
  46. 22 8
      service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java
  47. 231 3
      service-daq/src/main/java/com/simuwang/daq/service/NavEmailParser.java
  48. 2 2
      service-deploy/src/main/test/java/com/simuwang/datadaq/DataTrusteeApplicationTests.java
  49. 10 0
      service-manage/pom.xml
  50. 162 0
      service-manage/src/main/java/com/simuwang/manage/api/base/BaseController.java
  51. 49 0
      service-manage/src/main/java/com/simuwang/manage/api/company/CompanyEmailConfigController.java
  52. 22 0
      service-manage/src/main/java/com/simuwang/manage/api/company/CompanyEmailSendHistoryController.java
  53. 29 0
      service-manage/src/main/java/com/simuwang/manage/api/company/CompanyInformationController.java
  54. 80 0
      service-manage/src/main/java/com/simuwang/manage/api/fund/FundInformationController.java
  55. 125 0
      service-manage/src/main/java/com/simuwang/manage/api/system/SysConfigController.java
  56. 17 0
      service-manage/src/main/java/com/simuwang/manage/service/CompanyEmailConfigService.java
  57. 14 0
      service-manage/src/main/java/com/simuwang/manage/service/CompanyInformationService.java
  58. 18 0
      service-manage/src/main/java/com/simuwang/manage/service/FundInformationService.java
  59. 13 0
      service-manage/src/main/java/com/simuwang/manage/service/FundReportFrequencyService.java
  60. 53 0
      service-manage/src/main/java/com/simuwang/manage/service/impl/CompanyEmailConfigServiceImpl.java
  61. 27 0
      service-manage/src/main/java/com/simuwang/manage/service/impl/CompanyInformationServiceImpl.java
  62. 32 0
      service-manage/src/main/java/com/simuwang/manage/service/impl/FundInformationServiceImpl.java
  63. 42 0
      service-manage/src/main/java/com/simuwang/manage/service/impl/FundReportFrequencyServiceImpl.java
  64. 51 0
      service-manage/src/main/java/com/simuwang/manage/service/impl/system/SysConfigServiceImpl.java
  65. 27 0
      service-manage/src/main/java/com/simuwang/manage/service/system/SysConfigService.java

+ 21 - 1
service-base/pom.xml

@@ -33,6 +33,12 @@
             <groupId>com.zaxxer</groupId>
             <artifactId>HikariCP</artifactId>
         </dependency>
+        <!-- pagehelper 分页插件 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>2.0.0</version>
+        </dependency>
 <!--        <dependency>-->
 <!--            <groupId>com.baomidou</groupId>-->
 <!--            <artifactId>mybatis-plus</artifactId>-->
@@ -92,7 +98,12 @@
         </dependency>
         <dependency>
             <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
+            <artifactId>hutool-extra</artifactId>
+            <version>5.8.31</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-json</artifactId>
             <version>5.8.31</version>
         </dependency>
         <dependency>
@@ -141,6 +152,15 @@
             <artifactId>poi-ooxml</artifactId>
             <version>3.17</version>
         </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>6.1.12</version>
+        </dependency>
     </dependencies>
 
     <repositories>

+ 148 - 0
service-base/src/main/java/com/simuwang/base/common/conts/Constants.java

@@ -0,0 +1,148 @@
+package com.simuwang.base.common.conts;
+
+
+/**
+ * 通用常量信息
+ * 
+ * @author ruoyi
+ */
+public class Constants
+{
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * www主域
+     */
+    public static final String WWW = "www.";
+
+    /**
+     * http请求
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https请求
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 通用成功标识
+     */
+    public static final String SUCCESS = "0";
+
+    /**
+     * 通用失败标识
+     */
+    public static final String FAIL = "1";
+
+    /**
+     * 登录成功
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 注销
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 注册
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 登录失败
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 所有权限标识
+     */
+    public static final String ALL_PERMISSION = "*:*:*";
+
+    /**
+     * 管理员角色权限标识
+     */
+    public static final String SUPER_ADMIN = "admin";
+
+    /**
+     * 角色权限分隔符
+     */
+    public static final String ROLE_DELIMETER = ",";
+
+    /**
+     * 权限标识分隔符
+     */
+    public static final String PERMISSION_DELIMETER = ",";
+
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 令牌
+     */
+    public static final String TOKEN = "token";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String LOGIN_USER_KEY = "login_user_key";
+
+    /**
+     * 用户ID
+     */
+    public static final String JWT_USERID = "userid";
+
+    /**
+     * 用户头像
+     */
+    public static final String JWT_AVATAR = "avatar";
+
+    /**
+     * 创建时间
+     */
+    public static final String JWT_CREATED = "created";
+
+    /**
+     * 用户权限
+     */
+    public static final String JWT_AUTHORITIES = "authorities";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * RMI 远程方法调用
+     */
+    public static final String LOOKUP_RMI = "rmi:";
+
+    /**
+     * LDAP 远程方法调用
+     */
+    public static final String LOOKUP_LDAP = "ldap:";
+
+    /**
+     * LDAPS 远程方法调用
+     */
+    public static final String LOOKUP_LDAPS = "ldaps:";
+
+
+
+}

+ 14 - 0
service-base/src/main/java/com/simuwang/base/common/conts/EmailFieldConst.java

@@ -0,0 +1,14 @@
+package com.simuwang.base.common.conts;
+
+public class EmailFieldConst {
+
+    public final static String PRICE_DATE = "priceDate";
+    public final static String FUND_NAME = "fundName";
+    public final static String REGISTER_NUMBER = "registerNumber";
+    public final static String NAV = "nav";
+    public final static String CUMULATIVE_NAV_WITHDRAWAL = "cumulativeNavWithdrawal";
+    public final static String VIRTUAL_NAV = "virtualNav";
+    public final static String ASSET_SHARE = "assetShare";
+    public final static String ASSET_NET = "assetNet";
+
+}

+ 102 - 0
service-base/src/main/java/com/simuwang/base/common/page/PageDomain.java

@@ -0,0 +1,102 @@
+package com.simuwang.base.common.page;
+
+
+import com.simuwang.base.common.util.StringUtil;
+
+/**
+ * 分页数据
+ * 
+ * @author ruoyi
+ */
+public class PageDomain
+{
+    /** 当前记录起始索引 */
+    private Integer pageNum;
+
+    /** 每页显示记录数 */
+    private Integer pageSize;
+
+    /** 排序列 */
+    private String orderByColumn;
+
+    /** 排序的方向desc或者asc */
+    private String isAsc = "asc";
+
+    /** 分页参数合理化 */
+    private Boolean reasonable = true;
+
+    public String getOrderBy()
+    {
+        if (StringUtil.isEmpty(orderByColumn))
+        {
+            return "";
+        }
+        return StringUtil.toUnderScoreCase(orderByColumn) + " " + isAsc;
+    }
+
+    public Integer getPageNum()
+    {
+        return pageNum;
+    }
+
+    public void setPageNum(Integer pageNum)
+    {
+        this.pageNum = pageNum;
+    }
+
+    public Integer getPageSize()
+    {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize)
+    {
+        this.pageSize = pageSize;
+    }
+
+    public String getOrderByColumn()
+    {
+        return orderByColumn;
+    }
+
+    public void setOrderByColumn(String orderByColumn)
+    {
+        this.orderByColumn = orderByColumn;
+    }
+
+    public String getIsAsc()
+    {
+        return isAsc;
+    }
+
+    public void setIsAsc(String isAsc)
+    {
+        if (StringUtil.isNotEmpty(isAsc))
+        {
+            // 兼容前端排序类型
+            if ("ascending".equals(isAsc))
+            {
+                isAsc = "asc";
+            }
+            else if ("descending".equals(isAsc))
+            {
+                isAsc = "desc";
+            }
+            this.isAsc = isAsc;
+        }
+    }
+
+    public Boolean getReasonable()
+    {
+        if (StringUtil.isNull(reasonable))
+        {
+            return Boolean.TRUE;
+        }
+        return reasonable;
+    }
+
+    public void setReasonable(Boolean reasonable)
+    {
+        this.reasonable = reasonable;
+    }
+}

+ 85 - 0
service-base/src/main/java/com/simuwang/base/common/page/TableDataInfo.java

@@ -0,0 +1,85 @@
+package com.simuwang.base.common.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 表格分页数据对象
+ * 
+ * @author ruoyi
+ */
+public class TableDataInfo implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 总记录数 */
+    private long total;
+
+    /** 列表数据 */
+    private List<?> rows;
+
+    /** 消息状态码 */
+    private int code;
+
+    /** 消息内容 */
+    private String msg;
+
+    /**
+     * 表格数据对象
+     */
+    public TableDataInfo()
+    {
+    }
+
+    /**
+     * 分页
+     * 
+     * @param list 列表数据
+     * @param total 总记录数
+     */
+    public TableDataInfo(List<?> list, int total)
+    {
+        this.rows = list;
+        this.total = total;
+    }
+
+    public long getTotal()
+    {
+        return total;
+    }
+
+    public void setTotal(long total)
+    {
+        this.total = total;
+    }
+
+    public List<?> getRows()
+    {
+        return rows;
+    }
+
+    public void setRows(List<?> rows)
+    {
+        this.rows = rows;
+    }
+
+    public int getCode()
+    {
+        return code;
+    }
+
+    public void setCode(int code)
+    {
+        this.code = code;
+    }
+
+    public String getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(String msg)
+    {
+        this.msg = msg;
+    }
+}

+ 56 - 0
service-base/src/main/java/com/simuwang/base/common/page/TableSupport.java

@@ -0,0 +1,56 @@
+package com.simuwang.base.common.page;
+
+import com.simuwang.base.common.text.Convert;
+import com.simuwang.base.common.util.ServletUtils;
+
+/**
+ * 表格数据处理
+ * 
+ * @author ruoyi
+ */
+public class TableSupport
+{
+    /**
+     * 当前记录起始索引
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 每页显示记录数
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 排序列
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 排序的方向 "desc" 或者 "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 分页参数合理化
+     */
+    public static final String REASONABLE = "reasonable";
+
+    /**
+     * 封装分页对象
+     */
+    public static PageDomain getPageDomain()
+    {
+        PageDomain pageDomain = new PageDomain();
+        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+        return pageDomain;
+    }
+
+    public static PageDomain buildPageRequest()
+    {
+        return getPageDomain();
+    }
+}

+ 228 - 0
service-base/src/main/java/com/simuwang/base/common/result/AjaxResult.java

@@ -0,0 +1,228 @@
+package com.simuwang.base.common.result;
+
+import com.simuwang.base.common.util.StringUtil;
+
+import java.util.HashMap;
+import java.util.Objects;
+
+/**
+ * 操作消息提醒
+ *
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 状态码 */
+    public static final String CODE_TAG = "code";
+
+    /** 返回内容 */
+    public static final String MSG_TAG = "msg";
+
+    /** 数据对象 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 状态类型
+     */
+    public enum Type
+    {
+        /** 成功 */
+        SUCCESS(0),
+        /** 警告 */
+        WARN(301),
+        /** 错误 */
+        ERROR(500);
+        private final int value;
+
+        Type(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param type 状态类型
+     * @param msg 返回内容
+     */
+    public AjaxResult(Type type, String msg)
+    {
+        super.put(CODE_TAG, type.value);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param type 状态类型
+     * @param msg 返回内容
+     * @param data 数据对象
+     */
+    public AjaxResult(Type type, String msg, Object data)
+    {
+        super.put(CODE_TAG, type.value);
+        super.put(MSG_TAG, msg);
+        if (StringUtil.isNotNull(data))
+        {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @return 成功消息
+     */
+    public static AjaxResult success()
+    {
+        return AjaxResult.success("操作成功");
+    }
+
+    /**
+     * 返回成功数据
+     *
+     * @return 成功消息
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg 返回内容
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg)
+    {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg, Object data)
+    {
+        return new AjaxResult(Type.SUCCESS, msg, data);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult warn(String msg)
+    {
+        return AjaxResult.warn(msg, null);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static AjaxResult warn(String msg, Object data)
+    {
+        return new AjaxResult(Type.WARN, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @return
+     */
+    public static AjaxResult error()
+    {
+        return AjaxResult.error("操作失败");
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult error(String msg)
+    {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static AjaxResult error(String msg, Object data)
+    {
+        return new AjaxResult(Type.ERROR, msg, data);
+    }
+
+    /**
+     * 是否为成功消息
+     *
+     * @return 结果
+     */
+    public boolean isSuccess()
+    {
+        return Objects.equals(Type.SUCCESS.value, this.get(CODE_TAG));
+    }
+
+    /**
+     * 是否为警告消息
+     *
+     * @return 结果
+     */
+    public boolean isWarn()
+    {
+        return Objects.equals(Type.WARN.value, this.get(CODE_TAG));
+    }
+
+    /**
+     * 是否为错误消息
+     *
+     * @return 结果
+     */
+    public boolean isError()
+    {
+        return Objects.equals(Type.ERROR.value, this.get(CODE_TAG));
+    }
+
+    /**
+     * 方便链式调用
+     *
+     * @param key 键
+     * @param value 值
+     * @return 数据对象
+     */
+    @Override
+    public AjaxResult put(String key, Object value)
+    {
+        super.put(key, value);
+        return this;
+    }
+}

+ 87 - 0
service-base/src/main/java/com/simuwang/base/common/text/CharsetKit.java

@@ -0,0 +1,87 @@
+package com.simuwang.base.common.text;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 字符集工具类
+ * 
+ * @author ruoyi
+ */
+public class CharsetKit
+{
+    /** ISO-8859-1 */
+    public static final String ISO_8859_1 = "ISO-8859-1";
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+    /** GBK */
+    public static final String GBK = "GBK";
+
+    /** ISO-8859-1 */
+    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+    /** UTF-8 */
+    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+    /** GBK */
+    public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+    /**
+     * 转换为Charset对象
+     * 
+     * @param charset 字符集,为空则返回默认字符集
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, String srcCharset, String destCharset)
+    {
+        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, Charset srcCharset, Charset destCharset)
+    {
+        if (null == srcCharset)
+        {
+            srcCharset = StandardCharsets.ISO_8859_1;
+        }
+
+        if (null == destCharset)
+        {
+            destCharset = StandardCharsets.UTF_8;
+        }
+
+        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+        {
+            return source;
+        }
+        return new String(source.getBytes(srcCharset), destCharset);
+    }
+
+    /**
+     * @return 系统字符集编码
+     */
+    public static String systemCharset()
+    {
+        return Charset.defaultCharset().name();
+    }
+}

File diff suppressed because it is too large
+ 1007 - 0
service-base/src/main/java/com/simuwang/base/common/text/Convert.java


+ 218 - 0
service-base/src/main/java/com/simuwang/base/common/util/DateUtils.java

@@ -0,0 +1,218 @@
+package com.simuwang.base.common.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * 时间工具类
+ * 
+ * @author ruoyi
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 获取当前Date型日期
+     * 
+     * @return Date() 当前日期
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+
+
+    public static Date parse(String strDate, String pattern) {
+        try {
+            return StringUtils.isEmpty(strDate) ? null : (new SimpleDateFormat(pattern)).parse(strDate);
+        } catch (ParseException var3) {
+            var3.printStackTrace();
+            return null;
+        }
+    }
+
+    public static String getAroundToday(int offnum) {
+        return getAroundDate(new Date(), offnum, 5, DateUtils.YYYY_MM_DD);
+    }
+
+    public static String getAroundDate(Date date, int offnum, int type, String format) {
+        return format(getAroundDate(date, offnum, type), format);
+    }
+
+    public static Date getAroundDate(Date date, int offnum, int type) {
+        Calendar numday = Calendar.getInstance();
+        numday.setTime(date);
+        numday.add(type, offnum);
+        return numday.getTime();
+    }
+
+    public static String format(Date date, String pattern) {
+        return date == null ? null : (new SimpleDateFormat(pattern)).format(date);
+    }
+    /**
+     * 获取当前日期, 默认格式为yyyy-MM-dd
+     * 
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 日期路径 即年/月/日 如2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 日期路径 即年/月/日 如20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 日期型字符串转化为日期 格式
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 获取服务器启动时间
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 计算相差天数
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2)
+    {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 计算时间差
+     *
+     * @param endDate 最后时间
+     * @param startTime 开始时间
+     * @return 时间差(天/小时/分钟)
+     */
+    public static String timeDistance(Date endDate, Date startTime)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - startTime.getTime();
+        // 计算差多少天
+        long day = diff / nd;
+        // 计算差多少小时
+        long hour = diff % nd / nh;
+        // 计算差多少分钟
+        long min = diff % nd % nh / nm;
+        // 计算差多少秒//输出结果
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+
+    /**
+     * 增加 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 增加 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+}

+ 34 - 0
service-base/src/main/java/com/simuwang/base/common/util/PageUtils.java

@@ -0,0 +1,34 @@
+package com.simuwang.base.common.util;
+
+import com.github.pagehelper.PageHelper;
+import com.simuwang.base.common.page.PageDomain;
+import com.simuwang.base.common.page.TableSupport;
+
+/**
+ * 分页工具类
+ * 
+ * @author ruoyi
+ */
+public class PageUtils extends PageHelper
+{
+    /**
+     * 设置请求分页数据
+     */
+    public static void startPage()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+        Boolean reasonable = pageDomain.getReasonable();
+        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+    }
+
+    /**
+     * 清理分页的线程变量
+     */
+    public static void clearPage()
+    {
+        PageHelper.clearPage();
+    }
+}

+ 219 - 0
service-base/src/main/java/com/simuwang/base/common/util/ServletUtils.java

@@ -0,0 +1,219 @@
+package com.simuwang.base.common.util;
+
+import com.simuwang.base.common.conts.Constants;
+import com.simuwang.base.common.text.Convert;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * 客户端工具类
+ * 
+ * @author ruoyi
+ */
+public class ServletUtils
+{
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name)
+    {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue)
+    {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获得所有请求参数
+     *
+     * @param request 请求对象{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String[]> getParams(ServletRequest request)
+    {
+        final Map<String, String[]> map = request.getParameterMap();
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * 获得所有请求参数
+     *
+     * @param request 请求对象{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String> getParamMap(ServletRequest request)
+    {
+        Map<String, String> params = new HashMap<>();
+        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
+        {
+            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+        }
+        return params;
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 将字符串渲染到客户端
+     * 
+     * @param response 渲染对象
+     * @param string 待渲染的字符串
+     */
+    public static void renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setStatus(200);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json"))
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtil.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StringUtil.inStringIgnoreCase(ajax, "json", "xml");
+    }
+
+    /**
+     * 内容编码
+     * 
+     * @param str 内容
+     * @return 编码后的内容
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 内容解码
+     * 
+     * @param str 内容
+     * @return 解码后的内容
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+}

+ 71 - 0
service-base/src/main/java/com/simuwang/base/common/util/SqlUtil.java

@@ -0,0 +1,71 @@
+package com.simuwang.base.common.util;
+
+
+import cn.hutool.core.exceptions.UtilException;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * sql操作工具类
+ * 
+ * @author ruoyi
+ */
+public class SqlUtil
+{
+    /**
+     * 定义常用的 sql关键字
+     */
+    public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
+
+    /**
+     * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
+     */
+    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+    /**
+     * 限制orderBy最大长度
+     */
+    private static final int ORDER_BY_MAX_LENGTH = 500;
+
+    /**
+     * 检查字符,防止注入绕过
+     */
+    public static String escapeOrderBySql(String value)
+    {
+        if (StringUtil.isNotEmpty(value) && !isValidOrderBySql(value))
+        {
+            throw new UtilException("参数不符合规范,不能进行查询");
+        }
+        if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
+        {
+            throw new UtilException("参数已超过最大限制,不能进行查询");
+        }
+        return value;
+    }
+
+    /**
+     * 验证 order by 语法是否符合规范
+     */
+    public static boolean isValidOrderBySql(String value)
+    {
+        return value.matches(SQL_PATTERN);
+    }
+
+    /**
+     * SQL关键字检查
+     */
+    public static void filterKeyword(String value)
+    {
+        if (StringUtils.isEmpty(value))
+        {
+            return;
+        }
+        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
+        for (String sqlKeyword : sqlKeywords)
+        {
+            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
+            {
+                throw new UtilException("参数存在SQL注入风险");
+            }
+        }
+    }
+}

+ 629 - 0
service-base/src/main/java/com/simuwang/base/common/util/StringUtil.java

@@ -1,7 +1,28 @@
 package com.simuwang.base.common.util;
 
+import cn.hutool.core.util.StrUtil;
+
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.List;
+
+import cn.hutool.core.text.StrFormatter;
+import com.simuwang.base.common.conts.Constants;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.AntPathMatcher;
+
+import java.util.*;
+
 public class StringUtil {
 
+    private static final List<String> DATE_FORMATS = Arrays.asList("yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd");
+
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
     public static String retainChineseCharacters(String value) {
         // 正则表达式匹配中文字符
         String regex = "[^\\u4e00-\\u9fa5]";
@@ -9,4 +30,612 @@ public class StringUtil {
         return value.replaceAll(regex, "");
     }
 
+    public static boolean isValidDate(String dateString) {
+        if (StrUtil.isBlank(dateString)) {
+            return false;
+        }
+        dateString = dateString.replaceAll("年", "-").replaceAll("月", "-");
+        for (String format : DATE_FORMATS) {
+            SimpleDateFormat sdf = new SimpleDateFormat(format);
+            // 设置严格模式
+            sdf.setLenient(false);
+            try {
+                sdf.parse(dateString);
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * 获取参数不为空值
+     *
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     *
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     *
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     *
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     *
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     *
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     *
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     *
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 判断是否为空,并且不是空白字符
+     *
+     * @param str 要判断的value
+     * @return 结果
+     */
+    public static boolean hasText(String str)
+    {
+        return (str != null && !str.isEmpty() && containsText(str));
+    }
+
+    private static boolean containsText(CharSequence str)
+    {
+        int strLen = str.length();
+        for (int i = 0; i < strLen; i++)
+        {
+            if (!Character.isWhitespace(str.charAt(i)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     *
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param params 参数值
+     * @return 格式化后的文本
+     */
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }
+
+    /**
+     * 是否为http(s)://开头
+     *
+     * @param link 链接
+     * @return 结果
+     */
+    public static boolean ishttp(String link)
+    {
+        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
+    }
+
+    /**
+     * 字符串转set
+     *
+     * @param str 字符串
+     * @param sep 分隔符
+     * @return set集合
+     */
+    public static final Set<String> str2Set(String str, String sep)
+    {
+        return new HashSet<String>(str2List(str, sep, true, false));
+    }
+
+    /**
+     * 字符串转list
+     *
+     * @param str 字符串
+     * @param sep 分隔符
+     * @param filterBlank 过滤纯空白
+     * @param trim 去掉首尾空白
+     * @return list集合
+     */
+    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
+    {
+        List<String> list = new ArrayList<String>();
+        if (StringUtils.isEmpty(str))
+        {
+            return list;
+        }
+
+        // 过滤空白字符串
+        if (filterBlank && StringUtils.isBlank(str))
+        {
+            return list;
+        }
+        String[] split = str.split(sep);
+        for (String string : split)
+        {
+            if (filterBlank && StringUtils.isBlank(string))
+            {
+                continue;
+            }
+            if (trim)
+            {
+                string = string.trim();
+            }
+            list.add(string);
+        }
+
+        return list;
+    }
+
+    /**
+     * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+     *
+     * @param collection 给定的集合
+     * @param array 给定的数组
+     * @return boolean 结果
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+    /**
+     * 驼峰转下划线命名
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 前置字符是否大写
+        boolean preCharIsUpperCase = true;
+        // 当前字符是否大写
+        boolean curreCharIsUpperCase = true;
+        // 下一字符是否大写
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     *
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     *
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 驼峰式命名法
+     * 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        if (s.indexOf(SEPARATOR) == -1)
+        {
+            return s;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+     *
+     * @param str 指定字符串
+     * @param strs 需要检查的字符串数组
+     * @return 是否匹配
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断url是否与规则配置:
+     * ? 表示单个字符;
+     * * 表示一层路径内的任意字符串,不可跨层级;
+     * ** 表示任意层路径;
+     *
+     * @param pattern 匹配规则
+     * @param url 需要匹配的url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+    /**
+     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+     *
+     * @param num 数字对象
+     * @param size 字符串指定长度
+     * @return 返回数字的字符串格式,该字符串为指定长度。
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+     *
+     * @param s 原始字符串
+     * @param size 字符串指定长度
+     * @param c 用于补齐的字符
+     * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
+     */
+    public static final String padl(final String s, final int size, final char c)
+    {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null)
+        {
+            final int len = s.length();
+            if (s.length() <= size)
+            {
+                for (int i = size - len; i > 0; i--)
+                {
+                    sb.append(c);
+                }
+                sb.append(s);
+            }
+            else
+            {
+                return s.substring(len - size, len);
+            }
+        }
+        else
+        {
+            for (int i = size; i > 0; i--)
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
 }

+ 15 - 0
service-base/src/main/java/com/simuwang/base/mapper/CompanyEmailConfigMapper.java

@@ -0,0 +1,15 @@
+package com.simuwang.base.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.simuwang.base.pojo.dos.CompanyEmailConfigDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * FileName: CompanyEmailConfigMapper
+ * Author:   chenjianhua
+ * Date:     2024/9/7 12:59
+ * Description: ${DESCRIPTION}
+ */
+@Mapper
+public interface CompanyEmailConfigMapper extends BaseMapper<CompanyEmailConfigDO> {
+}

+ 18 - 0
service-base/src/main/java/com/simuwang/base/mapper/CompanyInformationMapper.java

@@ -0,0 +1,18 @@
+package com.simuwang.base.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: CompanyInformationMapper
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:30
+ * Description: ${DESCRIPTION}
+ */
+@Mapper
+public interface CompanyInformationMapper {
+    public List<Map<String, String>> searchCompanyInfoByKeyword(@Param("keyword") String keyword);
+}

+ 24 - 0
service-base/src/main/java/com/simuwang/base/mapper/FundInfomationMapper.java

@@ -0,0 +1,24 @@
+package com.simuwang.base.mapper;
+
+import com.simuwang.base.pojo.vo.FundInformationVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: FundInfomationMapper
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:11
+ * Description: ${DESCRIPTION}
+ */
+@Mapper
+public interface FundInfomationMapper {
+    List<Map<String, String>> searchFundInfoByKeyword(@Param("keyword") String keyword);
+
+    List<FundInformationVO> searchFundInfoList(@Param("fundId") String fundId, @Param("fundName") String fundName,
+                                               @Param("companyName") String companyName, @Param("navFrequency") Integer navFrequency,
+                                               @Param("assetFrequency") Integer assetFrequency,@Param("startDate") Integer startDate,
+                                               @Param("endDate")Integer endDate);
+}

+ 17 - 0
service-base/src/main/java/com/simuwang/base/mapper/FundReportFrequencyMapper.java

@@ -0,0 +1,17 @@
+package com.simuwang.base.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.simuwang.base.pojo.dos.FundReportFrequencyDO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * FileName: FundReportFrequencyMapper
+ * Author:   chenjianhua
+ * Date:     2024/9/6 17:22
+ * Description: ${DESCRIPTION}
+ */
+@Mapper
+public interface FundReportFrequencyMapper extends BaseMapper<FundReportFrequencyDO> {
+    public FundReportFrequencyDO getFrequencyByFundId(@Param("fundId") String fundId);
+}

+ 70 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/CompanyEmailConfigDO.java

@@ -0,0 +1,70 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: CompanyEmailConfigDO
+ * Author:   chenjianhua
+ * Date:     2024/9/7 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("company_email_config")
+public class CompanyEmailConfigDO {
+    /**
+     * 主键Id
+     */
+    @TableId(value = "id",type = IdType.AUTO)
+    private Integer id;
+    /**
+     * 公司ID
+     */
+    @TableField(value = "company_id")
+    private String companyId;
+    /**
+     * 公司名称
+     */
+    @TableField(value = "company_name")
+    private String companyName;
+    /**
+     * 邮箱地址
+     */
+    @TableField(value = "email")
+    private String email;
+    /**
+     * 邮箱地址
+     */
+    @TableField(value = "open_status")
+    private Integer openStatus;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 70 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/CompanyEmailSendHistoryDO.java

@@ -0,0 +1,70 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: CompanyEmailSendHistoryDO
+ * Author:   chenjianhua
+ * Date:     2024/9/7 13:36
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("company_email_config")
+public class CompanyEmailSendHistoryDO {
+    /**
+     * 主键Id
+     */
+    @TableId(value = "id",type = IdType.AUTO)
+    private Integer id;
+    /**
+     * 邮箱地址
+     */
+    @TableField(value = "email")
+    private String email;
+    /**
+     * 邮箱地址
+     */
+    @TableField(value = "send_status")
+    private Integer sendStatus;
+    /**
+     * 发送时间
+     */
+    @TableField(value = "send_time")
+    private Date sendTime;
+    /**
+     * 发送备注
+     */
+    @TableField(value = "send_remark")
+    private String sendRemark;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

File diff suppressed because it is too large
+ 205 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/CompanyInformationDO.java


+ 144 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/FundInformationDO.java

@@ -0,0 +1,144 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: FundInformation
+ * Author:   chenjianhua
+ * Date:     2024/9/6 11:34
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("fund_information")
+public class FundInformationDO {
+    /**
+     * 主键Id
+     */
+    @TableId(value = "id")
+    private Integer id;
+    /**
+     * 父级产品ID
+     */
+    @TableField(value = "p_fund_id")
+    private String pFundId;
+    /**
+     * 基金ID
+     */
+    @TableField(value = "fund_id")
+    private String fundId;
+    /**
+     * 基金全称
+     */
+    @TableField(value = "fund_name")
+    private String fundName;
+    /**
+     * 基金简称
+     */
+    @TableField(value = "fund_short_name")
+    private String fundShortName;
+    /**
+     * 基金类型:1-信托计划,2-有限合伙(已废弃),3-券商资管,4-公募专户,5-单账户,6-证券投资基金,7-海外基金,8-期货资管,9-保险资管、10-创业投资基金、11-股权投资基金、12-银行理财、13-类固收信托(已废弃) 、 14-私募资产配置基金 15公募基金 -1其他投资基金
+     */
+    @TableField(value = "fund_type")
+    private Integer fundType;
+    /**
+     * 管理类型:1-顾问管理,2-受托管理,3-自我管理
+     */
+    @TableField(value = "manager_type")
+    private Integer managerType;
+    /**
+     * 基础货币,1-人民币,2-港币,3-美元,4-份,-1-其他
+     */
+    @TableField(value = "base_currency")
+    private Integer baseCurrency;
+    /**
+     * 成立日期
+     */
+    @TableField(value = "inception_date")
+    private String inceptionDate;
+    /**
+     * 投资顾问Id
+     */
+    @TableField(value = "advisor_id")
+    private String advisorId;
+    /**
+     * 发行人id
+     */
+    @TableField(value = "issuer_id")
+    private String issuerId;
+    /**
+     * 托管机构Id
+     */
+    @TableField(value = "custodian_id")
+    private String custodianId;
+    /**
+     * 基金管理公司Id
+     */
+    @TableField(value = "trust_id")
+    private String trustId;
+    /**
+     * 备案编码
+     */
+    @TableField(value = "register_number")
+    private String registerNumber;
+    /**
+     * 当前是否备案展示:1-是 0-否 -1-不详
+     */
+    @TableField(value = "is_amac_show")
+    private Integer isAmacShow;
+    /**
+     * 基金运行状态:1-募集中、2-开放运行、3-封闭运行(已废弃)、4-提前清算、5-到期清算、6-发行失败、7-投顾协议已终止、 8-延期清算 -1-其他 9-非正常清算 10-已终止 11-已作废
+     */
+    @TableField(value = "fund_status")
+    private Integer fundStatus;
+    /**
+     * 中基协基金类型:1-私募基金(自主备案),2-期货资管,3-券商资管,4-公募专户 5-证券公司直投基金  6-证券公司私募投资基金 7-基金公司私募投资基金 8-资产支持专项计划 -1-不详
+     */
+    @TableField(value = "amac_source_type")
+    private Integer amacSourceType;
+    /**
+     * 监管公示投资类型:1-混合类,2-固定收益类,3-商品及金融衍生品类,4-权益类,5-其他类产品,6-非标类产品,-1-监管未公示
+     */
+    @TableField(value = "investment_type")
+    private Integer investmentType;
+    /**
+     * 备案日期
+     */
+    @TableField(value = "register_date")
+    private String registerDate;
+    /**
+     * 清算日期
+     */
+    @TableField(value = "liquidate_date")
+    private String liquidateDate;
+    /**
+     * 开始运作日期
+     */
+    @TableField(value = "performance_start_date")
+    private String performanceStartDate;
+    /**
+     * 是否份额基金:1-是 0-否
+     */
+    @TableField(value = "is_shareclass")
+    private Integer isShareclass;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 70 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/FundReportFrequencyDO.java

@@ -0,0 +1,70 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: FundReportFrequency
+ * Author:   chenjianhua
+ * Date:     2024/9/6 14:21
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("fund_report_frequency")
+public class FundReportFrequencyDO {
+    /**
+     * 主键Id
+     */
+    @TableId(value = "id",type= IdType.AUTO)
+    private Integer id;
+    /**
+     * 基金ID
+     */
+    @TableField(value = "fund_id")
+    private String fundId;
+    /**
+     * 净值报送频率,1-日频,2-周频,3-月频,4-季频,5-半年,6-年频
+     */
+    @TableField(value = "nav_frequency")
+    private Integer navFrequency;
+    /**
+     * 规模报送频率,1-日频,2-周频,3-月频,4-季频,5-半年,6-年频
+     */
+    @TableField(value = "asset_frequency")
+    private Integer assetFrequency;
+    /**
+     * 频率备注
+     */
+    @TableField(value = "frequency_remark")
+    private Integer frequencyRemark;
+    /**
+     * 创建者Id
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+    /**
+     * 有效标识
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+}

+ 70 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysConfigDO.java

@@ -0,0 +1,70 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: SysConfigDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_config")
+public class SysConfigDO
+{
+
+    /** 参数主键 */
+    @TableId(value = "config_id",type = IdType.AUTO)
+    private Long configId;
+
+    /** 参数名称 */
+    @TableId(value = "config_name")
+    private String configName;
+
+    /** 参数键名 */
+    @TableId(value = "config_key")
+    private String configKey;
+
+    /** 参数键值 */
+    @TableId(value = "config_value")
+    private String configValue;
+
+    /** 系统内置(Y是 N否) */
+    @TableId(value = "config_type")
+    private String configType;
+
+    /** 备注 */
+    @TableId(value = "remark")
+    private String remark;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 86 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysDictDataDO.java

@@ -0,0 +1,86 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: SysDictDataDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_dict_data")
+public class SysDictDataDO
+{
+
+    /** 字典编码 */
+    @TableId(value = "dict_code",type = IdType.AUTO)
+    private Long dictCode;
+
+    /** 字典排序 */
+    @TableId(value = "dict_sort")
+    private Long dictSort;
+
+    /** 字典标签 */
+    @TableId(value = "dict_label")
+    private String dictLabel;
+
+    /** 字典键值 */
+    @TableId(value = "dict_value")
+    private String dictValue;
+
+    /** 字典类型 */
+    @TableId(value = "dict_type")
+    private String dictType;
+
+    /** 样式属性(其他样式扩展) */
+    @TableId(value = "css_class")
+    private String cssClass;
+
+    /** 表格字典样式 */
+    @TableId(value = "list_class")
+    private String listClass;
+
+    /** 是否默认(Y是 N否) */
+    @TableId(value = "is_default")
+    private String isDefault;
+
+    /** 状态(0正常 1停用) */
+    @TableId(value = "status")
+    private String status;
+
+    /** 备注 */
+    @TableId(value = "remark")
+    private String remark;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 66 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysDictTypeDO.java

@@ -0,0 +1,66 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: SysDictTypeDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_dict_type")
+public class SysDictTypeDO
+{
+
+    /** 字典主键 */
+    @TableId(value = "dict_id",type = IdType.AUTO)
+    private Long dictId;
+
+    /** 字典名称 */
+    @TableId(value = "dict_name")
+    private String dictName;
+
+    /** 字典类型 */
+    @TableId(value = "dict_type")
+    private String dictType;
+
+    /** 状态(0正常 1停用) */
+    @TableId(value = "status")
+    private String status;
+
+    /** 备注 */
+    @TableId(value = "remark")
+    private String remark;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 99 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysMenuDO.java

@@ -0,0 +1,99 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: SysMenuDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_menu")
+public class SysMenuDO
+{
+    /** 菜单ID */
+    @TableId(value = "menu_id",type = IdType.AUTO)
+    private Long menuId;
+
+    /** 菜单名称 */
+    @TableId(value = "menu_name")
+    private String menuName;
+
+    /** 父菜单ID */
+    @TableId(value = "parent_id")
+    private Long parentId;
+
+    /** 显示顺序 */
+    @TableId(value = "order_num")
+    private Integer orderNum;
+
+    /** 路由地址 */
+    @TableId(value = "path")
+    private String path;
+
+    /** 组件路径 */
+    @TableId(value = "component")
+    private String component;
+
+    /** 路由参数 */
+    @TableId(value = "query")
+    private String query;
+
+    /** 是否为外链(0是 1否) */
+    @TableId(value = "is_frame")
+    private String isFrame;
+
+    /** 是否缓存(0缓存 1不缓存) */
+    @TableId(value = "is_cache")
+    private String isCache;
+
+    /** 类型(M目录 C菜单 F按钮) */
+    @TableId(value = "menu_type")
+    private String menuType;
+
+    /** 显示状态(0显示 1隐藏) */
+    @TableId(value = "visible")
+    private String visible;
+    
+    /** 菜单状态(0正常 1停用) */
+    @TableId(value = "status")
+    private String status;
+
+    /** 权限字符串 */
+    @TableId(value = "perms")
+    private String perms;
+
+    /** 菜单图标 */
+    @TableId(value = "icon")
+    private String icon;
+    /** 备注 */
+    @TableId(value = "remark")
+    private String remark;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 72 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysRoleDO.java

@@ -0,0 +1,72 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * FileName: SysRoleDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_role")
+public class SysRoleDO
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 角色ID */
+    private Long roleId;
+
+    /** 角色名称 */
+    private String roleName;
+
+    /** 角色权限 */
+    private String roleKey;
+
+    /** 角色排序 */
+    private String roleSort;
+
+    /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
+    private String dataScope;
+
+    /** 角色状态(0正常 1停用) */
+    private String status;
+
+    /** 删除标志(0代表存在 1代表删除) */
+    private String delFlag;
+
+    /** 用户是否存在此角色标识 默认不存在 */
+    private boolean flag = false;
+    /** 备注 */
+    @TableId(value = "remark")
+    private String remark;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 24 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysRoleMenuDO.java

@@ -0,0 +1,24 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * FileName: SysRoleMenuDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_role_menu")
+public class SysRoleMenuDO
+{
+    /** 角色ID */
+    @TableId(value = "role_id")
+    private Long roleId;
+    
+    /** 菜单ID */
+    @TableId(value = "menu_id")
+    private Long menuId;
+}

+ 92 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysUserDO.java

@@ -0,0 +1,92 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * FileName: SysUserDO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_user")
+public class SysUserDO
+{
+    /** 用户ID */
+    @TableId(value = "user_id",type = IdType.AUTO)
+    private Long userId;
+
+    /** 用户名称 */
+    @TableId(value = "user_name")
+    private String userName;
+
+    /** 用户类型 */
+    @TableId(value = "user_type")
+    private String userType;
+
+    /** 用户邮箱 */
+    @TableId(value = "email")
+    private String email;
+
+    /** 手机号码 */
+    @TableId(value = "phonenumber")
+    private String phonenumber;
+
+    /** 用户性别 */
+    @TableId(value = "sex")
+    private String sex;
+
+    /** 用户头像 */
+    @TableId(value = "avatar")
+    private String avatar;
+
+    /** 密码 */
+    @TableId(value = "password")
+    private String password;
+    /** 帐号状态(0正常 1停用) */
+    @TableId(value = "status")
+    private String status;
+
+    /** 删除标志(0代表存在 1代表删除) */
+    @TableId(value = "del_flag")
+    private String delFlag;
+    /** 备注 */
+    @TableId(value = "start_date")
+    private String startDate;
+    /** 备注 */
+    @TableId(value = "end_date")
+    private String endDate;
+    /** 备注 */
+    @TableId(value = "remark")
+    private String remark;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 25 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/SysUserRole.java

@@ -0,0 +1,25 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * FileName: SysUserRole
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+@TableName("sys_user_role")
+public class SysUserRole
+{
+    /** 用户ID */
+    @TableField(value = "user_id")
+    private Long userId;
+    
+    /** 角色ID */
+    @TableField(value = "role_id")
+    private Long roleId;
+
+}

+ 8 - 11
service-base/src/main/java/com/simuwang/base/pojo/dto/EmailFundNavDTO.java

@@ -2,9 +2,6 @@ package com.simuwang.base.pojo.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
-import java.util.Date;
-
 @Data
 public class EmailFundNavDTO {
     /**
@@ -18,25 +15,25 @@ public class EmailFundNavDTO {
     /**
      * 净值日期
      */
-    private Date priceDate;
+    private String priceDate;
     /**
      * 单位净值
      */
-    private BigDecimal nav;
+    private String nav;
     /**
      * 累计单位净值
      */
-    private BigDecimal cumulativeNav;
+    private String cumulativeNavWithdrawal;
     /**
-     * 资产份额
+     * 虚拟净值
      */
-    private BigDecimal assetShare;
+    private String virtualNav;
     /**
-     * 资产总值
+     * 资产份额
      */
-    private BigDecimal assetTotal;
+    private String assetShare;
     /**
      * 资产净值(基金规模)
      */
-    private BigDecimal assetNet;
+    private String assetNet;
 }

+ 40 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/CompanyEmailConfigVO.java

@@ -0,0 +1,40 @@
+package com.simuwang.base.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: CompanyEmailConfigDO
+ * Author:   chenjianhua
+ * Date:     2024/9/7 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class CompanyEmailConfigVO {
+    /**
+     * ID
+     */
+    private Integer id;
+    /**
+     * 公司ID
+     */
+    private String companyId;
+    /**
+     * 公司名称
+     */
+    private String companyName;
+    /**
+     * 邮箱地址
+     */
+    private String email;
+    /**
+     * 邮箱地址
+     */
+    private Integer openStatus;
+
+}

+ 48 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/CompanyEmailSendHistoryVO.java

@@ -0,0 +1,48 @@
+package com.simuwang.base.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: CompanyEmailSendHistoryDO
+ * Author:   chenjianhua
+ * Date:     2024/9/7 13:36
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class CompanyEmailSendHistoryVO {
+    /**
+     * 主键Id
+     */
+    private Integer id;
+    /**
+     * 公司ID
+     */
+    private String companyId;
+    /**
+     * 公司名称
+     */
+    private String companyName;
+    /**
+     * 邮箱地址
+     */
+    private String email;
+    /**
+     * 邮箱地址
+     */
+    private Integer sendStatus;
+    /**
+     * 发送时间
+     */
+    private Date sendTime;
+    /**
+     * 发送备注
+     */
+    private String sendRemark;
+
+}

+ 46 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/FundInformationVO.java

@@ -0,0 +1,46 @@
+package com.simuwang.base.pojo.vo;
+
+import lombok.Data;
+
+/**
+ * FileName: FundInformationVO
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:58
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class FundInformationVO {
+
+    /**
+     * 基金ID
+     */
+    private String fundId;
+    /**
+     * 基金简称
+     */
+    private String fundShortName;
+    /**
+     * 管理人
+     */
+    private String companyShortName;
+    /**
+     * 基金成立日期
+     */
+    private String inceptionDate;
+    /**
+     * 最新净值日期
+     */
+    private String lastPriceDate;
+    /**
+     * 净值报送频率,1-日频,2-周频,3-月频,4-季频,5-半年,6-年频
+     */
+    private Integer navFrequency;
+    /**
+     * 规模报送频率,1-日频,2-周频,3-月频,4-季频,5-半年,6-年频
+     */
+    private Integer assetFrequency;
+    /**
+     * 规模备注
+     */
+    private String frequencyRemark;
+}

+ 34 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/FundReportFrequencyVO.java

@@ -0,0 +1,34 @@
+package com.simuwang.base.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: FundReportFrequency
+ * Author:   chenjianhua
+ * Date:     2024/9/6 14:21
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class FundReportFrequencyVO {
+    /**
+     * 基金ID
+     */
+    private String fundId;
+    /**
+     * 净值报送频率,1-日频,2-周频,3-月频,4-季频,5-半年,6-年频
+     */
+    private Integer navFrequency;
+    /**
+     * 规模报送频率,1-日频,2-周频,3-月频,4-季频,5-半年,6-年频
+     */
+    private Integer assetFrequency;
+    /**
+     * 频率备注
+     */
+    private Integer frequencyRemark;
+}

+ 38 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/SysConfigVO.java

@@ -0,0 +1,38 @@
+package com.simuwang.base.pojo.vo;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * FileName: SysConfigVO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class SysConfigVO
+{
+
+    /** 参数主键 */
+    private Long configId;
+
+    /** 参数名称 */
+    private String configName;
+
+    /** 参数键名 */
+    private String configKey;
+
+    /** 参数键值 */
+    private String configValue;
+
+    /** 系统内置(Y是 N否) */
+    private String configType;
+
+    /** 备注 */
+    private String remark;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    private Date updateTime;
+}

+ 42 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/SysDictDataVO.java

@@ -0,0 +1,42 @@
+package com.simuwang.base.pojo.vo;
+
+
+import lombok.Data;
+
+/**
+ * FileName: SysDictDataVO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class SysDictDataVO
+{
+    /** 字典编码 */
+    private Long dictCode;
+
+    /** 字典排序 */
+    private Long dictSort;
+
+    /** 字典标签 */
+    private String dictLabel;
+
+    /** 字典键值 */
+    private String dictValue;
+
+    /** 字典类型 */
+    private String dictType;
+
+    /** 样式属性(其他样式扩展) */
+    private String cssClass;
+
+    /** 表格字典样式 */
+    private String listClass;
+
+    /** 是否默认(Y是 N否) */
+    private String isDefault;
+
+    /** 状态(0正常 1停用) */
+    private String status;
+
+}

+ 26 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/SysDictTypeVO.java

@@ -0,0 +1,26 @@
+package com.simuwang.base.pojo.vo;
+
+import lombok.Data;
+
+/**
+ * FileName: SysDictTypeVO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class SysDictTypeVO
+{
+    /** 字典主键 */
+    private Long dictId;
+
+    /** 字典名称 */
+    private String dictName;
+
+    /** 字典类型 */
+    private String dictType;
+
+    /** 状态(0正常 1停用) */
+    private String status;
+
+}

+ 66 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/SysMenuVO.java

@@ -0,0 +1,66 @@
+package com.simuwang.base.pojo.vo;
+
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * FileName: SysMenuVO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class SysMenuVO
+{
+    /** 菜单ID */
+    private Long menuId;
+
+    /** 菜单名称 */
+    private String menuName;
+
+    /** 父菜单名称 */
+    private String parentName;
+
+    /** 父菜单ID */
+    private Long parentId;
+
+    /** 显示顺序 */
+    private Integer orderNum;
+
+    /** 路由地址 */
+    private String path;
+
+    /** 组件路径 */
+    private String component;
+
+    /** 路由参数 */
+    private String query;
+
+    /** 是否为外链(0是 1否) */
+    private String isFrame;
+
+    /** 是否缓存(0缓存 1不缓存) */
+    private String isCache;
+
+    /** 类型(M目录 C菜单 F按钮) */
+    private String menuType;
+
+    /** 显示状态(0显示 1隐藏) */
+    private String visible;
+    
+    /** 菜单状态(0正常 1停用) */
+    private String status;
+
+    /** 权限字符串 */
+    private String perms;
+
+    /** 菜单图标 */
+    private String icon;
+
+    /** 子菜单 */
+    private List<SysMenuVO> children = new ArrayList<SysMenuVO>();
+
+}

+ 56 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/SysRoleVO.java

@@ -0,0 +1,56 @@
+package com.simuwang.base.pojo.vo;
+
+import lombok.Data;
+
+import java.util.Set;
+
+/**
+ * FileName: SysRoleVO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class SysRoleVO
+{
+
+    /** 角色ID */
+    private Long roleId;
+
+    /** 角色名称 */
+    private String roleName;
+
+    /** 角色权限 */
+    private String roleKey;
+
+    /** 角色排序 */
+    private Integer roleSort;
+
+    /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
+    private String dataScope;
+
+    /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
+    private boolean menuCheckStrictly;
+
+    /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
+    private boolean deptCheckStrictly;
+
+    /** 角色状态(0正常 1停用) */
+    private String status;
+
+    /** 删除标志(0代表存在 1代表删除) */
+    private String delFlag;
+
+    /** 用户是否存在此角色标识 默认不存在 */
+    private boolean flag = false;
+
+    /** 菜单组 */
+    private Long[] menuIds;
+
+    /** 部门组(数据权限) */
+    private Long[] deptIds;
+
+    /** 角色菜单权限 */
+    private Set<String> permissions;
+
+}

+ 67 - 0
service-base/src/main/java/com/simuwang/base/pojo/vo/SysUserVO.java

@@ -0,0 +1,67 @@
+package com.simuwang.base.pojo.vo;
+
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * FileName: SysUserVO
+ * Author:   chenjianhua
+ * Date:     2024/9/8 12:45
+ * Description: ${DESCRIPTION}
+ */
+@Data
+public class SysUserVO
+{
+    /** 用户ID */
+    private Long userId;
+
+    /** 用户账号 */
+    private String userName;
+
+    /** 用户类型1-内部系统,2-外部系统 */
+    private String userType;
+
+    /** 用户邮箱 */
+    private String email;
+
+    /** 手机号码 */
+    private String phonenumber;
+
+    /** 手机号码 */
+    private String startDate;
+
+    /** 手机号码 */
+    private String endDate;
+
+    /** 用户性别 */
+    private String sex;
+
+    /** 用户头像 */
+    private String avatar;
+
+    /** 密码 */
+    private String password;
+
+    /** 帐号状态(0正常 1停用) */
+    private String status;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private String delFlag;
+
+    /** 最后登录IP */
+    private String loginIp;
+
+    /** 最后登录时间 */
+    private Date loginDate;
+
+    /** 角色对象 */
+    private List<SysRoleVO> roles;
+
+    /** 角色组 */
+    private Long[] roleIds;
+
+    /** 角色ID */
+    private Long roleId;
+}

+ 53 - 0
service-base/src/main/resources/mapper/CompanyInformationMapper.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.CompanyInformationMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.CompanyInformationDO">
+        <id column="company_id" property="companyId"/>
+        <result column="is_amac_show" property="isAmacShow"/>
+        <result column="fund_practitioners_count" property="fundPractitionersCount"/>
+        <result column="managed_fund_count" property="managedFundCount"/>
+        <result column="cancel_date" property="cancelDate"/>
+        <result column="cancel_type" property="cancelType"/>
+        <result column="credit_code" property="creditCode"/>
+        <result column="employee_cnts" property="employeeCnts"/>
+        <result column="company_asset_size" property="companyAssetSize"/>
+        <result column="paid_capital" property="paidCapital"/>
+        <result column="capital_paid_rate" property="capitalPaidRate"/>
+        <result column="nature_business_type" property="natureBusinessType"/>
+        <result column="business_type" property="businessType"/>
+        <result column="member_type" property="memberType"/>
+        <result column="join_date" property="joinDate"/>
+        <result column="is_member" property="isMember"/>
+        <result column="register_date" property="registerDate"/>
+        <result column="register_status" property="registerStatus"/>
+        <result column="register_number" property="registerNumber"/>
+        <result column="registered_capital" property="registeredCapital"/>
+        <result column="reg_country" property="regCountry"/>
+        <result column="reg_province" property="regProvince"/>
+        <result column="reg_city" property="regCity"/>
+        <result column="country" property="country"/>
+        <result column="province" property="province"/>
+        <result column="city" property="city"/>
+        <result column="company_address2" property="companyAddress2"/>
+        <result column="company_address" property="companyAddress"/>
+        <result column="domicile_id" property="domicileId"/>
+        <result column="establish_date" property="establishDate"/>
+        <result column="organization_number" property="organizationNumber"/>
+        <result column="company_type" property="companyType"/>
+        <result column="company_name" property="companyName"/>
+        <result column="company_short_name" property="companyShortName"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updatetime" property="updateTime"/>
+        <result column="isvalid" property="isvalid"/>
+    </resultMap>
+    <select id="searchCompanyInfoByKeyword" resultType="java.util.Map" parameterType="java.lang.String">
+        select c.company_id as companyId,
+        c.company_name as companyName
+        c.register_number as registerNumber
+        from PPW_EMAIL.company_information c where c.isvalid =1
+        <if test="keyword != null and keyword !=''">
+            and (c.company_name like concat('%',#{keyword},'%') or c.company_short_name like concat('%',#{keyword},'%') or c.register_number like concat('%',#{keyword},'%'))
+        </if>
+    </select>
+
+</mapper>

+ 77 - 0
service-base/src/main/resources/mapper/FundInformationMapper.xml

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.FundInfomationMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.FundInformationDO">
+        <id column="id" property="id"/>
+        <result column="p_fund_id" property="pFundId"/>
+        <result column="fund_name" property="fundName"/>
+        <result column="fund_short_name" property="fundShortName"/>
+        <result column="fund_type" property="fundType"/>
+        <result column="manager_type" property="managerType"/>
+        <result column="base_currency" property="baseCurrency"/>
+        <result column="inception_date" property="inceptionDate"/>
+        <result column="advisor_id" property="advisorId"/>
+        <result column="issuer_id" property="issuerId"/>
+        <result column="custodian_id" property="custodianId"/>
+        <result column="register_number" property="registerNumber"/>
+        <result column="register_date" property="registerDate"/>
+        <result column="is_amac_show" property="isAmacShow"/>
+        <result column="fund_status" property="fundStatus"/>
+        <result column="amac_source_type" property="amacSourceType"/>
+        <result column="investment_type" property="investmentType"/>
+        <result column="liquidate_date" property="liquidateDate"/>
+        <result column="performance_start_date" property="performanceStartDate"/>
+        <result column="is_shareclass" property="isShareclass"/>
+        <result column="trust_id" property="trustId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updatetime" property="updateTime"/>
+        <result column="isvalid" property="isvalid"/>
+    </resultMap>
+    <select id="searchFundInfoByKeyword" resultType="java.util.Map" parameterType="java.lang.String">
+        select f.fund_id as fundId,
+        f.fund_short_name as fundShortName,
+        f.register_number as registerNumber
+        from PPW_EMAIL.fund_information f where f.isvalid =1
+        <if test="keyword != null and keyword !=''">
+            and (f.fund_name like concat('%',#{keyword},'%') or f.fund_short_name like concat('%',#{keyword},'%') or f.register_number like concat('%',#{keyword},'%'))
+        </if>
+    </select>
+    <select id="searchFundInfoList" resultType="com.simuwang.base.pojo.vo.FundInformationVO">
+        select f.fund_id as fundId,
+               f.fund_short_name as fundShortName,
+               c.company_short_name as companyShortName,
+               f.inception_date as inceptionDate,
+               n.last_price_date as lastPriceDate,
+               r.nav_frequency as navFrequency,
+               r.asset_Frequency as assetFrequency,
+               r.frequency_remark as frequencyRemark
+        from PPW_EMAIL.fund_information f
+        join PPW_EMAIL.company_information c on f.trust_id = c.company_id
+        left join (select nv.fund_id,max(nv.price_date) as last_price_date from PPW_EMAIL.nav nv where nv.isvalid =1 group by nv.fund_id) n
+        on f.fund_id = n .fund_id
+        left join PPW_EMAIL.fund_report_frequency r on r.fund_id = f.fund_id and r.isvalid =1
+        where f.isvalid =1 and c.isvalid =1
+        <if test="fundId != null and fundId !=''">
+            and f.fund_id like concat('%',#{fundId},'%')
+        </if>
+        <if test="fundName != null and fundName !=''">
+            and (f.fund_name like concat('%',#{fundName},'%') or f.fund_short_name like concat('%',#{fundName},'%'))
+        </if>
+        <if test="companyName != null and companyName !=''">
+            and (c.company_name like concat('%',#{companyName},'%') or c.company_short_name like concat('%',#{companyName},'%'))
+        </if>
+        <if test="navFrequency != null and navFrequency !=''">
+            and r.nav_frequency = #{navFrequency}
+        </if>
+        <if test="assetFrequency != null and assetFrequency !=''">
+            and r.asset_Frequency = #{navFrequency}
+        </if>
+        <if test="startDate != null and startDate !=''">
+            and r.inception_date <![CDATA[ >= ]]> #{startDate}
+        </if>
+        <if test="endDate != null and endDate !=''">
+            and r.inception_date <![CDATA[ <= ]]> #{endDate}
+        </if>
+    </select>
+
+</mapper>

+ 34 - 0
service-base/src/main/resources/mapper/FundReportFrequencyMapper.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.FundReportFrequencyMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.FundReportFrequencyDO">
+        <id column="id" property="id"/>
+        <result column="fund_id" property="fundId"/>
+        <result column="nav_frequency" property="navFrequency"/>
+        <result column="asset_frequency" property="assetFrequency"/>
+        <result column="frequency_remark" property="frequencyRemark"/>
+        <result column="creatorid" property="creatorId"/>
+        <result column="updaterid" property="updaterId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updatetime" property="updateTime"/>
+        <result column="isvalid" property="isvalid"/>
+    </resultMap>
+    <sql id="selectFundReportFrequencyVo">
+        select id, fund_id, nav_frequency, frequency_remark, asset_frequency, creatorid, updaterid, updatetime, createtime, isvalid
+        from PPW_EMAIL.fund_report_frequency
+    </sql>
+    <sql id="sqlwhereSearch">
+        <where>
+            isvalid =1
+            <if test="fundId !=null and fundId != ''">
+                and fund_id = #{fundId}
+            </if>
+        </where>
+    </sql>
+    <select id="getFrequencyByFundId" resultType="com.simuwang.base.pojo.dos.FundReportFrequencyDO"
+            parameterType="java.lang.String">
+        <include refid="selectFundReportFrequencyVo"/>
+        <include refid="sqlwhereSearch"/>
+    </select>
+
+</mapper>

+ 22 - 8
service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java

@@ -40,7 +40,7 @@ import java.util.stream.Collectors;
 @Service
 public class EmailParseService {
 
-    private static final Logger logger = LoggerFactory.getLogger(EmailParseService.class);
+    private static final Logger log = LoggerFactory.getLogger(EmailParseService.class);
 
     private final EmailTypeRuleMapper emailTypeRuleMapper;
     private final EmailRuleConfig emailRuleConfig;
@@ -71,19 +71,33 @@ public class EmailParseService {
         try {
             emailContentMap = realEmail(mailboxInfoDTO, emailTypeMap, startDate, endDate);
         } catch (Exception e) {
-            logger.info("采集邮件失败 -> 邮箱配置信息:{},堆栈信息:{}", mailboxInfoDTO, ExceptionUtil.stacktraceToString(e));
+            log.info("采集邮件失败 -> 邮箱配置信息:{},堆栈信息:{}", mailboxInfoDTO, ExceptionUtil.stacktraceToString(e));
             return;
         }
         for (Map.Entry<String, List<EmailContentInfoDTO>> emailEntry : emailContentMap.entrySet()) {
             List<EmailContentInfoDTO> emailContentInfoDTOList = emailEntry.getValue();
+            if (CollUtil.isEmpty(emailContentInfoDTOList)) {
+                log.warn("未采集到正文或附件");
+            }
+            List<EmailFundNavDTO> emailFundNavDTOList = CollUtil.newArrayList();
             for (EmailContentInfoDTO emailContentInfoDTO : emailContentInfoDTOList) {
-                List<EmailFundNavDTO> emailFundNavDTOList = parseEmailContent(emailContentInfoDTO, emailFieldMap);
-
+                try {
+                    List<EmailFundNavDTO> fundNavDTOList = parseEmail(emailContentInfoDTO, emailFieldMap);
+                    emailFundNavDTOList.addAll(fundNavDTOList);
+                } catch (Exception e) {
+                    log.error("堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
+                }
             }
+            if (CollUtil.isEmpty(emailFundNavDTOList)) {
+                log.warn("未解析到净值 -> 邮件主题:{},邮件日期:{}", emailContentInfoDTOList.get(0).getEmailTitle(), emailContentInfoDTOList.get(0).getEmailDate());
+                continue;
+            }
+            // todo 邮件信息表,邮件文件表,邮件净值表,邮件规模表,基金净值表
+
         }
     }
 
-    private List<EmailFundNavDTO> parseEmailContent(EmailContentInfoDTO emailContentInfoDTO, Map<String, List<String>> emailFieldMap) {
+    private List<EmailFundNavDTO> parseEmail(EmailContentInfoDTO emailContentInfoDTO, Map<String, List<String>> emailFieldMap) {
         Integer emailType = emailContentInfoDTO.getEmailType();
         AbstractEmailParser emailParser = emailParserFactory.getInstance(emailType);
         return emailParser.parse(emailContentInfoDTO, emailFieldMap);
@@ -144,10 +158,10 @@ public class EmailParseService {
                 emailType = EmailUtil.getEmailTypeBySubject(message.getSubject(), emailTypeMap);
                 String emailDateStr = DateUtil.format(emailDate, DateConst.YYYY_MM_DD_HH_MM_SS);
                 if (emailType == null) {
-                    logger.info("邮件不满足解析条件 -> 邮件主题:{},邮件日期:{}", message.getSubject(), emailDateStr);
+                    log.info("邮件不满足解析条件 -> 邮件主题:{},邮件日期:{}", message.getSubject(), emailDateStr);
                     continue;
                 }
-                logger.info("邮件采集成功 -> 邮件主题:{},邮件日期:{}", message.getSubject(), emailDateStr);
+                log.info("邮件采集成功 -> 邮件主题:{},邮件日期:{}", message.getSubject(), emailDateStr);
                 Object content = message.getContent();
                 // 1.邮件为MIME多部分消息体:可能既有邮件又有正文
                 if (content instanceof MimeMultipart) {
@@ -177,7 +191,7 @@ public class EmailParseService {
                     emailMessageMap.put(uuidKey, emailContentInfoDTOList);
                 }
             } catch (Exception e) {
-                logger.error("获取邮箱的邮件报错,堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
+                log.error("获取邮箱的邮件报错,堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
             }
         }
         folder.close(false);

+ 231 - 3
service-daq/src/main/java/com/simuwang/daq/service/NavEmailParser.java

@@ -1,25 +1,32 @@
 package com.simuwang.daq.service;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.Pair;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
+import com.simuwang.base.common.conts.DateConst;
+import com.simuwang.base.common.conts.EmailFieldConst;
 import com.simuwang.base.common.conts.EmailTypeConst;
 import com.simuwang.base.common.util.ExcelUtil;
 import com.simuwang.base.common.util.StringUtil;
 import com.simuwang.base.pojo.dto.EmailContentInfoDTO;
 import com.simuwang.base.pojo.dto.EmailFundNavDTO;
+import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
 import java.io.File;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 /**
  * @author mozuwen
@@ -29,6 +36,13 @@ import java.util.Map;
 @Component
 public class NavEmailParser extends AbstractEmailParser {
 
+    private static final Logger log = LoggerFactory.getLogger(AbstractEmailParser.class);
+
+    private static final Integer ROW_DIRECTION_TYPE = 1;
+    private static final Integer COLUMN_DIRECTION_TYPE = 2;
+
+    private static final int MAX_COLUMN = 20;
+
     @Override
     public boolean isSupport(Integer emailType) {
         return EmailTypeConst.NAV_EMAIL_TYPE.equals(emailType);
@@ -58,27 +72,234 @@ public class NavEmailParser extends AbstractEmailParser {
      * @return 解析到的净值数据
      */
     private List<EmailFundNavDTO> parseExcelFile(String filePath, Map<String, List<String>> emailFieldMap) {
-        List<EmailFundNavDTO> fundNavDTOList = CollUtil.newArrayList();
         File file = new File(filePath);
         Sheet sheet = ExcelUtil.getSheet(file, 0);
+        // 1.找到表头所在位置
         Map<String, Pair<Integer, Integer>> fieldPositionMap = getFieldPosition(sheet, emailFieldMap);
         if (MapUtil.isEmpty(fieldPositionMap)) {
+            log.warn("找不到文件表头字段 -> 文件:{}", filePath);
+            return CollUtil.newArrayList();
+        }
+        // 2.解析sheet中的净值数据
+        return parseSheetData(sheet, fieldPositionMap);
+    }
 
+    private List<EmailFundNavDTO> parseSheetData(Sheet sheet, Map<String, Pair<Integer, Integer>> fieldPositionMap) {
+        List<EmailFundNavDTO> fundNavDTOList = CollUtil.newArrayList();
+        // 通过表头所在位置判断是行数据还是列数据
+        Integer dataDirectionType = detectDataDirection(fieldPositionMap);
+        // 数据起始行,起始列
+        int initRow = dataDirectionType.equals(ROW_DIRECTION_TYPE) ? fieldPositionMap.values().stream().map(Pair::getKey).max(Integer::compareTo).orElse(0)
+                : fieldPositionMap.values().stream().map(Pair::getKey).min(Integer::compareTo).orElse(0);
+        int initColumn = fieldPositionMap.values().stream().map(Pair::getValue).min(Integer::compareTo).orElse(0);
+        if (dataDirectionType.equals(ROW_DIRECTION_TYPE)) {
+            // 表头字段-列号映射关系
+            Map<String, Integer> fieldColumnMap = getFieldRow(fieldPositionMap);
+            int lastRowNum = sheet.getLastRowNum();
+            // 遍历可能的数据行
+            for (int rowNum = initRow + 1; rowNum <= lastRowNum; rowNum++) {
+                Row sheetRow = sheet.getRow(rowNum);
+                Optional.ofNullable(readSheetRowData(sheetRow, fieldColumnMap)).ifPresent(fundNavDTOList::add);
+            }
         }
+        if (dataDirectionType.equals(COLUMN_DIRECTION_TYPE)) {
+            // 表头字段-行号映射关系
+            Map<Integer, String> fieldRowMap = getRowField(fieldPositionMap);
+            int lastRow = fieldPositionMap.values().stream().map(Pair::getKey).max(Integer::compareTo).orElse(0);
+            // 遍历每一列
+            for (int columnNum = initColumn + 1; columnNum < MAX_COLUMN; columnNum++) {
+                Map<String, String> fieldValueMap = MapUtil.newHashMap();
+                for (int rowNum = initRow; rowNum <= lastRow; rowNum++) {
+                    Row row = sheet.getRow(rowNum);
+                    Cell cell = row.getCell(columnNum);
+                    if (cell == null) {
+                        continue;
+                    }
+                    fieldValueMap.put(fieldRowMap.get(rowNum), cell.getStringCellValue());
+                }
+                Optional.ofNullable(buildEmailFundNavDTO(fieldValueMap)).ifPresent(fundNavDTOList::add);
+            }
+        }
+
+        // 兼容净值日期为空的情况
+        addPriceDateIfMiss(fundNavDTOList, getPriceDateFromSheet(sheet, initRow));
         return fundNavDTOList;
     }
 
+    private void addPriceDateIfMiss(List<EmailFundNavDTO> fundNavDTOList, String priceDate) {
+        if (fundNavDTOList.stream().map(EmailFundNavDTO::getPriceDate).allMatch(StrUtil::isBlank)) {
+            fundNavDTOList.forEach(e -> e.setPriceDate(priceDate));
+        }
+    }
+
+    private String getPriceDateFromSheet(Sheet sheet, Integer maxRowNum) {
+        Map<Integer, String> priceDateMap = MapUtil.newHashMap();
+        for (int rowNum = 0; rowNum < maxRowNum; rowNum++) {
+            Row row = sheet.getRow(rowNum);
+            if (row == null) {
+                continue;
+            }
+            int lastCellNum = row.getLastCellNum();
+            for (int columnNum = 0; columnNum < lastCellNum; columnNum++) {
+                Cell cell = row.getCell(columnNum);
+                if (cell == null) {
+                    continue;
+                }
+                String cellValue = cell.getStringCellValue();
+                if (StrUtil.isNotBlank(cellValue) && cellValue.contains("截至")) {
+                    int index = cellValue.indexOf("截至");
+                    String date = cellValue.substring(index + 2, index + 2 + 10);
+                    if (StrUtil.isNotBlank(date)) {
+                        date = date.replaceAll("年", "-").replaceAll("月", "-");
+                    }
+                    priceDateMap.put(1, date);
+                    continue;
+                }
+                boolean isValidDate = StringUtil.isValidDate(cellValue);
+                if (isValidDate) {
+                    String date = cellValue.replaceAll("年", "-").replaceAll("月", "-");
+                    priceDateMap.put(2, date);
+                }
+            }
+        }
+        if (MapUtil.isNotEmpty(priceDateMap)) {
+            Integer key = priceDateMap.keySet().stream().min(Integer::compareTo).orElse(null);
+            return priceDateMap.get(key);
+        }
+        return null;
+    }
+
+    private EmailFundNavDTO buildEmailFundNavDTO(Map<String, String> fieldValueMap) {
+        if (MapUtil.isEmpty(fieldValueMap) || fieldValueMap.values().stream().allMatch(StrUtil::isBlank)) {
+            return null;
+        }
+        EmailFundNavDTO fundNavDTO = new EmailFundNavDTO();
+        fundNavDTO.setFundName(fieldValueMap.get(EmailFieldConst.FUND_NAME));
+        fundNavDTO.setRegisterNumber(fieldValueMap.get(EmailFieldConst.REGISTER_NUMBER));
+        fundNavDTO.setPriceDate(fieldValueMap.get(EmailFieldConst.PRICE_DATE));
+        fundNavDTO.setNav(fieldValueMap.get(EmailFieldConst.NAV));
+        fundNavDTO.setCumulativeNavWithdrawal(fieldValueMap.get(EmailFieldConst.CUMULATIVE_NAV_WITHDRAWAL));
+        String assetNet = fieldValueMap.get(EmailFieldConst.ASSET_NET);
+        if (StrUtil.isBlank(assetNet) || !StrUtil.isNumeric(assetNet)) {
+            assetNet = null;
+        }
+        fundNavDTO.setAssetNet(assetNet);
+        String assetShares = fieldValueMap.get(EmailFieldConst.ASSET_NET);
+        if (StrUtil.isBlank(assetShares) || !StrUtil.isNumeric(assetShares)) {
+            assetShares = null;
+        }
+        fundNavDTO.setAssetShare(assetShares);
+        return fundNavDTO;
+    }
+
 
+    private EmailFundNavDTO readSheetRowData(Row sheetRow, Map<String, Integer> columnFieldMap) {
+        if (sheetRow == null) {
+            return null;
+        }
+        String nav = columnFieldMap.get(EmailFieldConst.NAV) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.NAV)) != null
+                ? sheetRow.getCell(columnFieldMap.get(EmailFieldConst.NAV)).getStringCellValue() : null;
+        String cumulativeNavWithdrawal = columnFieldMap.get(EmailFieldConst.CUMULATIVE_NAV_WITHDRAWAL) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.CUMULATIVE_NAV_WITHDRAWAL)) != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.CUMULATIVE_NAV_WITHDRAWAL)).getStringCellValue() : null;
+        if (StrUtil.isBlank(nav) || StrUtil.isBlank(cumulativeNavWithdrawal)) {
+            return null;
+        }
+        EmailFundNavDTO emailFundNavDTO = new EmailFundNavDTO();
+        String priceDate = columnFieldMap.get(EmailFieldConst.PRICE_DATE) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.PRICE_DATE)) != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.PRICE_DATE)).getStringCellValue() : null;
+        if (StrUtil.isNotBlank(priceDate) && !priceDate.contains("-")) {
+            // 处理日期yyyyMMdd格式 -> 转成yyyy-MM-dd
+            priceDate = DateUtil.format(DateUtil.parse(priceDate, DateConst.YYYYMMDD), DateConst.YYYY_MM_DD);
+        }
+        emailFundNavDTO.setPriceDate(priceDate);
+        String fundName = columnFieldMap.get(EmailFieldConst.FUND_NAME) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.FUND_NAME)).getStringCellValue() != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.FUND_NAME)).getStringCellValue() : null;
+        emailFundNavDTO.setFundName(fundName);
+        String registerNumber = columnFieldMap.get(EmailFieldConst.REGISTER_NUMBER) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.REGISTER_NUMBER)) != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.REGISTER_NUMBER)).getStringCellValue() : null;
+        emailFundNavDTO.setRegisterNumber(registerNumber);
+        emailFundNavDTO.setNav(nav);
+        emailFundNavDTO.setCumulativeNavWithdrawal(cumulativeNavWithdrawal);
+        String virtualNav = columnFieldMap.get(EmailFieldConst.VIRTUAL_NAV) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.VIRTUAL_NAV)) != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.VIRTUAL_NAV)).getStringCellValue() : null;
+        emailFundNavDTO.setVirtualNav(virtualNav);
+        String assetNet = columnFieldMap.get(EmailFieldConst.ASSET_NET) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.ASSET_NET)) != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.ASSET_NET)).getStringCellValue() : null;
+        if (StrUtil.isBlank(assetNet) || !StrUtil.isNumeric(assetNet)) {
+            assetNet = null;
+        }
+        emailFundNavDTO.setAssetNet(assetNet);
+        String assetShares = columnFieldMap.get(EmailFieldConst.ASSET_SHARE) != null && sheetRow.getCell(columnFieldMap.get(EmailFieldConst.ASSET_SHARE)) != null ?
+                sheetRow.getCell(columnFieldMap.get(EmailFieldConst.ASSET_SHARE)).getStringCellValue() : null;
+        if (StrUtil.isBlank(assetShares) || !StrUtil.isNumeric(assetShares)) {
+            assetShares = null;
+        }
+        emailFundNavDTO.setAssetShare(assetShares);
+        return emailFundNavDTO;
+    }
+
+    private Map<String, Integer> getFieldRow(Map<String, Pair<Integer, Integer>> fieldPositionMap) {
+        // 考虑日期字段识别逻辑的问题
+        long rowNumCount = fieldPositionMap.values().stream().map(Pair::getKey).distinct().count();
+        if (rowNumCount > 1) {
+            // 存在合并单元格的方式 -> 日期字段所在位置可能会存在错误
+            fieldPositionMap.remove(EmailFieldConst.PRICE_DATE);
+        }
+        Map<String, Integer> fieldRowMap = MapUtil.newHashMap();
+        for (Map.Entry<String, Pair<Integer, Integer>> fieldPositionEntry : fieldPositionMap.entrySet()) {
+            String field = fieldPositionEntry.getKey();
+            Integer column = fieldPositionEntry.getValue().getValue();
+            fieldRowMap.put(field, column);
+        }
+        return fieldRowMap;
+    }
+
+    private Map<Integer, String> getRowField(Map<String, Pair<Integer, Integer>> fieldPositionMap) {
+        Map<Integer, String> fieldRowMap = MapUtil.newHashMap();
+        for (Map.Entry<String, Pair<Integer, Integer>> fieldPositionEntry : fieldPositionMap.entrySet()) {
+            String field = fieldPositionEntry.getKey();
+            Integer column = fieldPositionEntry.getValue().getKey();
+            fieldRowMap.put(column, field);
+        }
+        return fieldRowMap;
+    }
+
+    /**
+     * 通过表头所在位置判断是行数据还是列数据
+     *
+     * @param fieldPositionMap excel中表头所在的位置
+     * @return 行方向-1,,列方向-2
+     */
+    private Integer detectDataDirection(Map<String, Pair<Integer, Integer>> fieldPositionMap) {
+        long count = fieldPositionMap.values().stream().map(Pair::getValue).distinct().count();
+        return count == 1 ? COLUMN_DIRECTION_TYPE : ROW_DIRECTION_TYPE;
+    }
+
+    /**
+     * 找出excel中表头所在的位置
+     *
+     * @param sheet         表格工作簿
+     * @param emailFieldMap 邮件字段识别规则映射表
+     * @return excel中表头所在的位置(行, 列)
+     */
     private Map<String, Pair<Integer, Integer>> getFieldPosition(Sheet sheet, Map<String, List<String>> emailFieldMap) {
         Map<String, Pair<Integer, Integer>> fieldPositionMap = MapUtil.newHashMap(8);
         int lastRowNum = sheet.getLastRowNum();
         for (int rowNum = 0; rowNum < lastRowNum; rowNum++) {
             Row sheetRow = sheet.getRow(rowNum);
+            if (sheetRow == null) {
+                continue;
+            }
             int lastCellNum = sheetRow.getLastCellNum();
             for (int cellNum = 0; cellNum < lastCellNum; cellNum++) {
-                String cellValue = sheetRow.getCell(cellNum).getStringCellValue();
+                Cell cell = sheetRow.getCell(cellNum);
+                if (cell == null) {
+                    continue;
+                }
+                String cellValue = cell.getStringCellValue();
                 String field = fieldMatch(cellValue, emailFieldMap);
-                if (StrUtil.isNotBlank(field) && !fieldPositionMap.containsKey(field)) {
+                // todo 考虑份额基金净值文件格式
+                if (StrUtil.isNotBlank(field)) {
                     fieldPositionMap.put(field, new Pair<>(rowNum, cellNum));
                 }
             }
@@ -86,6 +307,13 @@ public class NavEmailParser extends AbstractEmailParser {
         return fieldPositionMap;
     }
 
+    /**
+     * 判断单元格值是否为表头字段
+     *
+     * @param cellValue     单元格值
+     * @param emailFieldMap 邮件字段识别规则映射表
+     * @return 表头对应的标识
+     */
     public String fieldMatch(String cellValue, Map<String, List<String>> emailFieldMap) {
         if (StrUtil.isBlank(cellValue)) {
             return null;

+ 2 - 2
service-deploy/src/main/test/java/com/simuwang/datadaq/DataTrusteeApplicationTests.java

@@ -32,8 +32,8 @@ class DataTrusteeApplicationTests {
         emailInfoDTO.setProtocol("imap");
         Map<Integer, List<String>> emailTypeMap = MapUtil.newHashMap();
         emailTypeMap.put(1, List.of("净值"));
-        Date startDate = DateUtil.parse("2024-09-05 11:00:00", DateConst.YYYY_MM_DD_HH_MM_SS);
-        Date endDate = DateUtil.parse("2024-09-05 12:00:00", DateConst.YYYY_MM_DD_HH_MM_SS);
+        Date startDate = DateUtil.parse("2024-09-06 18:40:00", DateConst.YYYY_MM_DD_HH_MM_SS);
+        Date endDate = DateUtil.parse("2024-09-06 19:00:00", DateConst.YYYY_MM_DD_HH_MM_SS);
         try {
             emailParseService.parseEmail(emailInfoDTO, startDate, endDate);
         } catch (Exception e) {

+ 10 - 0
service-manage/pom.xml

@@ -14,6 +14,16 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
             <groupId>com.simuwang</groupId>
             <artifactId>service-base</artifactId>
         </dependency>

+ 162 - 0
service-manage/src/main/java/com/simuwang/manage/api/base/BaseController.java

@@ -0,0 +1,162 @@
+package com.simuwang.manage.api.base;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.simuwang.base.common.page.PageDomain;
+import com.simuwang.base.common.page.TableDataInfo;
+import com.simuwang.base.common.page.TableSupport;
+import com.simuwang.base.common.result.AjaxResult;
+import com.simuwang.base.common.util.DateUtils;
+import com.simuwang.base.common.util.PageUtils;
+import com.simuwang.base.common.util.SqlUtil;
+import com.simuwang.base.common.util.StringUtil;
+import com.smppw.common.pojo.enums.status.ResultCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * FileName: BaseController
+ * Author:   chenjianhua
+ * Date:     2024/9/8 10:02
+ * Description: ${DESCRIPTION}
+ */
+public class BaseController {
+        protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+        /**
+         * 将前台传递过来的日期格式的字符串,自动转化为Date类型
+         */
+        @InitBinder
+        public void initBinder(WebDataBinder binder)
+        {
+            // Date 类型转换
+            binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
+            {
+                @Override
+                public void setAsText(String text)
+                {
+                    setValue(DateUtils.parseDate(text));
+                }
+            });
+        }
+
+        /**
+         * 设置请求分页数据
+         */
+        protected void startPage()
+        {
+            PageUtils.startPage();
+        }
+
+        /**
+         * 设置请求排序数据
+         */
+        protected void startOrderBy()
+        {
+            PageDomain pageDomain = TableSupport.buildPageRequest();
+            if (StringUtil.isNotEmpty(pageDomain.getOrderBy()))
+            {
+                String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+                PageHelper.orderBy(orderBy);
+            }
+        }
+
+        /**
+         * 清理分页的线程变量
+         */
+        protected void clearPage()
+        {
+            PageUtils.clearPage();
+        }
+
+        /**
+         * 响应请求分页数据
+         */
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        protected TableDataInfo getDataTable(List<?> list)
+        {
+            TableDataInfo rspData = new TableDataInfo();
+            rspData.setCode(ResultCode.SUCCESS.getCode());
+            rspData.setMsg(null);
+            rspData.setRows(list);
+            rspData.setTotal(new PageInfo(list).getTotal());
+            return rspData;
+        }
+
+    /**
+     * 响应返回结果
+     *
+     * @param rows 影响行数
+     * @return 操作结果
+     */
+    protected AjaxResult toAjax(int rows)
+    {
+        return rows > 0 ? success() : error();
+    }
+
+    /**
+     * 响应返回结果
+     *
+     * @param result 结果
+     * @return 操作结果
+     */
+    protected AjaxResult toAjax(boolean result)
+    {
+        return result ? success() : error();
+    }
+
+    /**
+     * 返回成功
+     */
+    public AjaxResult success()
+    {
+        return AjaxResult.success();
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public AjaxResult error()
+    {
+        return AjaxResult.error();
+    }
+
+    /**
+     * 返回成功消息
+     */
+    public AjaxResult success(String message)
+    {
+        return AjaxResult.success(message);
+    }
+
+    /**
+     * 返回成功数据
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public AjaxResult error(String message)
+    {
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 返回错误码消息
+     */
+    public AjaxResult error(AjaxResult.Type type, String message)
+    {
+        return new AjaxResult(type, message);
+    }
+
+}

+ 49 - 0
service-manage/src/main/java/com/simuwang/manage/api/company/CompanyEmailConfigController.java

@@ -0,0 +1,49 @@
+package com.simuwang.manage.api.company;
+
+import com.simuwang.base.pojo.vo.CompanyEmailConfigVO;
+import com.simuwang.manage.service.CompanyEmailConfigService;
+import com.smppw.common.pojo.ResultVo;
+import com.smppw.common.pojo.enums.status.ResultCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * FileName: CompanyInformationController
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:25
+ * Description: ${DESCRIPTION}
+ */
+@RestController
+@RequestMapping("/company")
+public class CompanyEmailConfigController {
+    private static final Logger logger = LoggerFactory.getLogger(CompanyEmailConfigController.class);
+    @Autowired
+    private CompanyEmailConfigService companyEmailConfigService;
+    @PostMapping("save-email-config")
+    public ResultVo saveCompanyEmailConfig(@RequestBody List<CompanyEmailConfigVO> companyEmailConfigVOS){
+        ResultVo vo = new ResultVo(ResultCode.SAVE_SUCCESS);
+        try{
+            companyEmailConfigService.saveCompanyEmailConfig(companyEmailConfigVOS);
+        }catch (Exception e){
+            vo = new ResultVo(ResultCode.SAVE_SUCCESS);
+            logger.error(e.getMessage(),e);
+        }
+        return vo;
+    }
+
+    @PostMapping("delete-email-config")
+    public ResultVo deleteCompanyEmailConfig(@RequestParam("id")Integer id){
+        ResultVo vo = new ResultVo(ResultCode.DELETE_SUCCESS);
+        try{
+            companyEmailConfigService.deleteCompanyEmailConfig(id);
+        }catch (Exception e){
+            vo = new ResultVo(ResultCode.DELETE_FAILED);
+            logger.error(e.getMessage(),e);
+        }
+        return vo;
+    }
+}

+ 22 - 0
service-manage/src/main/java/com/simuwang/manage/api/company/CompanyEmailSendHistoryController.java

@@ -0,0 +1,22 @@
+package com.simuwang.manage.api.company;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * FileName: CompanyInformationController
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:25
+ * Description: ${DESCRIPTION}
+ */
+@RestController
+@RequestMapping("/company")
+public class CompanyEmailSendHistoryController {
+    private static final Logger logger = LoggerFactory.getLogger(CompanyEmailSendHistoryController.class);
+
+
+}

+ 29 - 0
service-manage/src/main/java/com/simuwang/manage/api/company/CompanyInformationController.java

@@ -0,0 +1,29 @@
+package com.simuwang.manage.api.company;
+
+import com.simuwang.manage.service.CompanyInformationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: CompanyInformationController
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:25
+ * Description: ${DESCRIPTION}
+ */
+@RestController
+@RequestMapping("/company")
+public class CompanyInformationController {
+    @Autowired
+    private CompanyInformationService companyInformationService;
+    @RequestMapping("search-info")
+    public List<Map<String,String>> searchCompanyInfo(@RequestParam(value = "keyword",required = false)String keyword){
+        List<Map<String,String>> result = companyInformationService.searchCompanyInfo(keyword);
+        return result;
+    }
+
+}

+ 80 - 0
service-manage/src/main/java/com/simuwang/manage/api/fund/FundInformationController.java

@@ -0,0 +1,80 @@
+package com.simuwang.manage.api.fund;
+
+import com.simuwang.base.common.page.TableDataInfo;
+import com.simuwang.base.pojo.vo.FundInformationVO;
+import com.simuwang.base.pojo.vo.FundReportFrequencyVO;
+import com.simuwang.manage.api.base.BaseController;
+import com.simuwang.manage.service.FundInformationService;
+import com.simuwang.manage.service.FundReportFrequencyService;
+import com.smppw.common.pojo.ResultVo;
+import com.smppw.common.pojo.enums.status.ResultCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: FundInformationController
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:01
+ * Description: ${DESCRIPTION}
+ */
+@RestController
+@RequestMapping("/fund")
+public class FundInformationController extends BaseController {
+
+    private static final Logger logger = LoggerFactory.getLogger(FundInformationController.class);
+
+
+    @Autowired
+    private FundInformationService fundInformationService;
+
+    @Autowired
+    private FundReportFrequencyService fundReportFrequencyService;
+    /**
+     * 搜索输入框查询
+     * @param keyword
+     * @return
+     */
+    @RequestMapping("search-info")
+    public TableDataInfo searchFundInfo(@RequestParam(value = "keyword",required = false)String keyword){
+        List<Map<String,String>> result = fundInformationService.searchFundInfo(keyword);
+        return getDataTable(result);
+    }
+
+    /**
+     * @param fundShortName
+     * @param companyShortName
+     * @param navFrequency
+     * @param assetFrequency
+     * @return
+     */
+    @RequestMapping("search-list")
+    public List<FundInformationVO> searchFundInfoList(
+              @RequestParam(value = "fundId",required = false)String fundId,
+              @RequestParam(value = "fundShortName",required = false)String fundShortName,
+              @RequestParam(value = "companyShortName",required = false)String companyShortName,
+              @RequestParam(value = "navFrequency",required = false)Integer navFrequency,
+              @RequestParam(value = "assetFrequency",required = false)Integer assetFrequency,
+              @RequestParam(value = "startDate",required = false)Integer startDate,
+              @RequestParam(value = "endDate",required = false)Integer endDate){
+        List<FundInformationVO> result = fundInformationService.searchFundInfoList(fundId,fundShortName,companyShortName,navFrequency,assetFrequency,startDate,endDate);
+        return result;
+    }
+
+    @PostMapping("/save-frequency")
+    public ResultVo saveFundReportFrequency(@RequestBody FundReportFrequencyVO fundReportFrequency){
+        ResultVo vo = new ResultVo(ResultCode.SAVE_SUCCESS);
+        try{
+            fundReportFrequencyService.saveFundReportFrequency(fundReportFrequency);
+        }catch (Exception e){
+            vo = new ResultVo(ResultCode.SAVE_FAILED);
+            logger.error(e.getMessage(),e);
+        }
+        return vo;
+    }
+
+}

+ 125 - 0
service-manage/src/main/java/com/simuwang/manage/api/system/SysConfigController.java

@@ -0,0 +1,125 @@
+package com.simuwang.manage.api.system;
+
+import com.simuwang.base.common.page.TableDataInfo;
+import com.simuwang.base.common.result.AjaxResult;
+import com.simuwang.base.pojo.vo.SysConfigVO;
+import com.simuwang.manage.api.base.BaseController;
+import com.simuwang.manage.service.system.SysConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 参数配置 信息操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/config")
+public class SysConfigController extends BaseController
+{
+    private String prefix = "system/config";
+
+    @Autowired
+    private SysConfigService configService;
+
+    @GetMapping()
+    public String config()
+    {
+        return prefix + "/config";
+    }
+
+    /**
+     * 查询参数配置列表
+     */
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysConfigVO config)
+    {
+        startPage();
+        List<SysConfigVO> list = configService.selectConfigList(config);
+        return getDataTable(list);
+    }
+    /**
+     * 新增参数配置
+     */
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存参数配置
+     */
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysConfigVO config)
+    {
+        if (!configService.checkConfigKeyUnique(config))
+        {
+            return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
+        }
+        return toAjax(configService.insertConfig(config));
+    }
+
+    /**
+     * 修改参数配置
+     */
+    @GetMapping("/edit/{configId}")
+    public String edit(@PathVariable("configId") Long configId, ModelMap mmap)
+    {
+        mmap.put("config", configService.selectConfigById(configId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存参数配置
+     */
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysConfigVO config)
+    {
+        if (!configService.checkConfigKeyUnique(config))
+        {
+            return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
+        }
+        return toAjax(configService.updateConfig(config));
+    }
+
+    /**
+     * 删除参数配置
+     */
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        configService.deleteConfigByIds(ids);
+        return success();
+    }
+
+    /**
+     * 刷新参数缓存
+     */
+    @GetMapping("/refreshCache")
+    @ResponseBody
+    public AjaxResult refreshCache()
+    {
+        configService.resetConfigCache();
+        return success();
+    }
+
+    /**
+     * 校验参数键名
+     */
+    @PostMapping("/checkConfigKeyUnique")
+    @ResponseBody
+    public boolean checkConfigKeyUnique(SysConfigVO config)
+    {
+        return configService.checkConfigKeyUnique(config);
+    }
+}

+ 17 - 0
service-manage/src/main/java/com/simuwang/manage/service/CompanyEmailConfigService.java

@@ -0,0 +1,17 @@
+package com.simuwang.manage.service;
+
+import com.simuwang.base.pojo.vo.CompanyEmailConfigVO;
+
+import java.util.List;
+
+/**
+ * FileName: CompanyEmailConfigService
+ * Author:   chenjianhua
+ * Date:     2024/9/7 12:55
+ * Description: ${DESCRIPTION}
+ */
+public interface CompanyEmailConfigService {
+    void saveCompanyEmailConfig(List<CompanyEmailConfigVO> companyEmailConfigVOS);
+
+    void deleteCompanyEmailConfig(Integer id);
+}

+ 14 - 0
service-manage/src/main/java/com/simuwang/manage/service/CompanyInformationService.java

@@ -0,0 +1,14 @@
+package com.simuwang.manage.service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: CompanyInformationService
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:28
+ * Description: ${DESCRIPTION}
+ */
+public interface CompanyInformationService {
+    List<Map<String, String>> searchCompanyInfo(String keyword);
+}

+ 18 - 0
service-manage/src/main/java/com/simuwang/manage/service/FundInformationService.java

@@ -0,0 +1,18 @@
+package com.simuwang.manage.service;
+
+import com.simuwang.base.pojo.vo.FundInformationVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: FundInformationService
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:08
+ * Description: ${DESCRIPTION}
+ */
+public interface FundInformationService {
+    List<Map<String, String>> searchFundInfo(String keyword);
+
+    List<FundInformationVO> searchFundInfoList(String funId, String funName, String companyName, Integer navFrequency, Integer assetFrequency, Integer startDate, Integer endDate);
+}

+ 13 - 0
service-manage/src/main/java/com/simuwang/manage/service/FundReportFrequencyService.java

@@ -0,0 +1,13 @@
+package com.simuwang.manage.service;
+
+import com.simuwang.base.pojo.vo.FundReportFrequencyVO;
+
+/**
+ * FileName: FundReportFrequencyService
+ * Author:   chenjianhua
+ * Date:     2024/9/6 17:14
+ * Description: ${DESCRIPTION}
+ */
+public interface FundReportFrequencyService {
+    void saveFundReportFrequency(FundReportFrequencyVO fundReportFrequency);
+}

+ 53 - 0
service-manage/src/main/java/com/simuwang/manage/service/impl/CompanyEmailConfigServiceImpl.java

@@ -0,0 +1,53 @@
+package com.simuwang.manage.service.impl;
+
+import com.simuwang.base.mapper.CompanyEmailConfigMapper;
+import com.simuwang.base.pojo.dos.CompanyEmailConfigDO;
+import com.simuwang.base.pojo.vo.CompanyEmailConfigVO;
+import com.simuwang.manage.service.CompanyEmailConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * FileName: CompanyEmailConfigServiceImpl
+ * Author:   chenjianhua
+ * Date:     2024/9/7 12:55
+ * Description: ${DESCRIPTION}
+ */
+@Service
+public class CompanyEmailConfigServiceImpl implements CompanyEmailConfigService {
+    @Autowired
+    private CompanyEmailConfigMapper companyEmailConfigMapper;
+    @Override
+    public void saveCompanyEmailConfig(List<CompanyEmailConfigVO> companyEmailConfigVOS) {
+        for(CompanyEmailConfigVO emailConfigVO : companyEmailConfigVOS){
+            CompanyEmailConfigDO emailConfigDO = new CompanyEmailConfigDO();
+            emailConfigDO.setCompanyId(emailConfigVO.getCompanyId());
+            emailConfigDO.setCompanyName(emailConfigVO.getCompanyName());
+            emailConfigDO.setEmail(emailConfigVO.getEmail());
+            emailConfigDO.setOpenStatus(emailConfigVO.getOpenStatus());
+            emailConfigDO.setIsvalid(1);
+            emailConfigDO.setUpdateTime(new Date());
+            if(emailConfigVO.getId() != null){
+                emailConfigDO.setId(emailConfigVO.getId());
+                companyEmailConfigMapper.updateById(emailConfigDO);
+            }else{
+                emailConfigDO.setCreateTime(new Date());
+                companyEmailConfigMapper.insert(emailConfigDO);
+            }
+        }
+    }
+
+    @Override
+    public void deleteCompanyEmailConfig(Integer id) {
+        CompanyEmailConfigDO configDO = companyEmailConfigMapper.selectById(id);
+        if(configDO != null){
+            configDO.setIsvalid(0);
+            configDO.setUpdateTime(new Date());
+            companyEmailConfigMapper.updateById(configDO);
+        }
+    }
+}

+ 27 - 0
service-manage/src/main/java/com/simuwang/manage/service/impl/CompanyInformationServiceImpl.java

@@ -0,0 +1,27 @@
+package com.simuwang.manage.service.impl;
+
+import com.simuwang.base.mapper.CompanyInformationMapper;
+import com.simuwang.manage.service.CompanyInformationService;
+import org.checkerframework.checker.units.qual.A;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: CompanyInformationServiceImpl
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:28
+ * Description: ${DESCRIPTION}
+ */
+@Service
+public class CompanyInformationServiceImpl implements CompanyInformationService {
+    @Autowired
+    private CompanyInformationMapper companyInformationMapper;
+    @Override
+    public List<Map<String, String>> searchCompanyInfo(String keyword) {
+        List<Map<String, String>> result = companyInformationMapper.searchCompanyInfoByKeyword(keyword);
+        return result;
+    }
+}

+ 32 - 0
service-manage/src/main/java/com/simuwang/manage/service/impl/FundInformationServiceImpl.java

@@ -0,0 +1,32 @@
+package com.simuwang.manage.service.impl;
+
+import com.simuwang.base.mapper.FundInfomationMapper;
+import com.simuwang.base.pojo.vo.FundInformationVO;
+import com.simuwang.manage.service.FundInformationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * FileName: FundInformationServiceImpl
+ * Author:   chenjianhua
+ * Date:     2024/9/6 15:08
+ * Description: ${DESCRIPTION}
+ */
+@Service
+public class FundInformationServiceImpl implements FundInformationService {
+    @Autowired
+    private FundInfomationMapper fundInfomationMapper;
+    @Override
+    public List<Map<String, String>> searchFundInfo(String keyword) {
+        return fundInfomationMapper.searchFundInfoByKeyword(keyword);
+    }
+
+    @Override
+    public List<FundInformationVO> searchFundInfoList(String fundId, String fundName, String companyName, Integer navFrequency, Integer assetFrequency, Integer startDate, Integer endDate) {
+        List<FundInformationVO> result = fundInfomationMapper.searchFundInfoList(fundId,fundName,companyName,navFrequency,assetFrequency,startDate,endDate);
+        return result;
+    }
+}

+ 42 - 0
service-manage/src/main/java/com/simuwang/manage/service/impl/FundReportFrequencyServiceImpl.java

@@ -0,0 +1,42 @@
+package com.simuwang.manage.service.impl;
+
+import com.simuwang.base.mapper.FundReportFrequencyMapper;
+import com.simuwang.base.pojo.dos.FundReportFrequencyDO;
+import com.simuwang.base.pojo.vo.FundReportFrequencyVO;
+import com.simuwang.manage.service.FundReportFrequencyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/**
+ * FileName: FundReportFrequencyService
+ * Author:   chenjianhua
+ * Date:     2024/9/6 17:14
+ * Description: ${DESCRIPTION}
+ */
+@Service
+public class FundReportFrequencyServiceImpl implements FundReportFrequencyService {
+    @Autowired
+    private FundReportFrequencyMapper fundReportFrequencyMapper;
+    @Override
+    public void saveFundReportFrequency(FundReportFrequencyVO fundReportFrequency) {
+        String fundIds = fundReportFrequency.getFundId();
+        String[] fundIdList = fundIds.split(",");
+        for(String fundId : fundIdList){
+            FundReportFrequencyDO fundReportFrequencyDO = new FundReportFrequencyDO();
+            fundReportFrequencyDO.setFundId(fundId);
+            fundReportFrequencyDO.setAssetFrequency(fundReportFrequency.getAssetFrequency());
+            fundReportFrequencyDO.setNavFrequency(fundReportFrequency.getNavFrequency());
+            fundReportFrequencyDO.setUpdateTime(new Date());
+            FundReportFrequencyDO oldFrequency = fundReportFrequencyMapper.getFrequencyByFundId(fundId);
+            if(oldFrequency == null){
+                fundReportFrequencyDO.setCreateTime(new Date());
+                fundReportFrequencyDO.setIsvalid(1);
+                fundReportFrequencyMapper.insert(fundReportFrequencyDO);
+            }else{
+                fundReportFrequencyMapper.updateById(fundReportFrequencyDO);
+            }
+        }
+    }
+}

+ 51 - 0
service-manage/src/main/java/com/simuwang/manage/service/impl/system/SysConfigServiceImpl.java

@@ -0,0 +1,51 @@
+package com.simuwang.manage.service.impl.system;
+
+import com.simuwang.base.pojo.vo.SysConfigVO;
+import com.simuwang.manage.service.system.SysConfigService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * FileName: SysConfigServiceImpl
+ * Author:   chenjianhua
+ * Date:     2024/9/8 11:01
+ * Description: ${DESCRIPTION}
+ */
+@Service
+public class SysConfigServiceImpl implements SysConfigService {
+    @Override
+    public List<SysConfigVO> selectConfigList(SysConfigVO config) {
+        return null;
+    }
+
+    @Override
+    public int insertConfig(SysConfigVO config) {
+        return 0;
+    }
+
+    @Override
+    public SysConfigVO selectConfigById(Long configId) {
+        return null;
+    }
+
+    @Override
+    public boolean checkConfigKeyUnique(SysConfigVO config) {
+        return false;
+    }
+
+    @Override
+    public void resetConfigCache() {
+
+    }
+
+    @Override
+    public void deleteConfigByIds(String ids) {
+
+    }
+
+    @Override
+    public int updateConfig(SysConfigVO config) {
+        return 0;
+    }
+}

+ 27 - 0
service-manage/src/main/java/com/simuwang/manage/service/system/SysConfigService.java

@@ -0,0 +1,27 @@
+package com.simuwang.manage.service.system;
+
+import com.simuwang.base.pojo.vo.SysConfigVO;
+
+import java.util.List;
+
+/**
+ * FileName: SysConfigService
+ * Author:   chenjianhua
+ * Date:     2024/9/8 11:01
+ * Description: ${DESCRIPTION}
+ */
+public interface SysConfigService {
+    List<SysConfigVO> selectConfigList(SysConfigVO config);
+
+    int insertConfig(SysConfigVO config);
+
+    SysConfigVO selectConfigById(Long configId);
+
+    boolean checkConfigKeyUnique(SysConfigVO config);
+
+    void resetConfigCache();
+
+    void deleteConfigByIds(String ids);
+
+    int updateConfig(SysConfigVO config);
+}