Explorar o código

!99 merge
Merge pull request !99 from AE86/V_1.0.0_RC

AE86 %!s(int64=2) %!d(string=hai) anos
pai
achega
d9ba2a2037
Modificáronse 46 ficheiros con 1210 adicións e 503 borrados
  1. 0 14
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/ConfigService.java
  2. 75 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/UserService.java
  3. 1 25
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/config/ConfigChecker.java
  4. 38 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/user/UserConfigChecker.java
  5. 65 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/enums/UserRoleEnum.java
  6. 14 31
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/ConfigServiceImpl.java
  7. 2 1
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MappingServiceImpl.java
  8. 200 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/UserServiceImpl.java
  9. 0 10
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/vo/ConfigVo.java
  10. 24 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/vo/UserInfoVo.java
  11. 27 11
      dbsyncer-connector/src/main/test/ConnectionTest.java
  12. 9 0
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/Manager.java
  13. 25 1
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/ManagerFactory.java
  14. 4 0
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/command/PreloadCommand.java
  15. 6 1
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/enums/CommandEnum.java
  16. 1 7
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/puller/FullPuller.java
  17. 3 1
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/template/PreloadTemplate.java
  18. 0 20
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/Config.java
  19. 1 1
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/ConfigModel.java
  20. 0 10
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/Task.java
  21. 64 0
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/UserConfig.java
  22. 99 0
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/UserInfo.java
  23. 1 0
      dbsyncer-storage/src/main/java/org/dbsyncer/storage/constant/ConfigConstant.java
  24. 2 2
      dbsyncer-storage/src/main/java/org/dbsyncer/storage/support/MysqlStorageServiceImpl.java
  25. 11 0
      dbsyncer-storage/src/main/java/org/dbsyncer/storage/util/BinlogMessageUtil.java
  26. 3 0
      dbsyncer-storage/src/main/test/ShardBinlogTest.java
  27. 4 7
      dbsyncer-web/src/main/java/org/dbsyncer/web/config/WebAppConfig.java
  28. 2 3
      dbsyncer-web/src/main/java/org/dbsyncer/web/controller/index/ProjectGroupController.java
  29. 0 51
      dbsyncer-web/src/main/java/org/dbsyncer/web/controller/pwd/PwdController.java
  30. 1 1
      dbsyncer-web/src/main/java/org/dbsyncer/web/controller/system/SystemController.java
  31. 125 0
      dbsyncer-web/src/main/java/org/dbsyncer/web/controller/user/UserController.java
  32. 0 2
      dbsyncer-web/src/main/resources/application.properties
  33. 0 1
      dbsyncer-web/src/main/resources/public/index.html
  34. 4 4
      dbsyncer-web/src/main/resources/public/login.html
  35. 10 6
      dbsyncer-web/src/main/resources/public/nav.html
  36. 0 49
      dbsyncer-web/src/main/resources/public/pwd/pwd.html
  37. 0 6
      dbsyncer-web/src/main/resources/public/system/system.html
  38. 105 0
      dbsyncer-web/src/main/resources/public/user/add.html
  39. 135 0
      dbsyncer-web/src/main/resources/public/user/edit.html
  40. 61 0
      dbsyncer-web/src/main/resources/public/user/user.html
  41. 21 204
      dbsyncer-web/src/main/resources/static/css/login/login.css
  42. 11 0
      dbsyncer-web/src/main/resources/static/js/common.js
  43. 7 0
      dbsyncer-web/src/main/resources/static/js/index.js
  44. 6 10
      dbsyncer-web/src/main/resources/static/js/login/login.js
  45. 0 24
      dbsyncer-web/src/main/resources/static/js/pwd/index.js
  46. 43 0
      dbsyncer-web/src/main/resources/static/js/user/index.js

+ 0 - 14
dbsyncer-biz/src/main/java/org/dbsyncer/biz/ConfigService.java

@@ -28,20 +28,6 @@ public interface ConfigService {
      */
     ConfigVo getConfig();
 
-    /**
-     * 获取密码
-     *
-     * @return
-     */
-    String getPassword();
-
-    /**
-     * 获取所有配置
-     *
-     * @return
-     */
-    List<ConfigVo> queryConfig();
-
     /**
      * 获取所有配置
      *

+ 75 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/UserService.java

@@ -0,0 +1,75 @@
+package org.dbsyncer.biz;
+
+import org.dbsyncer.biz.vo.UserInfoVo;
+import org.dbsyncer.parser.model.UserConfig;
+import org.dbsyncer.parser.model.UserInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/17 0:16
+ */
+public interface UserService {
+
+    /**
+     * 获取登录用户属性KEY
+     */
+    String CURRENT_USER_NAME = "currentUserName";
+
+    /**
+     * 新增用戶(仅管理员可以新增用户)
+     *
+     * @param params
+     */
+    String add(Map<String, String> params);
+
+    /**
+     * 修改用戶(管理员可以修改所有用户,普通用户只能修改自己)
+     *
+     * @param params
+     */
+    String edit(Map<String, String> params);
+
+    /**
+     * 删除用戶(仅管理员可以删除普通用户)
+     *
+     * @param params
+     */
+    String remove(Map<String, String> params);
+
+    /**
+     * 获取登录用户密码
+     *
+     * @param currentUserName 登录用户
+     * @return
+     */
+    UserInfo getUserInfo(String currentUserName);
+
+    /**
+     * 获取登录用户信息VO(管理员可以查看所有用户,普通用户只能查看自己)
+     *
+     * @param currentUserName 登录用户
+     * @param username        查询的用户
+     * @return
+     */
+    UserInfoVo getUserInfoVo(String currentUserName, String username);
+
+    /**
+     * 获取所有用户信息VO(系统管理员可以查看所有用户,其他用户只能查看自己)
+     *
+     * @param currentUserName 登录用户
+     * @return
+     */
+    List<UserInfoVo> getUserInfoAll(String currentUserName);
+
+    /**
+     * 获取用户配置
+     *
+     * @return
+     */
+    UserConfig getUserConfig();
+
+}

+ 1 - 25
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/config/ConfigChecker.java

@@ -1,9 +1,7 @@
 package org.dbsyncer.biz.checker.impl.config;
 
-import org.dbsyncer.biz.BizException;
 import org.dbsyncer.biz.checker.AbstractChecker;
 import org.dbsyncer.common.util.NumberUtil;
-import org.dbsyncer.common.util.SHA1Util;
 import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.parser.logger.LogService;
@@ -14,7 +12,6 @@ import org.dbsyncer.storage.constant.ConfigConstant;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.util.Assert;
 
@@ -30,9 +27,6 @@ public class ConfigChecker extends AbstractChecker {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    @Value(value = "${dbsyncer.web.login.password}")
-    private String password;
-
     @Autowired
     private Manager manager;
 
@@ -44,7 +38,6 @@ public class ConfigChecker extends AbstractChecker {
         Config config = new Config();
         config.setName("系统配置");
         config.setType(ConfigConstant.CONFIG);
-        config.setPassword(password);
 
         // 修改基本配置
         this.modifyConfigModel(config, params);
@@ -63,30 +56,13 @@ public class ConfigChecker extends AbstractChecker {
         Config config = manager.getConfig(id);
         Assert.notNull(config, "配置文件为空.");
 
-        // 修改密码
-        String newPwd = params.get("newPwd");
-        String oldPwd = params.get("oldPwd");
-        if (StringUtil.isNotBlank(newPwd) && StringUtil.isNotBlank(oldPwd)) {
-            oldPwd = SHA1Util.b64_sha1(oldPwd);
-            if (!StringUtil.equals(config.getPassword(), oldPwd)) {
-                logService.log(LogType.SystemLog.ERROR, "修改密码失败");
-                throw new BizException("修改密码失败");
-            }
-            config.setPassword(SHA1Util.b64_sha1(newPwd));
-            logService.log(LogType.SystemLog.INFO, "修改密码成功");
-        }
-        logService.log(LogType.SystemLog.INFO, "修改系统配置");
-
         // 刷新监控间隔(秒)
         String refreshInterval = params.get("refreshInterval");
         if (StringUtil.isNotBlank(refreshInterval)) {
             int time = NumberUtil.toInt(refreshInterval, 10);
             config.setRefreshInterval(time);
         }
-
-        // 刷新邮箱配置(有配置则发邮件)
-        String email = params.get("email");
-        config.setEmail(email);
+        logService.log(LogType.SystemLog.INFO, "修改系统配置");
 
         // 修改基本配置
         this.modifyConfigModel(config, params);

+ 38 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/user/UserConfigChecker.java

@@ -0,0 +1,38 @@
+package org.dbsyncer.biz.checker.impl.user;
+
+import org.dbsyncer.biz.BizException;
+import org.dbsyncer.biz.checker.AbstractChecker;
+import org.dbsyncer.parser.model.ConfigModel;
+import org.dbsyncer.parser.model.UserConfig;
+import org.dbsyncer.storage.constant.ConfigConstant;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2020/1/8 15:17
+ */
+@Component
+public class UserConfigChecker extends AbstractChecker {
+
+    @Override
+    public ConfigModel checkAddConfigModel(Map<String, String> params) {
+        UserConfig config = new UserConfig();
+        config.setName("用户配置");
+        config.setType(ConfigConstant.USER_CONFIG);
+        config.setUserInfoList(new ArrayList<>());
+
+        // 修改基本配置
+        this.modifyConfigModel(config, params);
+        return config;
+    }
+
+    @Override
+    public ConfigModel checkEditConfigModel(Map<String, String> params) {
+        throw new BizException("Unsupported method");
+    }
+
+}

+ 65 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/enums/UserRoleEnum.java

@@ -0,0 +1,65 @@
+package org.dbsyncer.biz.enums;
+
+import org.dbsyncer.common.util.StringUtil;
+
+/**
+ * 用户角色枚举
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/18 23:21
+ */
+public enum UserRoleEnum {
+
+    /**
+     * 管理员
+     */
+    ADMIN("admin", "管理员"),
+
+    /**
+     * 普通用户
+     */
+    USER("user", "普通用户");
+
+    private String code;
+
+    private String name;
+
+    UserRoleEnum(String code, String name) {
+        this.code = code;
+        this.name = name;
+    }
+
+    /**
+     * 是否是管理员
+     *
+     * @param roleCode
+     * @return
+     */
+    public static boolean isAdmin(String roleCode) {
+        return ADMIN.getCode().equals(roleCode);
+    }
+
+    /**
+     * 获取角色名称
+     *
+     * @param roleCode
+     * @return
+     */
+    public static String getNameByCode(String roleCode) {
+        for (UserRoleEnum u : UserRoleEnum.values()) {
+            if (StringUtil.equals(roleCode, u.getCode())) {
+                return u.getName();
+            }
+        }
+        return "";
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

+ 14 - 31
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/ConfigServiceImpl.java

@@ -2,6 +2,7 @@ package org.dbsyncer.biz.impl;
 
 import org.apache.commons.io.FileUtils;
 import org.dbsyncer.biz.ConfigService;
+import org.dbsyncer.biz.UserService;
 import org.dbsyncer.biz.checker.Checker;
 import org.dbsyncer.biz.vo.ConfigVo;
 import org.dbsyncer.common.util.CollectionUtils;
@@ -12,7 +13,6 @@ import org.dbsyncer.parser.logger.LogType;
 import org.dbsyncer.parser.model.Config;
 import org.dbsyncer.parser.model.ConfigModel;
 import org.dbsyncer.plugin.enums.FileSuffixEnum;
-import org.dbsyncer.storage.constant.ConfigConstant;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 /**
  * @author AE86
@@ -47,45 +46,26 @@ public class ConfigServiceImpl implements ConfigService {
     @Autowired
     private LogService logService;
 
+    @Autowired
+    private UserService userService;
+
     @Override
     public String edit(Map<String, String> params) {
-        synchronized (this) {
-            Config config = manager.getConfig(ConfigConstant.CONFIG);
-            if (null == config) {
-                configChecker.checkAddConfigModel(params);
-            }
-            ConfigModel model = configChecker.checkEditConfigModel(params);
-            manager.editConfig(model);
-        }
+        ConfigModel model = configChecker.checkEditConfigModel(params);
+        manager.editConfig(model);
         return "修改成功.";
     }
 
     @Override
     public ConfigVo getConfig() {
-        List<Config> all = manager.getConfigAll();
-        Config config = CollectionUtils.isEmpty(all) ? (Config) configChecker.checkAddConfigModel(new HashMap<>()) : all.get(0);
-        return convertConfig2Vo(config);
-    }
-
-    @Override
-    public String getPassword() {
-        List<Config> all = manager.getConfigAll();
-        Config config = CollectionUtils.isEmpty(all) ? (Config) configChecker.checkAddConfigModel(new HashMap<>()) : all.get(0);
-        return config.getPassword();
-    }
-
-    @Override
-    public List<ConfigVo> queryConfig() {
-        List<ConfigVo> list = manager.getConfigAll().stream()
-                .map(config -> convertConfig2Vo(config))
-                .collect(Collectors.toList());
-        return list;
+        return convertConfig2Vo(getConfigModel());
     }
 
     @Override
     public List<ConfigModel> getConfigModelAll() {
         List<ConfigModel> list = new ArrayList<>();
-        manager.getConfigAll().forEach(config -> list.add(config));
+        list.add(getConfigModel());
+        list.add(userService.getUserConfig());
         manager.getConnectorAll().forEach(config -> list.add(config));
         manager.getMappingAll().forEach(config -> list.add(config));
         manager.getMetaAll().forEach(config -> list.add(config));
@@ -118,11 +98,14 @@ public class ConfigServiceImpl implements ConfigService {
         }
     }
 
+    private synchronized Config getConfigModel() {
+        List<Config> all = manager.getConfigAll();
+        return CollectionUtils.isEmpty(all) ? (Config) configChecker.checkAddConfigModel(new HashMap<>()) : all.get(0);
+    }
+
     private ConfigVo convertConfig2Vo(Config config) {
         ConfigVo configVo = new ConfigVo();
         BeanUtils.copyProperties(config, configVo);
-        // 避免密码直接暴露
-        configVo.setPassword("");
         return configVo;
     }
 

+ 2 - 1
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MappingServiceImpl.java

@@ -214,7 +214,8 @@ public class MappingServiceImpl extends BaseServiceImpl implements MappingServic
     private void clearMetaIfFinished(String metaId) {
         Meta meta = manager.getMeta(metaId);
         Assert.notNull(meta, "Mapping meta can not be null.");
-        if (meta.getTotal().get() >= (meta.getSuccess().get() + meta.getFail().get())) {
+        // 完成任务则重置状态
+        if (meta.getTotal().get() <= (meta.getSuccess().get() + meta.getFail().get())) {
             meta.getFail().set(0);
             meta.getSuccess().set(0);
             manager.editMeta(meta);

+ 200 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/UserServiceImpl.java

@@ -0,0 +1,200 @@
+package org.dbsyncer.biz.impl;
+
+import org.dbsyncer.biz.BizException;
+import org.dbsyncer.biz.UserService;
+import org.dbsyncer.biz.checker.impl.user.UserConfigChecker;
+import org.dbsyncer.biz.enums.UserRoleEnum;
+import org.dbsyncer.biz.vo.UserInfoVo;
+import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.SHA1Util;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.manager.Manager;
+import org.dbsyncer.parser.logger.LogService;
+import org.dbsyncer.parser.logger.LogType;
+import org.dbsyncer.parser.model.UserConfig;
+import org.dbsyncer.parser.model.UserInfo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/17 0:16
+ */
+@Service
+public class UserServiceImpl implements UserService {
+
+    private static final String DEFAULT_USERNAME = "admin";
+
+    private static final String DEFAULT_PASSWORD = "0DPiKuNIrrVmD8IUCuw1hQxNqZc=";
+
+    @Autowired
+    private Manager manager;
+
+    @Autowired
+    private UserConfigChecker userConfigChecker;
+
+    @Autowired
+    private LogService logService;
+
+    @Override
+    public synchronized String add(Map<String, String> params) {
+        String username = params.get("username");
+        Assert.hasText(username, "The username is null.");
+        String nickname = params.get("nickname");
+        Assert.hasText(nickname, "The nickname is null.");
+        String password = params.get("password");
+        Assert.hasText(password, "The password is null.");
+        String mail = params.get("mail");
+
+        // 验证当前登录用户合法身份(必须是管理员操作)
+        UserConfig userConfig = getUserConfig();
+        UserInfo currentUser = userConfig.getUserInfo(params.get(UserService.CURRENT_USER_NAME));
+        Assert.isTrue(null == currentUser || UserRoleEnum.isAdmin(currentUser.getRoleCode()), "No permission.");
+        // 新用户合法性(用户不能重复)
+        Assert.isNull(userConfig.getUserInfo(username), "用户已存在,请换个账号");
+        // 注册新用户
+        userConfig.getUserInfoList().add(new UserInfo(username, nickname, SHA1Util.b64_sha1(password), UserRoleEnum.USER.getCode(), mail));
+
+        return manager.editUserConfig(userConfig);
+    }
+
+    @Override
+    public synchronized String edit(Map<String, String> params) {
+        String username = params.get("username");
+        Assert.hasText(username, "The username is null.");
+        String nickname = params.get("nickname");
+        Assert.hasText(nickname, "The nickname is null.");
+        String newPwd = params.get("newPwd");
+        String mail = params.get("mail");
+
+        // 验证当前登录用户合法身份(管理员或本人操作)
+        UserConfig userConfig = getUserConfig();
+        UserInfo currentUser = userConfig.getUserInfo(params.get(UserService.CURRENT_USER_NAME));
+        boolean admin = null != currentUser && UserRoleEnum.isAdmin(currentUser.getRoleCode());
+        boolean self = null != currentUser && StringUtil.equals(currentUser.getUsername(), username);
+        Assert.isTrue(admin || self, "No permission.");
+
+        // 修改自己或其他用户信息
+        UserInfo updateUser = self ? currentUser : userConfig.getUserInfo(username);
+        Assert.notNull(updateUser, "用户不存在");
+
+        // 用户昵称
+        updateUser.setNickname(nickname);
+        updateUser.setMail(mail);
+        // 修改密码
+        if (StringUtil.isNotBlank(newPwd)) {
+            // 修改自己的密码需要验证
+            if (self) {
+                String oldPwd = params.get("oldPwd");
+                Assert.hasText(oldPwd, "旧密码不能为空.");
+                if (!StringUtil.equals(SHA1Util.b64_sha1(oldPwd), updateUser.getPassword())) {
+                    logService.log(LogType.SystemLog.ERROR, String.format("[%s]修改密码失败", username));
+                    throw new BizException("修改密码失败.");
+                }
+            }
+            newPwd = SHA1Util.b64_sha1(newPwd);
+            Assert.isTrue(!StringUtil.equals(newPwd, updateUser.getPassword()), "新旧密码不能完全一样.");
+            updateUser.setPassword(newPwd);
+            logService.log(LogType.SystemLog.INFO, String.format("[%s]修改[%s]账号密码成功", currentUser.getUsername(), username));
+        }
+
+        return manager.editUserConfig(userConfig);
+    }
+
+    @Override
+    public synchronized String remove(Map<String, String> params) {
+        String username = params.get("username");
+        Assert.hasText(username, "The username is null.");
+
+        // 验证当前登录用户合法身份(必须是管理员操作)
+        UserConfig userConfig = getUserConfig();
+        UserInfo currentUser = userConfig.getUserInfo(params.get(UserService.CURRENT_USER_NAME));
+        Assert.isTrue(UserRoleEnum.isAdmin(currentUser.getRoleCode()), "No permission.");
+
+        // 不能删除自己
+        Assert.isTrue(!StringUtil.equals(currentUser.getUsername(), username), "不能删除自己.");
+
+        // 删除用户
+        UserInfo deleteUser = userConfig.getUserInfo(username);
+        Assert.notNull(deleteUser, "用户已删除.");
+        userConfig.removeUserInfo(username);
+        manager.editUserConfig(userConfig);
+        return "删除用户成功!";
+    }
+
+    @Override
+    public UserInfo getUserInfo(String currentUserName) {
+        return getUserConfig().getUserInfo(currentUserName);
+    }
+
+    @Override
+    public UserInfoVo getUserInfoVo(String currentUserName, String username) {
+        // 管理员可以查看所有用户,普通用户只能查看自己
+        UserConfig userConfig = getUserConfig();
+        UserInfo currentUser = userConfig.getUserInfo(currentUserName);
+        boolean admin = null != currentUser && UserRoleEnum.isAdmin(currentUser.getRoleCode());
+        boolean self = null != currentUser && StringUtil.equals(currentUser.getUsername(), username);
+        Assert.isTrue(admin || self, "No permission.");
+
+        UserInfo userInfo = getUserConfig().getUserInfo(username);
+        return convertUserInfo2Vo(userInfo);
+    }
+
+    @Override
+    public List<UserInfoVo> getUserInfoAll(String currentUserName) {
+        // 系统管理员可以查看所有用户,其他用户只能查看自己
+        UserConfig userConfig = getUserConfig();
+        UserInfo currentUser = userConfig.getUserInfo(currentUserName);
+        boolean admin = null != currentUser && UserRoleEnum.isAdmin(currentUser.getRoleCode());
+        if (admin) {
+            return getUserConfig().getUserInfoList().stream().map(user -> convertUserInfo2Vo(user)).collect(Collectors.toList());
+        }
+
+        List<UserInfoVo> list = new ArrayList<>();
+        UserInfo userInfo = userConfig.getUserInfo(currentUserName);
+        list.add(convertUserInfo2Vo(userInfo));
+        return list;
+    }
+
+    @Override
+    public UserConfig getUserConfig() {
+        List<UserConfig> all = manager.getUserConfigAll();
+        if (!CollectionUtils.isEmpty(all)) {
+            return all.get(0);
+        }
+
+        synchronized (this) {
+            all = manager.getUserConfigAll();
+            if (!CollectionUtils.isEmpty(all)) {
+                return all.get(0);
+            }
+
+            UserConfig userConfig = (UserConfig) userConfigChecker.checkAddConfigModel(new HashMap<>());
+            UserRoleEnum admin = UserRoleEnum.ADMIN;
+            userConfig.getUserInfoList().add(new UserInfo(DEFAULT_USERNAME, DEFAULT_USERNAME, DEFAULT_PASSWORD, admin.getCode(), ""));
+            manager.addUserConfig(userConfig);
+            return userConfig;
+        }
+    }
+
+    private UserInfoVo convertUserInfo2Vo(UserInfo userInfo) {
+        UserInfoVo userInfoVo = new UserInfoVo();
+        if (null != userInfo) {
+            BeanUtils.copyProperties(userInfo, userInfoVo);
+            // 避免密码直接暴露
+            userInfoVo.setPassword("***");
+            userInfoVo.setRoleName(UserRoleEnum.getNameByCode(userInfo.getRoleCode()));
+        }
+        return userInfoVo;
+    }
+
+}

+ 0 - 10
dbsyncer-biz/src/main/java/org/dbsyncer/biz/vo/ConfigVo.java

@@ -4,14 +4,4 @@ import org.dbsyncer.parser.model.Config;
 
 public class ConfigVo extends Config {
 
-    private String id;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
 }

+ 24 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/vo/UserInfoVo.java

@@ -0,0 +1,24 @@
+package org.dbsyncer.biz.vo;
+
+import org.dbsyncer.parser.model.UserInfo;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/17 0:14
+ */
+public class UserInfoVo extends UserInfo {
+
+    /**
+     * 角色名称
+     */
+    private String roleName;
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+}

+ 27 - 11
dbsyncer-connector/src/main/test/ConnectionTest.java

@@ -1,5 +1,7 @@
 import oracle.jdbc.OracleConnection;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.RandomUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.config.DatabaseConfig;
 import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 import org.dbsyncer.connector.database.ds.SimpleConnection;
@@ -107,43 +109,57 @@ public class ConnectionTest {
 
     @Test
     public void testBatchInsert() {
-        final DatabaseConnectorMapper connectorMapper = new DatabaseConnectorMapper(createPostgresConfig());
+        final DatabaseConnectorMapper connectorMapper = new DatabaseConnectorMapper(createMysqlConfig());
 
         long begin = Instant.now().toEpochMilli();
         final int threadSize = 10;
         final ExecutorService pool = Executors.newFixedThreadPool(threadSize);
+        //final String sql = "insert into t_course2 (id,course,score,user_id,memo) VALUES (?,?,?,?,?)";
+        final String sql = "INSERT INTO `vote_record_memory` (`id`, `user_id`, `vote_num`, `group_id`, `status`, `create_time`) VALUES (?, ?, ?, ?, ?, ?)";
 
         // 模拟1000w条数据
         List<Object[]> dataList = new ArrayList<>();
-        for (int i = 1; i <= 10000001; i++) {
-            Object[] args = new Object[5];
+        for (int i = 1; i <= 10000002; i++) {
+            // 442001, 'dA8LeJLtX9MgQgDe7H1O', 9620, 1, 2, '2022-11-17 16:35:21'
+            Object[] args = new Object[6];
             args[0] = i;
-            args[1] = "mathaaaaaaaaaaaaaaaaaa";
-            args[2] = 9999;
-            args[3] = 8888;
-            args[4] = "888899999999999999999999999999蓉儿UN是代付款房间里的解放东路来得及分类的恢复力度菲欧";
+            args[1] = randomUserId(20);
+            args[2] = RandomUtil.nextInt(1, 9999);
+            args[3] = RandomUtil.nextInt(0, 3);
+            args[4] = RandomUtil.nextInt(1, 3);
+            args[5] = Timestamp.valueOf(LocalDateTime.now());
             dataList.add(args);
 
             if (i % 10000 == 0) {
                 System.out.println(i + "-----------------正在处理");
-                batchInsert(connectorMapper, pool, dataList, 1000);
+                batchInsert(connectorMapper, pool, sql, dataList, 1000);
                 dataList.clear();
             }
         }
 
         if(!CollectionUtils.isEmpty(dataList)){
             System.out.println("-----------------正在处理剩余数据");
-            batchInsert(connectorMapper, pool, dataList, 1000);
+            batchInsert(connectorMapper, pool, sql, dataList, 1000);
         }
 
         pool.shutdown();
         logger.info("总共耗时:{}秒", (Instant.now().toEpochMilli() - begin) / 1000);
     }
 
-    private void batchInsert(DatabaseConnectorMapper connectorMapper, ExecutorService pool, List<Object[]> dataList, int batchSize) {
+    private final static String STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+    private String randomUserId(int i) {
+        StringBuilder s = new StringBuilder();
+        for (int j = 0; j < i; j++) {
+            int r = RandomUtil.nextInt(0, 62);
+            s.append(StringUtil.substring(STR, r, r + 1));
+        }
+        return s.toString();
+    }
+
+    private void batchInsert(DatabaseConnectorMapper connectorMapper, ExecutorService pool, String sql, List<Object[]> dataList, int batchSize) {
         int total = dataList.size();
         int taskSize = total % batchSize == 0 ? total / batchSize : total / batchSize + 1;
-        final String sql = "insert into t_course2 (id,course,score,user_id,memo) VALUES (?,?,?,?,?)";
         final CountDownLatch latch = new CountDownLatch(taskSize);
         int fromIndex = 0;
         int toIndex = batchSize;

+ 9 - 0
dbsyncer-manager/src/main/java/org/dbsyncer/manager/Manager.java

@@ -27,6 +27,15 @@ import java.util.Map;
  */
 public interface Manager extends Executor {
 
+    // user
+    String addUserConfig(ConfigModel model);
+
+    String editUserConfig(ConfigModel model);
+
+    UserConfig getUserConfig(String id);
+
+    List<UserConfig> getUserConfigAll();
+
     // project group
     String addProjectGroup(ConfigModel model);
 

+ 25 - 1
dbsyncer-manager/src/main/java/org/dbsyncer/manager/ManagerFactory.java

@@ -67,6 +67,30 @@ public class ManagerFactory implements Manager, ApplicationListener<ClosedEvent>
     @Autowired
     private Map<String, Puller> map;
 
+    @Override
+    public String addUserConfig(ConfigModel model) {
+        return operationTemplate.execute(new OperationConfig(model, CommandEnum.OPR_ADD));
+    }
+
+    @Override
+    public String editUserConfig(ConfigModel model) {
+        return operationTemplate.execute(new OperationConfig(model, CommandEnum.OPR_EDIT));
+    }
+
+    @Override
+    public UserConfig getUserConfig(String id) {
+        return operationTemplate.queryObject(UserConfig.class, id);
+    }
+
+    @Override
+    public List<UserConfig> getUserConfigAll() {
+        UserConfig userConfig = new UserConfig();
+        userConfig.setType(ConfigConstant.USER_CONFIG);
+        QueryConfig<UserConfig> queryConfig = new QueryConfig<>(userConfig);
+        List<UserConfig> userConfigs = operationTemplate.queryAll(queryConfig);
+        return userConfigs;
+    }
+
     @Override
     public String addProjectGroup(ConfigModel model) {
         return operationTemplate.execute(new OperationConfig(model, CommandEnum.OPR_ADD));
@@ -431,4 +455,4 @@ public class ManagerFactory implements Manager, ApplicationListener<ClosedEvent>
         return puller;
     }
 
-}
+}

+ 4 - 0
dbsyncer-manager/src/main/java/org/dbsyncer/manager/command/PreloadCommand.java

@@ -38,4 +38,8 @@ public class PreloadCommand implements Command {
     public Object parseProjectGroup() {
         return parser.parseObject(json, ProjectGroup.class);
     }
+
+    public Object parseUserConfig() {
+        return parser.parseObject(json, UserConfig.class);
+    }
 }

+ 6 - 1
dbsyncer-manager/src/main/java/org/dbsyncer/manager/enums/CommandEnum.java

@@ -50,7 +50,12 @@ public enum CommandEnum {
     /**
      * 预加载ProjectGroup
      */
-    PRELOAD_PROJECT_GROUP(ConfigConstant.PROJECT_GROUP, true, (cmd) -> ((PreloadCommand) cmd).parseProjectGroup());
+    PRELOAD_PROJECT_GROUP(ConfigConstant.PROJECT_GROUP, true, (cmd) -> ((PreloadCommand) cmd).parseProjectGroup()),
+
+    /**
+     * 预加载用户配置
+     */
+    USER_CONFIG(ConfigConstant.USER_CONFIG, true, (cmd) -> ((PreloadCommand) cmd).parseUserConfig());
 
     private String modelType;
     private boolean preload;

+ 1 - 7
dbsyncer-manager/src/main/java/org/dbsyncer/manager/puller/FullPuller.java

@@ -106,10 +106,10 @@ public class FullPuller extends AbstractPuller implements ApplicationListener<Fu
 
         int i = task.getTableGroupIndex();
         while (i < list.size()){
+            parser.execute(task, mapping, list.get(i), executorService);
             if (!task.isRunning()) {
                 break;
             }
-            parser.execute(task, mapping, list.get(i), executorService);
             task.setPageIndex(ParserEnum.PAGE_INDEX.getDefaultValue());
             task.setCursor(null);
             task.setTableGroupIndex(++i);
@@ -119,7 +119,6 @@ public class FullPuller extends AbstractPuller implements ApplicationListener<Fu
         // 记录结束时间
         task.setEndTime(Instant.now().toEpochMilli());
         task.setTableGroupIndex(ParserEnum.TABLE_GROUP_INDEX.getDefaultValue());
-        task.setFinished(true);
         flush(task);
     }
 
@@ -133,11 +132,6 @@ public class FullPuller extends AbstractPuller implements ApplicationListener<Fu
             meta.getTotal().set(finished);
         }
 
-        // 同步实际完成总数(读取的系统表存在误差,执行的过程中,总数可能有变化)
-        if(task.isFinished() && meta.getTotal().get() != finished){
-            meta.getTotal().set(finished);
-        }
-
         meta.setBeginTime(task.getBeginTime());
         meta.setEndTime(task.getEndTime());
         Map<String, String> snapshot = meta.getSnapshot();

+ 3 - 1
dbsyncer-manager/src/main/java/org/dbsyncer/manager/template/PreloadTemplate.java

@@ -90,7 +90,7 @@ public final class PreloadTemplate implements ApplicationListener<ContextRefresh
             return;
         }
 
-        // Load configs
+        // Load config
         reload(map, CommandEnum.PRELOAD_CONFIG);
         // Load connectors
         reload(map, CommandEnum.PRELOAD_CONNECTOR);
@@ -100,6 +100,8 @@ public final class PreloadTemplate implements ApplicationListener<ContextRefresh
         reload(map, CommandEnum.PRELOAD_META);
         // Load projectGroups
         reload(map, CommandEnum.PRELOAD_PROJECT_GROUP);
+        // Load userConfig
+        reload(map, CommandEnum.USER_CONFIG);
         launch();
     }
 

+ 0 - 20
dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/Config.java

@@ -7,21 +7,8 @@ package org.dbsyncer.parser.model;
  */
 public class Config extends ConfigModel {
 
-    private String password;
-
     private int refreshInterval = 5;
 
-    // 同步失败发送邮箱,多个以分号分割
-    private String email;
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
     public int getRefreshInterval() {
         return refreshInterval;
     }
@@ -30,11 +17,4 @@ public class Config extends ConfigModel {
         this.refreshInterval = refreshInterval;
     }
 
-    public String getEmail() {
-        return email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-    }
 }

+ 1 - 1
dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/ConfigModel.java

@@ -12,7 +12,7 @@ public class ConfigModel {
     private String id;
 
     /**
-     * connector/mapping/tableGroup/meta/config
+     * connector/mapping/tableGroup/meta/config/ProjectGroup/UserConfig
      *
      * @see ConfigConstant
      */

+ 0 - 10
dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/Task.java

@@ -16,8 +16,6 @@ public class Task {
 
     private long endTime;
 
-    private boolean finished;
-
     public Task() {
     }
 
@@ -82,14 +80,6 @@ public class Task {
         this.endTime = endTime;
     }
 
-    public boolean isFinished() {
-        return finished;
-    }
-
-    public void setFinished(boolean finished) {
-        this.finished = finished;
-    }
-
     public enum StateEnum {
         /**
          * 运行

+ 64 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/UserConfig.java

@@ -0,0 +1,64 @@
+package org.dbsyncer.parser.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * 用户配置
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/17 22:54
+ */
+public class UserConfig extends ConfigModel {
+
+    private List<UserInfo> userInfoList = new ArrayList<>();
+
+    public synchronized void addUserInfo(UserInfo userInfo){
+        if(userInfoList.contains(userInfo)){
+            return;
+        }
+        userInfoList.add(userInfo);
+    }
+
+    public synchronized void updateUserInfo(UserInfo userInfo){
+        for (UserInfo u : userInfoList) {
+            if(u.getUsername().equals(userInfo.getUsername())){
+                u.setNickname(userInfo.getNickname());
+                u.setPassword(userInfo.getPassword());
+                break;
+            }
+        }
+    }
+
+    public synchronized void removeUserInfo(String username){
+        Iterator<UserInfo> iterator = userInfoList.iterator();
+        while (iterator.hasNext()){
+            UserInfo next = iterator.next();
+            if(next.getUsername().equals(username)){
+                iterator.remove();
+                break;
+            }
+        }
+    }
+
+    public synchronized UserInfo getUserInfo(String username){
+        Iterator<UserInfo> iterator = userInfoList.iterator();
+        while (iterator.hasNext()){
+            UserInfo next = iterator.next();
+            if(next.getUsername().equals(username)){
+                return next;
+            }
+        }
+        return null;
+    }
+
+    public List<UserInfo> getUserInfoList() {
+        return userInfoList;
+    }
+
+    public void setUserInfoList(List<UserInfo> userInfoList) {
+        this.userInfoList = userInfoList;
+    }
+}

+ 99 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/UserInfo.java

@@ -0,0 +1,99 @@
+package org.dbsyncer.parser.model;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/17 23:09
+ */
+public class UserInfo {
+
+    /**
+     * 账号
+     */
+    private String username;
+
+    /**
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 角色
+     */
+    private String roleCode;
+
+    /**
+     * 邮箱(多个邮箱使用分号拼接)
+     */
+    private String mail;
+
+    public UserInfo() {
+    }
+
+    public UserInfo(String username, String nickname, String password, String roleCode, String mail) {
+        this.username = username;
+        this.nickname = nickname;
+        this.password = password;
+        this.roleCode = roleCode;
+        this.mail = mail;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getRoleCode() {
+        return roleCode;
+    }
+
+    public void setRoleCode(String roleCode) {
+        this.roleCode = roleCode;
+    }
+
+    public String getMail() {
+        return mail;
+    }
+
+    public void setMail(String mail) {
+        this.mail = mail;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(obj instanceof UserInfo){
+            UserInfo userInfo = (UserInfo) obj;
+            return userInfo.username.equals(this.username);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return username.hashCode();
+    }
+}

+ 1 - 0
dbsyncer-storage/src/main/java/org/dbsyncer/storage/constant/ConfigConstant.java

@@ -26,6 +26,7 @@ public class ConfigConstant {
     public static final String META = "meta";
     public static final String CONFIG = "config";
     public static final String PROJECT_GROUP = "projectGroup";
+    public static final String USER_CONFIG = "userConfig";
 
     /**
      * 数据

+ 2 - 2
dbsyncer-storage/src/main/java/org/dbsyncer/storage/support/MysqlStorageServiceImpl.java

@@ -234,9 +234,9 @@ public class MysqlStorageServiceImpl extends AbstractStorageService {
         // order by updateTime,createTime desc
         sql.append(" order by ");
         if (executor.isOrderByUpdateTime()) {
-            sql.append(ConfigConstant.CONFIG_MODEL_UPDATE_TIME).append(",");
+            sql.append(UnderlineToCamelUtils.camelToUnderline(ConfigConstant.CONFIG_MODEL_UPDATE_TIME)).append(",");
         }
-        sql.append(ConfigConstant.CONFIG_MODEL_CREATE_TIME).append(" desc");
+        sql.append(UnderlineToCamelUtils.camelToUnderline(ConfigConstant.CONFIG_MODEL_CREATE_TIME)).append(" desc");
         sql.append(DatabaseConstant.MYSQL_PAGE_SQL);
         args.add((query.getPageNum() - 1) * query.getPageSize());
         args.add(query.getPageSize());

+ 11 - 0
dbsyncer-storage/src/main/java/org/dbsyncer/storage/util/BinlogMessageUtil.java

@@ -11,9 +11,11 @@ import org.slf4j.LoggerFactory;
 
 import java.io.InputStream;
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.sql.*;
+import java.time.LocalDateTime;
 import java.util.BitSet;
 
 /**
@@ -87,6 +89,10 @@ public abstract class BinlogMessageUtil {
                 buffer.putInt((Integer) v);
                 buffer.flip();
                 return ByteString.copyFrom(buffer, 4);
+            case "java.math.BigInteger":
+                BigInteger bigInteger = (BigInteger) v;
+                byte[] bytes = bigInteger.toByteArray();
+                return ByteString.copyFrom(bytes, 0, 8);
             case "java.lang.Long":
                 buffer.clear();
                 buffer.putLong((Long) v);
@@ -121,6 +127,11 @@ public abstract class BinlogMessageUtil {
                 buffer.putShort((short) (b ? 1 : 0));
                 buffer.flip();
                 return ByteString.copyFrom(buffer, 2);
+            case "java.time.LocalDateTime":
+                buffer.clear();
+                buffer.putLong(Timestamp.valueOf((LocalDateTime) v).getTime());
+                buffer.flip();
+                return ByteString.copyFrom(buffer, 8);
             case "oracle.sql.TIMESTAMP":
                 buffer.clear();
                 TIMESTAMP timeStamp = (TIMESTAMP) v;

+ 3 - 0
dbsyncer-storage/src/main/test/ShardBinlogTest.java

@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.nio.charset.Charset;
 import java.sql.Date;
 import java.sql.Timestamp;
@@ -160,6 +161,8 @@ public class ShardBinlogTest {
         data.put("name", key + "中文");
         data.put("age", 88);
         data.put("bd", new BigDecimal(88));
+        data.put("bigInt", new BigInteger("123456789876543210"));
+        data.put("localTime", LocalDateTime.now());
         data.put("sex", 1);
         data.put("f", 88.88f);
         data.put("d", 999.99d);

+ 4 - 7
dbsyncer-web/src/main/java/org/dbsyncer/web/config/WebAppConfig.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.web.config;
 
-import org.dbsyncer.biz.ConfigService;
+import org.dbsyncer.biz.UserService;
 import org.dbsyncer.biz.vo.RestResult;
 import org.dbsyncer.common.util.JsonUtil;
 import org.dbsyncer.common.util.SHA1Util;
@@ -8,7 +8,6 @@ import org.dbsyncer.common.util.StringUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.authentication.AuthenticationProvider;
@@ -57,11 +56,9 @@ public class WebAppConfig extends WebSecurityConfigurerAdapter implements Authen
      */
     private static final int MAXIMUM_SESSIONS = 1;
 
-    @Value(value = "${dbsyncer.web.login.username}")
-    private String username;
-
     @Autowired
-    private ConfigService configService;
+    private UserService userService;
+
 
     /**
      * 登录失败
@@ -141,7 +138,7 @@ public class WebAppConfig extends WebSecurityConfigurerAdapter implements Authen
         String password = (String) authentication.getCredentials();
         password = SHA1Util.b64_sha1(password);
 
-        if (!StringUtil.equals(username, this.username) || !StringUtil.equals(configService.getPassword(), password)) {
+        if (!StringUtil.equals(userService.getPassword(username), password)) {
             throw new BadCredentialsException("对不起,您输入的帐号或密码错误");
         }
         return new UsernamePasswordAuthenticationToken(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));

+ 2 - 3
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/index/ProjectGroupController.java

@@ -3,7 +3,6 @@ package org.dbsyncer.web.controller.index;
 import org.dbsyncer.biz.ConnectorService;
 import org.dbsyncer.biz.MappingService;
 import org.dbsyncer.biz.ProjectGroupService;
-import org.dbsyncer.biz.vo.ProjectGroupVo;
 import org.dbsyncer.biz.vo.RestResult;
 import org.dbsyncer.web.controller.BaseController;
 import org.slf4j.Logger;
@@ -38,14 +37,14 @@ public class ProjectGroupController extends BaseController {
     private MappingService mappingService;
 
     @GetMapping("/page/add")
-    public String pageAdd(HttpServletRequest request, ModelMap model) {
+    public String pageAdd(ModelMap model) {
         model.put("connectors", connectorService.getConnectorAll());
         model.put("mappings", mappingService.getMappingAll());
         return "group/save";
     }
 
     @GetMapping("/page/edit")
-    public String pageEdit(HttpServletRequest request, ModelMap model, String id) {
+    public String pageEdit(ModelMap model, String id) {
         model.put("projectGroup", projectGroupService.getProjectGroup(id));
         model.put("connectors", connectorService.getConnectorAll());
         model.put("mappings", mappingService.getMappingAll());

+ 0 - 51
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/pwd/PwdController.java

@@ -1,51 +0,0 @@
-package org.dbsyncer.web.controller.pwd;
-
-import org.dbsyncer.biz.ConfigService;
-import org.dbsyncer.biz.vo.RestResult;
-import org.dbsyncer.web.controller.BaseController;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Map;
-
-/**
- * 密码修改处理
- * @ClassName: PwdController
- * @author AE86
- * @date: 2017年7月7日 上午10:03:33
- */
-@Controller
-@RequestMapping(value = "/pwd")
-public class PwdController extends BaseController {
-
-	private final Logger logger = LoggerFactory.getLogger(getClass());
-
-	@Autowired
-	private ConfigService configService;
-
-	@RequestMapping("")
-	public String index(ModelMap model) {
-		model.put("config", configService.getConfig());
-		return "pwd/pwd";
-	}
-
-	@PostMapping("/edit")
-	@ResponseBody
-	public RestResult edit(HttpServletRequest request) {
-		try {
-			Map<String, String> params = getParams(request);
-			return RestResult.restSuccess(configService.edit(params));
-		} catch (Exception e) {
-			logger.error(e.getLocalizedMessage(), e.getClass());
-			return RestResult.restFail(e.getMessage());
-		}
-	}
-
-}

+ 1 - 1
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/system/SystemController.java

@@ -47,7 +47,7 @@ public class SystemController extends BaseController {
 	@ResponseBody
 	public RestResult queryConfig(HttpServletRequest request) {
 		try {
-			return RestResult.restSuccess(configService.queryConfig());
+			return RestResult.restSuccess(configService.getConfig());
 		} catch (Exception e) {
 			logger.error(e.getLocalizedMessage(), e.getClass());
 			return RestResult.restFail(e.getMessage());

+ 125 - 0
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/user/UserController.java

@@ -0,0 +1,125 @@
+package org.dbsyncer.web.controller.user;
+
+import org.dbsyncer.biz.UserService;
+import org.dbsyncer.biz.vo.RestResult;
+import org.dbsyncer.biz.vo.UserInfoVo;
+import org.dbsyncer.web.controller.BaseController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * 用户信息管理
+ *
+ * @author AE86
+ * @ClassName: UserController
+ * @date: 2017年7月7日 上午10:03:33
+ */
+@Controller
+@RequestMapping(value = "/user")
+public class UserController extends BaseController {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Autowired
+    private UserService userService;
+
+    @RequestMapping("")
+    public String index(ModelMap model) {
+        model.put("currentUser", getUserInfoVo());
+        model.put("users", userService.getUserInfoAll(getUserName()));
+        return "user/user";
+    }
+
+    @GetMapping("/page/add")
+    public String pageAdd(ModelMap model) {
+        return "user/add";
+    }
+
+    @GetMapping("/page/edit")
+    public String pageEdit(ModelMap model, String username) {
+        String currentUserName = getUserName();
+        model.put(UserService.CURRENT_USER_NAME, currentUserName);
+        model.put("currentUser", userService.getUserInfoVo(currentUserName, username));
+        return "user/edit";
+    }
+
+    @GetMapping("/getUserInfo.json")
+    @ResponseBody
+    public RestResult getUserInfo() {
+        return RestResult.restSuccess(getUserInfoVo());
+    }
+
+    @RequestMapping(value = "/add")
+    @ResponseBody
+    public RestResult add(HttpServletRequest request) {
+        try {
+            Map<String, String> params = getParamsWithUserName(request);
+            return RestResult.restSuccess(userService.add(params));
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            return RestResult.restFail(e.getMessage());
+        }
+    }
+
+    @RequestMapping(value = "/edit")
+    @ResponseBody
+    public RestResult edit(HttpServletRequest request) {
+        try {
+            Map<String, String> params = getParamsWithUserName(request);
+            return RestResult.restSuccess(userService.edit(params));
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            return RestResult.restFail(e.getMessage());
+        }
+    }
+
+    @PostMapping("/remove")
+    @ResponseBody
+    public RestResult remove(HttpServletRequest request) {
+        try {
+            Map<String, String> params = getParamsWithUserName(request);
+            return RestResult.restSuccess(userService.remove(params));
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            return RestResult.restFail(e.getMessage());
+        }
+    }
+
+    private Map<String, String> getParamsWithUserName(HttpServletRequest request) {
+        Map<String, String> params = getParams(request);
+        params.put(UserService.CURRENT_USER_NAME, getUserName());
+        return params;
+    }
+
+    /**
+     * 获取登录用户信息
+     *
+     * @return
+     */
+    private UserInfoVo getUserInfoVo() {
+        String currentUserName = getUserName();
+        return userService.getUserInfoVo(currentUserName, currentUserName);
+    }
+
+    private String getUserName() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        String username = authentication.getName();
+        Assert.hasText(username, "无法获取登录用户.");
+        return username;
+    }
+
+
+}

+ 0 - 2
dbsyncer-web/src/main/resources/application.properties

@@ -2,8 +2,6 @@ server.ip=127.0.0.1
 server.port=18686
 #web
 dbsyncer.web.worker.id=1
-dbsyncer.web.login.username=admin
-dbsyncer.web.login.password=0DPiKuNIrrVmD8IUCuw1hQxNqZc=
 dbsyncer.web.task.scheduler.pool-size=8
 dbsyncer.web.task.executor.core-size=10
 dbsyncer.web.task.executor.queue-capacity=1000

+ 0 - 1
dbsyncer-web/src/main/resources/public/index.html

@@ -18,7 +18,6 @@
     <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/bootstrap-dialog/bootstrap-dialog.min.css}"/>
     <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/bootstrap-select/bootstrap-select.min.css}"/>
     <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/bootstrap-switch/bootstrap-switch.min.css}"/>
-    <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/bootstrap-table/bootstrap-table-reorder-rows.css}"/>
     <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/bootstrap-fileinput/fileinput.min.css}"/>
     <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/icheck/all.css}"/>
     <link type="text/css" rel="stylesheet" th:href="@{/plugins/css/loading-plus/loading-plus.css}"/>

+ 4 - 4
dbsyncer-web/src/main/resources/public/login.html

@@ -11,10 +11,10 @@
 <form id="loginForm" name="loginForm" method="post">
 	<dl class="admin_login">
 		<dt><strong id="appName" /></dt>
-		<div id="loginTip" class="loginVerifcateTextError"></div>
-		<dd class="user_icon"><input type="text" name="username" placeholder="请输入帐号" class="login_txtbx required" /></dd>
-		<dd class="pwd_icon"><input type="password" name="password" placeholder="请输入密码" class="login_txtbx required" /></dd>
-		<dd class="pwd_icon"><input type="button" value="登录" class="submit_btn" id="loginSubmitBtn" /></dd>
+		<div id="loginTip" class="loginTextTip"></div>
+		<dd><input type="text" name="username" placeholder="请输入帐号" class="loginInput required" /></dd>
+		<dd><input type="password" name="password" placeholder="请输入密码" class="loginInput required" /></dd>
+		<dd><input type="button" value="登录" class="submit_btn" id="loginSubmitBtn" /></dd>
 	</dl>
 </form>
 <div class="footerContainer">

+ 10 - 6
dbsyncer-web/src/main/resources/public/nav.html

@@ -13,20 +13,24 @@
                         class="fa fa-tachometer"></span>驱动</a>
                 </li>
                 <li><a href="javascript:void(0);" url="/monitor"><span class="fa fa-line-chart"></span>监控</a></li>
-                <li><a href="javascript:void(0);" url="/plugin"><span class="fa fa-puzzle-piece"
-                                                                      aria-hidden="true"></span>插件</a></li>
+                <li><a href="javascript:void(0);" url="/plugin"><span class="fa fa-puzzle-piece" aria-hidden="true"></span>插件</a></li>
                 <li class="dropdown">
                     <a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown">配置<b class="caret"></b></a>
                     <ul class="dropdown-menu">
                         <li><a href="javascript:void(0);" url="/system"><span class="fa fa-cog"></span>系统参数</a></li>
-                        <li><a href="javascript:void(0);" url="/pwd"><span class="fa fa-lock"></span>修改密码</a></li>
-                        <li><a href="javascript:void(0);" url="/config"><span class="fa fa-file"
-                                                                              aria-hidden="true"></span>配置管理</a></li>
+                        <li><a href="javascript:void(0);" url="/user"><span class="fa fa-users"></span>用户管理</a></li>
+                        <li><a href="javascript:void(0);" url="/config"><span class="fa fa-file" aria-hidden="true"></span>配置管理</a></li>
                     </ul>
                 </li>
             </ul>
             <ul class="nav navbar-nav navbar-right">
-                <li><a href="javascript:void(0);" id="nav_logout"> <i class ="fa fa-power-off"></i>注销</a></li>
+                <li class="dropdown">
+                    <a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown"><span id="currentUser"></span></a>
+                    <ul class="dropdown-menu">
+                        <li><a href="javascript:void(0);" id="edit_personal"> <i class ="fa fa-pencil"></i>修改</a></li>
+                        <li><a href="javascript:void(0);" id="nav_logout"> <i class ="fa fa-power-off"></i>注销</a></li>
+                    </ul>
+                </li>
             </ul>
         </div>
     </div>

+ 0 - 49
dbsyncer-web/src/main/resources/public/pwd/pwd.html

@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
-
-<div class="container">
-    <form id="configEditForm" class="form-horizontal" role="form">
-        <div class="row text-center">
-            <div class="page-header">
-                <h3>修改密码</h3>
-            </div>
-        </div>
-
-        <!-- 操作 -->
-        <div class="row">
-            <div class="col-md-3">
-                <!-- 隐藏表单值 -->
-                <div class="form-group hidden">
-                    <input name="id" type="text" th:value="${config?.id}"/>
-                </div>
-            </div>
-            <div class="col-md-6">
-                <div class="form-group">
-                    <label class="col-sm-4 control-label">原密码 <strong class="driverVerifcateRequired">*</strong></label>
-                    <div class="col-sm-8">
-                        <input type="password" class="form-control" name="oldPwd" maxlength="32" dbsyncer-valid="require" placeholder="请输入原密码">
-                    </div>
-                </div>
-                <div class="form-group">
-                    <label class="col-sm-4 control-label">新密码 <strong class="driverVerifcateRequired">*</strong></label>
-                    <div class="col-sm-8">
-                        <input type="password" class="form-control" name="newPwd" maxlength="32" dbsyncer-valid="require" placeholder="请输入新密码">
-                    </div>
-                </div>
-                <div class="form-group">
-                    <div class="text-right col-sm-4"></div>
-                    <div class="text-right col-sm-8">
-                        <button id="updatePwdSubBtn" type="button" class="btn btn-primary">
-                            <span class="fa fa-save"></span>保存
-                        </button>
-                    </div>
-                </div>
-            </div>
-            <div class="col-md-3"></div>
-        </div>
-    </form>
-</div>
-
-<script th:src="@{/js/pwd/index.js}"></script>
-</html>

+ 0 - 6
dbsyncer-web/src/main/resources/public/system/system.html

@@ -26,12 +26,6 @@
                         <input type="number" class="form-control" max="100" min="1" dbsyncer-valid="require" name="refreshInterval" th:value="${config?.refreshInterval}"/>
                     </div>
                 </div>
-                <div class="form-group">
-                    <label class="col-sm-4 control-label">邮箱配置(多个邮箱分号分割)</label>
-                    <div class="col-sm-8">
-                        <input type="string" class="form-control" max="100" min="1" dbsyncer-valid="false" name="email" th:value="${config?.email}"/>
-                    </div>
-                </div>
                 <div class="form-group">
                     <div class="text-right col-sm-4"></div>
                     <div class="text-right col-sm-8">

+ 105 - 0
dbsyncer-web/src/main/resources/public/user/add.html

@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
+
+<div class="container-fluid">
+  <div class="container">
+    <form id="userAddForm" class="form-horizontal" role="form" method="post">
+      <!-- 标题 -->
+      <div class="row text-center">
+        <div class="page-header">
+          <h3>添加用户</h3>
+        </div>
+      </div>
+
+      <!-- 操作 -->
+      <div class="form-group">
+        <div class="col-md-10"></div>
+        <div class="col-md-2 text-right">
+          <button id="userSubmitBtn" type="button" class="btn btn-primary">
+            <span class="fa fa-save"></span>保存
+          </button>
+          <button id="userBackBtn" type="button" class="btn btn-default">
+            <span class="fa fa-reply"></span>返回
+          </button>
+        </div>
+      </div>
+
+      <!-- 配置 -->
+      <div class="row">
+        <div class="col-md-12">
+          <div class="panel panel-info">
+            <div class="panel-heading">
+              <h3 class="panel-title">用户配置</h3>
+            </div>
+
+            <div class="panel-body">
+              <!-- 账号 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">账号 <strong class="driverVerifcateRequired">*</strong></label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="username" type="text" maxlength="50" dbsyncer-valid="require" placeholder="账号"/>
+                </div>
+              </div>
+
+              <!-- 昵称 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">昵称 <strong class="driverVerifcateRequired">*</strong></label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="nickname" type="text" maxlength="50" dbsyncer-valid="require" placeholder="昵称"/>
+                </div>
+              </div>
+
+              <!-- 密码 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">密码 <strong class="driverVerifcateRequired">*</strong></label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="password" type="password" maxlength="50" dbsyncer-valid="require" placeholder="密码"/>
+                </div>
+              </div>
+
+              <!-- 邮箱 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">邮箱 <i class="fa fa-question-circle fa_gray" aria-hidden="true" title="多个邮箱使用分号拼接,例子:abc@qq.com;xxx@qq.com"></i></label>
+                <div class="col-sm-10">
+                  <input type="string" class="form-control" max="100" min="1" dbsyncer-valid="false" name="mail"/>
+                </div>
+              </div>
+
+            </div>
+          </div>
+        </div>
+      </div>
+
+    </form>
+  </div>
+</div>
+
+<script type="text/javascript">
+  // 跳转用户管理
+  function backUserIndexPage() {
+    doLoader("/user?refresh=" + new Date().getTime());
+  }
+
+  //保存
+  $("#userSubmitBtn").click(function () {
+    const $form = $("#userAddForm");
+    if ($form.formValidate() == true) {
+      const data = $form.serializeJson();
+      doPoster("/user/add", data, function (data) {
+        if (data.success == true) {
+          bootGrowl("新增用户成功!", "success");
+          backUserIndexPage();
+        } else {
+          bootGrowl(data.resultValue, "danger");
+        }
+      });
+    }
+  });
+
+  //返回
+  $("#userBackBtn").click(function () {
+    backUserIndexPage();
+  });
+</script>
+</html>

+ 135 - 0
dbsyncer-web/src/main/resources/public/user/edit.html

@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
+
+<div class="container-fluid">
+  <div class="container">
+    <form id="userEditForm" class="form-horizontal" role="form" method="post">
+      <!-- 标题 -->
+      <div class="row text-center">
+        <div class="page-header">
+          <h3>修改用户</h3>
+        </div>
+      </div>
+
+      <!-- 操作 -->
+      <div class="form-group">
+        <div class="col-md-10"></div>
+        <div class="col-md-2 text-right">
+          <button id="userSubmitBtn" type="button" class="btn btn-primary">
+            <span class="fa fa-save"></span>保存
+          </button>
+          <button id="userBackBtn" type="button" class="btn btn-default">
+            <span class="fa fa-reply"></span>返回
+          </button>
+        </div>
+      </div>
+
+      <!-- 配置 -->
+      <div class="row">
+        <div class="col-md-12">
+          <div class="panel panel-info">
+            <div class="panel-heading">
+              <h3 class="panel-title">用户配置</h3>
+            </div>
+
+            <div class="panel-body">
+              <!-- 账号 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">角色</label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="roleName" type="text" readonly="true" th:value="${currentUser?.roleName}"/>
+                </div>
+              </div>
+              <!-- 账号 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">账号</label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="username" type="text" maxlength="50" placeholder="账号" readonly="true" th:value="${currentUser?.username}"/>
+                </div>
+              </div>
+
+              <!-- 昵称 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">昵称 <strong class="driverVerifcateRequired">*</strong></label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="nickname" type="text" maxlength="50" dbsyncer-valid="require" placeholder="昵称" th:value="${currentUser?.nickname}"/>
+                </div>
+              </div>
+
+              <!-- 旧密码 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">旧密码</label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="oldPwd" type="password" maxlength="50" placeholder="密码"/>
+                </div>
+              </div>
+
+              <!-- 新密码 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">新密码</label>
+                <div class="col-sm-10">
+                  <input class="form-control" name="newPwd" type="password" maxlength="50" placeholder="密码"/>
+                </div>
+              </div>
+
+              <!-- 邮箱 -->
+              <div class="form-group">
+                <label class="col-sm-2 control-label">邮箱 <i class="fa fa-question-circle fa_gray" aria-hidden="true" title="多个邮箱使用分号拼接,例子:abc@qq.com;xxx@qq.com"></i></label>
+                <div class="col-sm-10">
+                  <input type="string" class="form-control" max="100" min="1" name="mail" th:value="${currentUser?.mail}"/>
+                </div>
+              </div>
+
+            </div>
+          </div>
+        </div>
+      </div>
+
+    </form>
+  </div>
+</div>
+
+<script type="text/javascript" th:inline="javascript">
+  const currentUserName = [[${currentUserName}]];
+
+  // 跳转用户管理
+  function backUserIndexPage() {
+    doLoader("/user?refresh=" + new Date().getTime());
+  }
+
+  //保存
+  $("#userSubmitBtn").click(function () {
+    const $form = $("#userEditForm");
+    if ($form.formValidate() == true) {
+      const data = $form.serializeJson();
+      const username = data.username;
+      const newPwd = data.newPwd;
+      doPoster("/user/edit", data, function (data) {
+        if (data.success == true) {
+          bootGrowl("修改用户成功!", "success");
+          backUserIndexPage();
+          // 刷新个人信息
+          if (currentUserName == username) {
+            // 修改个人密码后需要重新登录
+            if (!isBlank(newPwd)) {
+              doPoster("/logout", null, function (data) {
+                location.href = $basePath;
+              });
+              return;
+            }
+            refreshLoginUser();
+          }
+        } else {
+          bootGrowl(data.resultValue, "danger");
+        }
+      });
+    }
+  });
+
+  //返回
+  $("#userBackBtn").click(function () {
+    backUserIndexPage();
+  });
+</script>
+</html>

+ 61 - 0
dbsyncer-web/src/main/resources/public/user/user.html

@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
+
+<div class="container">
+    <form id="configEditForm" class="form-horizontal" role="form">
+        <div class="row text-center">
+            <div class="page-header">
+                <h3>用户管理</h3>
+            </div>
+        </div>
+
+        <!-- 管理员操作区域 -->
+        <div class="form-group" th:if="${currentUser?.roleCode eq 'admin'}">
+            <div class="row">
+                <div class="col-sm-10"></div>
+                <div class="col-md-2 text-right">
+                    <button id="addUserBtn" type="button" class="btn btn-primary">
+                        <span class="fa fa-plus"></span>添加([[${users?.size()} ?: 0]])
+                    </button>
+                </div>
+            </div>
+        </div>
+
+        <!-- 操作 -->
+        <div class="row">
+            <div class="col-md-12">
+                <table class="table table-hover">
+                    <thead>
+                    <tr>
+                        <th>用户</th>
+                        <th>角色</th>
+                        <th>邮箱</th>
+                        <th>操作</th>
+                    </tr>
+                    </thead>
+                    <tbody id="userList">
+                    <tr th:each="u,state : ${users}">
+                        <td th:text="${u?.username + '(' + u?.nickname + ')'}"/>
+                        <td th:text="${u?.roleName}"/>
+                        <td th:text="${u?.mail}"/>
+                        <td>
+                            <!-- 管理员或本人权限 -->
+                            <button th:if="${currentUser?.roleCode eq 'admin' or currentUser?.username eq u?.username}" type="button" th:id="${u?.username}" class="btn btn-primary editUserBtn">
+                                <span class="fa fa-pencil"></span>修改
+                            </button>
+                            <!-- 管理员且非本人权限 -->
+                            <button th:if="${currentUser?.roleCode eq 'admin' and currentUser?.username != u?.username}" type="button" th:id="${u?.username}" class="btn btn-default removeUserBtn">
+                                <span class="fa fa-times"></span>删除
+                            </button>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    </form>
+</div>
+
+<script th:src="@{/js/user/index.js}"></script>
+</html>

+ 21 - 204
dbsyncer-web/src/main/resources/static/css/login/login.css

@@ -1,213 +1,30 @@
 @charset "UTF-8";
-html{overflow-y:hidden;}
-body{margin:0;height:100%;}
-a:active,a:hover{outline:0}
-button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}
-button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
-input,select,button{outline:none;}
-table{border-collapse:collapse;border-spacing:0}
-td,th{padding:0}
-img{vertical-align:middle;border:0}
-@-ms-viewport{width:device-width}
-html{font-size:50px;-webkit-tap-highlight-color:transparent;height:100%;min-width:320px;overflow-x:hidden}
-body{font-family:"Microsoft YaHei";font-size:.28em;line-height:1;color:#333;background-color:white;}
-.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.1}
-.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1}
-.h1,.h2,.h3,h1,h2,h3{margin-top:.28rem;margin-bottom:.14rem}
-.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}
-.h4,.h5,.h6,h4,h5,h6{margin-top:.14rem;margin-bottom:.14rem}
-.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}
-.h1,h1{font-size:.364rem}
-.h2,h2{font-size:.2996rem}
-.h3,h3{font-size:.238rem}
-.h4,h4{font-size:.175rem}
-.h5,h5{font-size:.14rem}
-.h6,h6{font-size:.119rem}
-h6{margin-top:0;margin-bottom:0}
-button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}
-a{color:#06c1ae;text-decoration:none;outline:0}
-a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}
-a.react,label.react{display:block;color:inherit;height:100%}
-a.react.react-active,a.react:active,label.react:active{background:rgba(0,0,0,.1)}
-ul{margin:0;padding:0;list-style-type:none}
-hr{margin-top:.28rem;margin-bottom:.28rem;border:0;border-top:1px solid #DDD8CE}
-h6,p{line-height:1.41;text-align:justify;margin:-.2em 0;word-break:break-all}
-small,weak{color:#666}
-::-webkit-input-placeholder {color:#717171;line-height:inherit;} 
-:-moz-placeholder {color:#717171;line-height:inherit;} 
-::-moz-placeholder {color:#717171;line-height:inherit;}
+html{overflow-y:hidden;font-family:"Microsoft YaHei";font-size:50px;-webkit-tap-highlight-color:transparent;height:100%;min-width:320px;overflow-x:hidden}
+body{margin:0;height:100%;font-size:.28em;line-height:1;background:#23A6D5;
+/* 标准语法 */animation-name:bg-gradient;animation-duration:5s;animation-iteration-count:infinite;animation-direction:alternate;
+/* IE */-ms-animation-name:bg-gradient;-ms-animation-duration:5s;-ms-animation-iteration-count:infinite;-ms-animation-direction:alternate;
+/* Firefox 3.6 - 15 */-moz-animation-name:bg-gradient;-moz-animation-duration:5s;-moz-animation-iteration-count:infinite;-moz-animation-direction:alternate;
+/* Safari 5.1 - 6.0 */-webkit-animation-name:bg-gradient;-webkit-animation-duration:5s;-webkit-animation-iteration-count:infinite;-webkit-animation-direction:alternate;
+/* Opera 11.1 - 12.0 */-o-animation-name:bg-gradient;-o-animation-duration:5s;-o-animation-iteration-count:infinite;-o-animation-direction:alternate;
+}
+@keyframes bg-gradient{0%{background:#23A6D5;}100%{background: #a8eb12;}}
+@-ms-keyframes bg-gradient{0%{background:#23A6D5;}100%{background:#a8eb12;}}
+@-moz-keyframes bg-gradient{0%{background:#23A6D5;}100%{background:#a8eb12;}}
+@-webkit-keyframes bg-gradient{0%{background:#23A6D5;}100%{background:#a8eb12;}}
+@-o-keyframes bg-gradient{0%{background:#23A6D5;}100%{background:#a8eb12;}}
 
-/*other public*/
-.iconfont{font-family:'adminthemesregular';}
-.add_icon:before{content:"a";margin:0 5px;font-family:'adminthemesregular';}
-.money_icon:before{content:"$";margin:0 5px;font-family:'adminthemesregular';font-size:20px;}
-.rmb_icon{color:#19a97b;}
-.rmb_icon:before{content:"¥";margin-right:2px;}
-.ellipsis{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;}
-.center{text-align:center;}
-.fl{float:left;}
-.fr{float:right;}
-.mtb{margin:5px 0;overflow:hidden;}
-.mlr{margin:0 5px;overflow:hidden;}
+input{color:inherit;font:inherit;margin:0}
+input[type=button]{-webkit-appearance:button;cursor:pointer}
 .admin_login{width:300px;height: 200px;overflow:hidden;margin:12% auto;padding:30px;box-shadow: 0 0 10px #6b5e5e;border-radius:5px;background-color: #f7f7f7;}
 .admin_login dt{font-size:20px;font-weight:bold;text-align:center;color:#63d2bc;margin-bottom:15px;}
-.admin_login dt strong{display:block;}
-.admin_login dt em{display:block;font-size:12px;margin-top:8px;}
 .admin_login dd{margin:5px 0;height:42px;overflow:hidden;position:relative;}
-.admin_login dd .login_txtbx{border-radius: 5px;height: 25px;padding: 6px 4%;width: 91%;border: 1px solid #cad2db;background: #fff;color: #717171;}
-.admin_login dd .login_txtbx::-webkit-input-placeholder {color:#717171;line-height:inherit;} 
-.admin_login dd .login_txtbx:-moz-placeholder {color:#717171;line-height:inherit;} 
-.admin_login dd .login_txtbx::-moz-placeholder {color:#717171;line-height:inherit;}
-.admin_login dd .login_txtbx:focus{border-color: #66afe9;outline: 0;-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);}
-.admin_login dd:before{font-family:'adminthemesregular';position:absolute;top:0;left:10px;height:42px;line-height:42px;font-size:20px;color:#0c9076;}
-/*.admin_login dd.user_icon:before{content:"帐号";font-size:14px;}
-.admin_login dd.pwd_icon:before{content:"密码";font-size:14px;}*/
-.admin_login dd.val_icon:before{content:"n";}
-.admin_login dd .ver_btn{text-align:right;border:none;color:#f4f4f4;height:42px;line-height:42px;margin:0;z-index:1;position:relative;float:right;background:#48bca5;}
-.admin_login dd .checkcode{float:left;width:182px;height:42px;background:#fff}
-.admin_login dd .checkcode input{width:120px;height:36px;line-height:36px;padding:3px;color:white;outline:none;border:none;text-indent:2.8em;}
-.admin_login dd .checkcode canvas{width:85px;height:36px;padding:3px;z-index:0;background:#5cbdaa;}
 .admin_login dd .submit_btn{width:100%;height:42px;border:none;font-size:16px;background:#048f74;color:#f8f8f8;}
-.admin_login dd .submit_btn:hover{background:#0c9076;color:#f4f4f4;}
-.admin_login dd p{color:#53c6b0;font-size:12px;text-align:center;margin:5px 0;}
+.admin_login dd .submit_btn:hover{background:#048f74b0;color:#f4f4f4;transition:0.8s;}
 
-/*header*/
-header{background:#19a97b;overflow:hidden;}
-header h1{margin:0;float:left;margin-left:1%;}
-header h1 img{width:auto;max-width:300px;height:70px;}
-header .rt_nav{float:right;overflow:hidden;margin-right:3%;margin-top:12px;}
-header .rt_nav li{float:left;padding:0 25px;text-align:center;border-right:1px #139667 solid;}
-header .rt_nav li:last-child{border:none;}
-header .rt_nav li a{color:white;font-size:12px;text-shadow:0 0 1px #20af83;display:block;}
-header .rt_nav li a:hover{color:#f4f4f4;}
-header .rt_nav li a:hover:before{color:#f4f4f4;}
-header .rt_nav li a:before{font-family:'adminthemesregular';color:white;font-size:30px;display:block;}
-header .rt_nav li .website_icon:before{content:"I";}
-header .rt_nav li .admin_icon:before{content:"U";}
-header .rt_nav li .clear_icon:before{content:"C";}
-header .rt_nav li .set_icon:before{content:"S";}
-header .rt_nav li .quit_icon:before{content:"Q";}
-/*aside nav*/
-.lt_aside_nav{width:210px;height:100%;position:absolute;top:70px;left:0;background:#fcfcfc;}
-.lt_aside_nav h2{text-align:center;border-bottom:1px #b6b6b6 solid;margin:0;height:45px;line-height:45px;background:#efefef;}
-.lt_aside_nav h2 a{display:block;color:#333333;font-size:14px;text-shadow:0 0 2px white;}
-.lt_aside_nav ul{margin-bottom:75px;}
-.lt_aside_nav dl{margin:0;}
-.lt_aside_nav dl dt{font-weight:bold;height:45px;line-height:45px;border-bottom:1px #e9e9e9 solid;padding:0 15px;position:relative;}
-.lt_aside_nav dl dt:before{position:absolute;width:5px;height:25px;background:#67c1a5;content:"";top:10px;left:0;}
-.lt_aside_nav dl dd{margin:0;height:40px;line-height:40px;border-bottom:1px #e9e9e9 dotted;}
-.lt_aside_nav dl dd a{display:block;color:#555555;padding:0 15px;}
-.lt_aside_nav dl dd a:hover{background:#f8f8f8;text-shadow:0 1px 5px #f4f4f4;color:#19a97b;}
-.lt_aside_nav dl dd .active{background:#f8f8f8;color:#19a97b;}
-.lt_aside_nav dl dd .active:after{content:">";font-family:'adminthemesregular';position:absolute;right:3%;color:#19a97b;}
-.lt_aside_nav .btm_infor{height:35px;line-height:35px;width:100%;background:#efefef;border-top:1px #b6b6b6 solid;text-align:center;color:#aaa;}
-/*public:rtContent*/
-.rt_wrap{margin-left:218px;margin-right:10px;height:100%;position:relative;}
-.rt_content{margin-bottom:80px;margin-right:8px;overflow:hidden;}
-.textWhite{color:white;}
-.link_btn{border:1px #139667 solid;border-radius:2px;background:#19a97b;color:white;padding:8px 15px;display:inline-block;cursor:pointer;}
-.link_btn:hover{background:#11a274;border:1px #0e8f61 solid;}
-.link_btn:active{background:#0c9c6e;border:1px #0e8f61 solid;}
-.textbox{border:1px #139667 solid;height:26px;line-height:26px;padding:5px;font-size:12px; vertical-align:middle;}
-.textbox_295{width:295px;}
-.textbox_225{width:225px;}
-.select{padding:0 5px;height:38px;font-size:12px;border:1px #139667 solid;vertical-align:middle; appearance: button;-webkit-appearance:button;}
-.group_btn{border:1px #139667 solid;background:#19a97b;color:white;padding:0 15px;height:38px;cursor:pointer;display:inline-block;vertical-align:middle;}
-.group_btn:hover{background:#11a274;border:1px #0e8f61 solid;}
-.group_btn:active{background:#0c9c6e;border:1px #0e8f61 solid;}
-.page_title{height:40px;line-height:40px;border-bottom:1px #b6b6b6 solid;margin:10px 0;}
-.page_title h2{font-size:15px;font-weight:bold;}
-.page_title .top_rt_btn{display:inline-block;height:30px;line-height:30px;padding:0 15px;border:1px #d2d2d2 solid;background:#f8f8f8;color:#19a97b; vertical-align:middle;cursor:pointer;}
-.table{width:100%;table-layout:fixed;margin:5px 0;}
-.table th{border:1px #d2d2d2 solid;height:40px;line-height:40px;}
-.table td{border:1px #d2d2d2 solid;padding:10px 8px;position:relative;}
-.table td p{margin:5px 0;line-height:1.3;}
-.table td mark{color:red;line-height:1.3;}
-.table tr:nth-child(odd){background:#f8f8f8;}
-.table tr:hover{background:#f9f9f9;}
-.table td a{color:#19a97b;margin:0 5px;cursor:pointer;}
-.table td .full_link_td{display:block;width:100%;height:100%;border:none;outline:none;position:absolute;top:0;left:0;text-align:center;margin:0;font-size:20px;font-weight:bold;}
-.table td .full_link_td:hover{background:#f4f4f4;color:#019163;}
-.table td .inner_btn{background:#F9F;color:white;padding:5px 8px;border-radius:2px;}
-.table td .inner_btn:hover{background:#ffa4ff;color:#f8f8f8;}
-.table td .cut_title{width:265px;}
-.table td .link_icon{font-size:24px;font-family:'adminthemesregular';color:#19a97b;}
-.table td .link_icon:hover{color:#019163;}
-.paging{margin:8px 0;overflow:hidden;text-align:right;}
-.paging a{background:#19a97b;border:1px #139667 solid;color:white;padding:5px 8px;display:inline-block;cursor:pointer;}
-.paging a:hover{background:#11a274;border:1px #0e8f61 solid;}
-.paging a:active{background:#17a578;border:1px #0e8f61 solid;}
-.single_selection{color:#333;padding:6px 8px;display:inline-block;vertical-align:middle;}
-.single_selection input{margin-right:3px;vertical-align:middle;}
-.errorTips{color:red;margin:0 8px;}
-.errorTips:before{content:"x";font-family:'adminthemesregular';margin-right:3px;font-size:16px;}
-.textarea{display:inline-block;margin-top:5px;outline:none;resize:none;border:1px #139667 solid;padding:8px;}
-.uploadImg{display:inline-block;padding:15px;background:#f8f8f8;position:relative;border:1px #139667 solid;}
-.uploadImg input{display:none;}
-.uploadImg span{display:block;font-size:12px;text-align:center;color:#139667;}
-.uploadImg span:hover{color:#209f71;}
-.uploadImg span:before{content:"#";font-family:'adminthemesregular';display:block;font-size:40px;}
-.ulColumn2{overflow:hidden;}
-.ulColumn2 li{margin:15px 0;}
-.ulColumn2 li .item_name{text-align:right;display:inline-block;}
-/*TAB*/
-.admin_tab{background:#f8f8f8;overflow:hidden;border:1px #d2d2d2 solid;margin-bottom:8px;}
-.admin_tab li{float:left;height:40px;line-height:40px;border-right:1px #f2f2f2 solid;}
-.admin_tab li:last-child{border:none;}
-.admin_tab li a{display:block;padding:0 20px;color:grey;font-size:12px;cursor:pointer;}
-.admin_tab li a.active{background:white;font-weight:bold;border-top:1px #19a97b solid;color:#19a97b;}
-.admin_tab_cont{display:none;margin:5px 0;overflow:hidden;}
-.cont_col_lt{width:300px;overflow:hidden;float:left;}
-.cont_col_rt{margin-left:315px;overflow:hidden;}
-/*pop*/
-.pop_bg{display:none;background:rgba(0,0,0,.35);width:100%;height:100%;position:fixed;top:0;left:0;z-index:999;}
-.pop_cont{background:white;min-width:300px;height:auto;overflow:hidden;position:absolute;top:20%;left:50%;margin-left:-150px;border-radius:5px 5px 0 0;}
-.pop_cont h3{height:40px;line-height:40px;background:#19a97b;color:white;font-size:14px;font-weight:bold;margin:0;padding:0 1em;}
-.pop_cont h3:before{content:"*";font-family:'adminthemesregular';margin-right:2px;font-size:20px;font-weight:normal;}
-.pop_cont .pop_cont_text{padding:10px;line-height:1.3;color:grey;}
-.pop_cont .pop_cont_input{padding:10px;text-align:center;}
-.pop_cont .pop_cont_input li{margin:5px 0;text-align:left;overflow:hidden;}
-.pop_cont .pop_cont_input li .ttl{display:inline-block;}
-.pop_cont .pop_cont_input li .textbox{border:1px #d2d2d2 solid;width:200px;display:inline-block;}
-.pop_cont .pop_cont_input li .select{border:1px #d2d2d2 solid;}
-.pop_cont .pop_cont_input li .textarea{border:1px #d2d2d2 solid;}
-.pop_cont .btm_btn{padding:10px 0;text-align:center;}
-.pop_cont .btm_btn .input_btn{display:inline-block;height:35px;border:none;background:none;padding:0 20px;}
-.pop_cont .btm_btn .trueBtn{background:#19a97b;color:white;border:1px #19a97b solid;border-radius:2px;}
-.pop_cont .btm_btn .trueBtn:hover{background:#13a174;border-radius:0;border:1px #13a174 solid;}
-.pop_cont .btm_btn .falseBtn{background:#fafafa;color:grey;border:1px #d2d2d2 solid;border-radius:2px;}
-.pop_cont .btm_btn .falseBtn:hover,.pop_cont .btm_btn .input_btn_02:active{background:#f0f0f0;border-radius:0;color:#818181;text-shadow:0 1px 1px white;}
-/*loading*/
-.loading_area{display:none;background:rgba(255,255,255,.85);position:fixed;left:0;top:0;width:100%;height:100%;text-align:center;z-index:999;}
-.loading_cont{overflow:hidden;margin-top:20%;}
-@-webkit-keyframes loading_icon{0%{transform:scaleY(1);-moz-transform:scaleY(1);-webkit-transform:scaleY(1)}
-50%{transform:scaleY(.4);-moz-transform:scaleY(.4);-webkit-transform:scaleY(.4)}
-100%{transform:scaleY(1);-moz-transform:scaleY(1);-webkit-transform:scaleY(1)}
-}
-@-moz-keyframes loading_icon{0%{transform:scaleY(1);-moz-transform:scaleY(1);-webkit-transform:scaleY(1)}
-50%{transform:scaleY(.4);-moz-transform:scaleY(.4);-webkit-transform:scaleY(.4)}
-100%{transform:scaleY(1);-moz-transform:scaleY(1);-webkit-transform:scaleY(1)}
-}
-.loading_icon i{display:inline-block;width:4px;height:20px;border-radius:2px;background:#19a97b;margin:0 2px}
-.loading_icon i:nth-child(1){-webkit-animation:loading_icon 1s ease-in .1s infinite;-moz-animation:loading_icon 1s ease-in .1s infinite;animation:loading_icon 1s ease-in .1s infinite}
-.loading_icon i:nth-child(2){-webkit-animation:loading_icon 1s ease-in .2s infinite;-moz-animation:loading_icon 1s ease-in .2s infinite;animation:loading_icon 1s ease-in .2s infinite}
-.loading_icon i:nth-child(3){-webkit-animation:loading_icon 1s ease-in .3s infinite;-moz-animation:loading_icon 1s ease-in .3s infinite;animation:loading_icon 1s ease-in .3s infinite}
-.loading_icon i:nth-child(4){-webkit-animation:loading_icon 1s ease-in .4s infinite;-moz-animation:loading_icon 1s ease-in .4s infinite;animation:loading_icon 1s ease-in .4s infinite}
-.loading_icon i:nth-child(5){-webkit-animation:loading_icon 1s ease-in .5s infinite;-moz-animation:loading_icon 1s ease-in .5s infinite;animation:loading_icon 1s ease-in .5s infinite}
-.loading_txt mark{background:none;font-size:12px;color:red;}
-/*statistic*/
-.dataStatistic{width:700px;height:400px;border:1px solid #ccc;margin:0 auto;margin-top:100px;overflow:hidden}
-#cylindrical{width:700px;height:400px;margin-top:-15px}
-#line{width:700px;height:400px;margin-top:-15px}
-#pie{width:700px;height:400px;margin-top:-15px}
-body { background: -webkit-linear-gradient(left top,rgba(197, 136, 86, 0.26) , rgba(154, 154, 204, 0.75)););
-    /* Safari 5.1 - 6.0 */ background: -o-linear-gradient(bottom right,rgba(197, 136, 86, 0.26) , rgba(154, 154, 204, 0.75)););
-    /* Opera 11.1 - 12.0 */background: -moz-linear-gradient(bottom right, rgba(197, 136, 86, 0.26) , rgba(154, 154, 204, 0.75)););
-    /* Firefox 3.6 - 15 */background: linear-gradient(to bottom right,rgba(197, 136, 86, 0.26), rgba(154, 154, 204, 0.75)););
-    /* 标准的语法 */height: 100%;overflow: hidden;}
-canvas {z-index: -1;position: absolute;}
 /*登录输入框错误高亮样式*/
-.loginVerifcateError{padding: 9px 4%;width: 91%;background: #fff;color:#717171;border: 1px solid #b94a48;border-radius: 5px;-webkit-box-shadow: inset 0 1px 1px rgba(95, 46, 46, 0.075), 0 0 8px rgba(233, 102, 150, 0.6);box-shadow: inset 0 1px 1px rgba(204, 53, 53, 0.075), 0 0 8px rgba(214, 80, 86, 0.6);}
-.loginVerifcateTextTip{width: 300px;height: 15px;font-size: 16px;color: green;}
-.loginVerifcateTextError{width: 300px;height: 15px;font-size: 16px;color: #e43f3c;}
+.loginTextTip{width: 300px;height: 15px;font-size: 16px;color: green;}
+.loginTextTipError{width: 300px;height: 15px;font-size: 16px;color: #e43f3c;}
+.loginInput{border-radius: 5px;height: 25px;padding: 6px 4%;width: 91%;border: 1px solid #cad2db;background: #fff;color: #717171;}
+.loginInput:focus{border-color: #66afe9;outline: 0;-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);}
+.loginInputError{padding: 9px 4%;width: 91%;background: #fff;color:#717171;border-radius: 5px;-webkit-box-shadow: inset 0 1px 1px rgba(95, 46, 46, 0.075), 0 0 8px rgba(233, 102, 150, 0.6);box-shadow: inset 0 1px 1px rgba(204, 53, 53, 0.075), 0 0 8px rgba(214, 80, 86, 0.6);}
 .footerContainer{width:100%;position:fixed;bottom:0;}

+ 11 - 0
dbsyncer-web/src/main/resources/static/js/common.js

@@ -18,6 +18,17 @@ function bootGrowl(data, type) {
     });
 }
 
+// 刷新登录用户信息
+function refreshLoginUser() {
+    // 获取登录用户信息
+    doGetter("/user/getUserInfo.json", {}, function (data) {
+        if (data.success == true) {
+            $("#currentUser").html(data.resultValue.nickname + " (" + data.resultValue.roleName + ")");
+            $("#edit_personal").attr("username", data.resultValue.username);
+        }
+    });
+}
+
 // 跳转主页
 function backIndexPage(projectGroupId) {
     // 加载页面

+ 7 - 0
dbsyncer-web/src/main/resources/static/js/index.js

@@ -1,6 +1,8 @@
 // ******************* 初始化 *****************************
 // 默认绑定菜单事件
 $(function () {
+    // 刷新登录用户
+    refreshLoginUser();
 
     // 初始化版权信息
     doGetter("/index/version.json",{}, function (data) {
@@ -10,6 +12,11 @@ $(function () {
         }
     });
 
+    // 修改登录用户
+    $("#edit_personal").click(function () {
+        doLoader("/user/page/edit?username=" + $(this).attr("username"));
+    });
+
     // 注销
     $("#nav_logout").click(function () {
         // 确认框确认是否注销

+ 6 - 10
dbsyncer-web/src/main/resources/static/js/login/login.js

@@ -47,7 +47,7 @@ function showResponse($form, data) {
         location.href = $basePath;
     } else {
         // 请求失败
-        $form.find("#loginTip").removeClass("loginVerifcateTextTip").addClass("loginVerifcateTextError").html(data.resultValue);
+        $form.find("#loginTip").removeClass("loginTextTip").addClass("loginTextTipError").html(data.resultValue);
         //用户名密码错误清空输入框
         $form.find('input:eq(0)').val("");
         $form.find('input:eq(1)').val("");
@@ -59,7 +59,7 @@ function login($form) {
     var username = $form.find('input[name="username"]').val();
     var password = $form.find('input[name="password"]').val();
     if (username != "" && password != "") {
-        $form.find("#loginTip").removeClass("loginVerifcateTextError").addClass("loginVerifcateTextTip").html("登录中...");
+        $form.find("#loginTip").removeClass("loginTextTipError").addClass("loginTextTip").html("登录中...");
         $form.find("input").attr("disabled", "disabled");
         // 点击确定确认登录请求后台
         $.post($basePath + "/login", {"username": username, "password": password}, function (data) {
@@ -78,20 +78,16 @@ function login($form) {
     // 对登录表单进行非空校验
     $form.find("input.required").each(function () {
         if ($(this).val() != "") {
-            $(this).removeClass("loginVerifcateError");
-            $(this).addClass("login_txtbx");
+            $(this).removeClass("loginInputError").addClass("loginInput");
             return;
         }
-        $(this).removeClass("login_txtbx");
-        $(this).addClass("loginVerifcateError");
+        $(this).removeClass("loginInput").addClass("loginInputError");
     });
     // 触发 keyup 事件
     $form.find("input.required").keyup(function () {
-        $(this).removeClass("loginVerifcateError");
-        $(this).addClass("login_txtbx");
+        $(this).removeClass("loginInputError").addClass("loginInput");
         if ($(this).val() == "") {
-            $(this).removeClass("login_txtbx");
-            $(this).addClass("loginVerifcateError");
+            $(this).removeClass("loginInput").addClass("loginInputError");
         }
     });
 }

+ 0 - 24
dbsyncer-web/src/main/resources/static/js/pwd/index.js

@@ -1,24 +0,0 @@
-function submit(data) {
-    doPoster('/pwd/edit', data, function (data) {
-        if (data.success == true) {
-            doPoster("/logout", null, function (data) {
-                location.href = $basePath;
-            });
-        } else {
-            bootGrowl(data.resultValue, "danger");
-            doLoader("/pwd");
-        }
-    });
-}
-
-$(function () {
-    //保存
-    $("#updatePwdSubBtn").click(function () {
-        var $form = $("#configEditForm");
-        if ($form.formValidate() == true) {
-            var data = $form.serializeJson();
-            submit(data);
-        }
-    });
-
-})

+ 43 - 0
dbsyncer-web/src/main/resources/static/js/user/index.js

@@ -0,0 +1,43 @@
+$(function () {
+    // 绑定添加用户按钮事件
+    $("#addUserBtn").click(function () {
+        doLoader("/user/page/add");
+    });
+
+    // 绑定修改用户按钮事件
+    $(".editUserBtn").click(function () {
+        doLoader("/user/page/edit?username=" + $(this).attr("id"));
+    });
+
+    // 绑定删除用户按钮事件
+    $(".removeUserBtn").click(function () {
+        const $username = $(this).attr("id");
+        // 确认框确认是否删除用户
+        BootstrapDialog.show({
+            title: "提示",
+            type: BootstrapDialog.TYPE_INFO,
+            message: "确认删除帐号?",
+            size: BootstrapDialog.SIZE_NORMAL,
+            buttons: [{
+                label: "确定",
+                action: function (dialog) {
+                    doPoster('/user/remove', {username: $username}, function (data) {
+                        if (data.success == true) {
+                            bootGrowl("删除用户成功!", "success");
+                        } else {
+                            bootGrowl(data.resultValue, "danger");
+                        }
+                        doLoader("/user?refresh=" + new Date().getTime());
+                    });
+                    dialog.close();
+                }
+            }, {
+                label: "取消",
+                action: function (dialog) {
+                    dialog.close();
+                }
+            }]
+        });
+    });
+
+})