Jelajahi Sumber

reset computer

CJ 1 tahun lalu
induk
melakukan
c4971cd454
60 mengubah file dengan 1445 tambahan dan 2723 penghapusan
  1. 39 0
      dtok-api/.idea/inspectionProfiles/Project_Default.xml
  2. 1 1
      dtok-api/api/src/main/java/com/dtok/api/ApiApplication.java
  3. 147 0
      dtok-api/api/src/main/java/com/dtok/api/AppApi.java
  4. 6 6
      dtok-api/api/src/main/java/com/dtok/api/controller/CommonItemController.java
  5. 125 0
      dtok-api/api/src/main/java/com/dtok/api/controller/DeviceController.java
  6. 36 10
      dtok-api/api/src/main/java/com/dtok/api/controller/LoginController.java
  7. 45 17
      dtok-api/api/src/main/java/com/dtok/api/controller/ScriptController.java
  8. 11 6
      dtok-api/api/src/main/java/com/dtok/api/controller/UserController.java
  9. 1 1
      dtok-api/entity/src/main/java/com/dtok/entity/Account.java
  10. 10 4
      dtok-api/entity/src/main/java/com/dtok/entity/CommonItem.java
  11. 12 0
      dtok-api/entity/src/main/java/com/dtok/entity/Devices.java
  12. 4 4
      dtok-api/entity/src/main/java/com/dtok/entity/Script.java
  13. 7 4
      dtok-api/entity/src/main/java/com/dtok/entity/ScriptHistory.java
  14. 17 0
      dtok-api/entity/src/main/java/com/dtok/entity/jedisvo/LoginItem.java
  15. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/Account.class
  16. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/CommonItem.class
  17. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/Devices.class
  18. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/Script.class
  19. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/ScriptHistory.class
  20. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/jedisvo/LoginItem.class
  21. TEMPAT SAMPAH
      dtok-api/entity/target/classes/com/dtok/entity/params/ScriptFormData.class
  22. 1 2
      dtok-api/framework/pom.xml
  23. 3 2
      dtok-api/framework/src/main/java/com/dtok/framework/authenticate/StpInterfaceImpl.java
  24. 27 32
      dtok-api/framework/src/main/java/com/dtok/framework/configure/SaTokenConfigure.java
  25. 2 11
      dtok-api/framework/src/main/java/com/dtok/framework/configure/WebConfigurer.java
  26. 3 1
      dtok-api/framework/src/main/java/com/dtok/framework/exception/BizExceptionEnum.java
  27. 27 26
      dtok-api/framework/src/main/java/com/dtok/framework/listener/MySaTokenListener.java
  28. 24 2300
      dtok-api/framework/src/main/java/com/dtok/framework/util/RedisUtil.java
  29. 4 4
      dtok-api/framework/src/main/resources/application.properties
  30. 4 4
      dtok-api/framework/target/classes/application.properties
  31. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/authenticate/StpInterfaceImpl.class
  32. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/configure/SaTokenConfigure.class
  33. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/configure/WebConfigurer.class
  34. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/configure/WebSocketConfig.class
  35. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/exception/BizExceptionEnum.class
  36. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/listener/MySaTokenListener.class
  37. TEMPAT SAMPAH
      dtok-api/framework/target/classes/com/dtok/framework/util/RedisUtil.class
  38. 6 6
      dtok-api/pom.xml
  39. 11 3
      dtok-api/repository/src/main/java/com/dtok/repository/AccountRepository.java
  40. 5 0
      dtok-api/repository/src/main/java/com/dtok/repository/CommonItemRepository.java
  41. 19 4
      dtok-api/repository/src/main/java/com/dtok/repository/DevicesRepository.java
  42. 5 0
      dtok-api/repository/src/main/java/com/dtok/repository/ScriptHistoryRepository.java
  43. 7 4
      dtok-api/repository/src/main/java/com/dtok/repository/ScriptRepository.java
  44. TEMPAT SAMPAH
      dtok-api/repository/target/classes/com/dtok/repository/AccountRepository.class
  45. TEMPAT SAMPAH
      dtok-api/repository/target/classes/com/dtok/repository/CommonItemRepository.class
  46. TEMPAT SAMPAH
      dtok-api/repository/target/classes/com/dtok/repository/DevicesRepository.class
  47. TEMPAT SAMPAH
      dtok-api/repository/target/classes/com/dtok/repository/ScriptHistoryRepository.class
  48. TEMPAT SAMPAH
      dtok-api/repository/target/classes/com/dtok/repository/ScriptRepository.class
  49. TEMPAT SAMPAH
      dtok-app/dtok-final/back.png
  50. TEMPAT SAMPAH
      dtok-app/dtok-final/close.png
  51. 3 0
      dtok-app/dtok-final/common/ScriptConf.js
  52. 316 0
      dtok-app/dtok-final/floatywindow.js
  53. TEMPAT SAMPAH
      dtok-app/dtok-final/logo.png
  54. 298 0
      dtok-app/dtok-final/main.js
  55. 37 0
      dtok-app/dtok-final/project.json
  56. TEMPAT SAMPAH
      dtok-app/dtok-final/resume.png
  57. TEMPAT SAMPAH
      dtok-app/dtok-final/start.png
  58. 1 0
      dtok-app/dtok-final/test.js
  59. TEMPAT SAMPAH
      dtok-app/dtok-final/test.png
  60. 181 271
      dtok-app/dtok/demo.js

+ 39 - 0
dtok-api/.idea/inspectionProfiles/Project_Default.xml

@@ -1,6 +1,9 @@
 <component name="InspectionProjectProfileManager">
   <profile version="1.0">
     <option name="myName" value="Project Default" />
+    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,cn.hutool.db.nosql.redis.RedisDS,create" />
+    </inspection_tool>
     <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="TOP_LEVEL_CLASS_OPTIONS">
         <value>
@@ -32,5 +35,41 @@
       <option name="IGNORE_POINT_TO_ITSELF" value="false" />
       <option name="myAdditionalJavadocTags" value="Description,Author,Date" />
     </inspection_tool>
+    <inspection_tool class="JavadocDeclaration" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ADDITIONAL_TAGS" value="Description,Author,Date" />
+    </inspection_tool>
+    <inspection_tool class="MissingJavadoc" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="PACKAGE_SETTINGS">
+        <Options>
+          <option name="ENABLED" value="false" />
+        </Options>
+      </option>
+      <option name="MODULE_SETTINGS">
+        <Options>
+          <option name="ENABLED" value="false" />
+        </Options>
+      </option>
+      <option name="TOP_LEVEL_CLASS_SETTINGS">
+        <Options>
+          <option name="ENABLED" value="false" />
+        </Options>
+      </option>
+      <option name="INNER_CLASS_SETTINGS">
+        <Options>
+          <option name="ENABLED" value="false" />
+        </Options>
+      </option>
+      <option name="METHOD_SETTINGS">
+        <Options>
+          <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+          <option name="ENABLED" value="false" />
+        </Options>
+      </option>
+      <option name="FIELD_SETTINGS">
+        <Options>
+          <option name="ENABLED" value="false" />
+        </Options>
+      </option>
+    </inspection_tool>
   </profile>
 </component>

+ 1 - 1
dtok-api/api/src/main/java/com/dtok/api/ApiApplication.java

@@ -8,7 +8,7 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 
-@ComponentScan(basePackages = {"com.dtok.framework", "com.dtok.api.controller", "com.dtok.framework.configure",
+@ComponentScan(basePackages = {"com.dtok.framework", "com.dtok.api", "com.dtok.framework.configure",
         "com.dtok.framework.listener",  "com.dtok.framework.authenticate","com.dtok.service"})
 @EnableJpaRepositories(basePackages = {"com.dtok.repository"})
 @EntityScan(basePackages = {"com.dtok.entity"})

+ 147 - 0
dtok-api/api/src/main/java/com/dtok/api/AppApi.java

@@ -0,0 +1,147 @@
+package com.dtok.api;
+
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.dtok.entity.Account;
+import com.dtok.entity.CommonItem;
+import com.dtok.entity.Devices;
+import com.dtok.entity.Script;
+import com.dtok.framework.exception.AuthenticateException;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.exception.BusinessException;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.repository.AccountRepository;
+import com.dtok.repository.CommonItemRepository;
+import com.dtok.repository.DevicesRepository;
+import com.dtok.repository.ScriptRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api")
+public class AppApi {
+
+    @Autowired
+    DevicesRepository devicesRepository;
+
+    @Autowired
+    AccountRepository accountRepository;
+
+    @Autowired
+    CommonItemRepository commonItemRepository;
+
+
+    @Autowired
+    ScriptRepository scriptRepository;
+
+    @GetMapping("/checkRegister/{token}/{androidId}")
+    public ResponseData checkRegister(@PathVariable String token, @PathVariable String androidId) {
+        String username = (String) StpUtil.getLoginIdByToken(token);
+
+        if (!StpUtil.getTokenValue().equals(token)) {
+            throw new AuthenticateException(401, "非法注册");
+        }
+        if (!StringUtils.hasLength(username)) {
+            throw new AuthenticateException(401, "登录信息失效");
+        }
+
+        Account account = accountRepository.findUserByUsername(username);
+
+        Devices devices = devicesRepository.findFirstByAccountAndAndroidId(account.getId(), androidId);
+
+        if (Objects.isNull(devices)) {
+            throw new BusinessException(BizExceptionEnum.DEVICE_NOT_REGISTER);
+        } else {
+            return ResponseData.success(devices);
+        }
+    }
+
+
+    @GetMapping("/getCommonItem")
+    public ResponseData getCommonItem(@RequestParam(defaultValue = "com.ss.android.ugc.aweme", required = false,
+            value = "app") String app) {
+        Account account = ((Account) StpUtil.getSession().get("loginUser"));
+
+        List<CommonItem> commonItemList = commonItemRepository.findAllByAppAndIsDefaultOrCreatedAt(app, true, account.getId());
+        Map<String, List<CommonItem>> resultMap = commonItemList.stream().collect(
+                Collectors.groupingBy(CommonItem::getType));
+        return ResponseData.success(resultMap);
+    }
+
+
+    @GetMapping("/checkLogin")
+    public ResponseData checkLogin() {
+//        Account account = ((Account) StpUtil.getSession().get("loginUser"));
+        Account account = accountRepository.findUserByUsername((String) StpUtil.getLoginId());
+
+        Timestamp timestamp = new Timestamp((new Date()).getTime());
+        if (!Objects.isNull(account.getExpireAt()) && account.getExpireAt().before(timestamp)) {
+            StpUtil.logoutByTokenValue(StpUtil.getTokenValue());
+            throw new AuthenticateException(BizExceptionEnum.ACCOUNT_EXPIRE);
+        }
+
+        return ResponseData.success(accountRepository.getFirstByUsername((String) StpUtil.getLoginId()));
+    }
+
+    @PostMapping("/addCommonItem")
+    public ResponseData addCommonItem(@RequestParam(defaultValue = "com.ss.android.ugc.aweme", required = false,
+            value = "app") String app, @RequestParam("type") String type, @RequestParam("content") String content) {
+        CommonItem commonItem = new CommonItem();
+        commonItem.setApp(app);
+        commonItem.setCreatedTime(new Date());
+        commonItem.setContent(content);
+        commonItem.setType(type);
+        commonItem.setCreatedAt(((Account) StpUtil.getSession().get("loginUser")).getId());
+        commonItem.setIsDefault(false);
+        commonItemRepository.save(commonItem);
+
+        return ResponseData.success("添加成功");
+    }
+
+
+    @PostMapping("/getExecScript/{uuid}")
+    public ResponseData getExecScript(@RequestParam(defaultValue = "com.ss.android.ugc.aweme", required = false,
+            value = "app") String app, @RequestParam("module") String module, @PathVariable String uuid) {
+        Account account = accountRepository.getUserLoginEntity((String) StpUtil.getLoginId());
+
+        if (!StringUtils.hasLength(uuid)) {
+            throw new NullPointerException("没有找到设备");
+        }
+
+        if (!StringUtils.hasLength(module)) {
+            throw new NullPointerException("没有此功能");
+        }
+
+        Devices devices = devicesRepository.findFirstByUuid(uuid);
+
+        Timestamp timestamp = new Timestamp((new Date()).getTime());
+        if (!Objects.isNull(account.getExpireAt()) && account.getExpireAt().before(timestamp)) {
+            StpUtil.logoutByTokenValue(StpUtil.getTokenValue());
+            throw new AuthenticateException(BizExceptionEnum.ACCOUNT_EXPIRE);
+        }
+
+        if (!account.getId().equals(devices.getAccount())) {
+            throw new NullPointerException("权限错误");
+        }
+
+        Script script = scriptRepository.findFirstByModuleAndApp(module, app);
+
+        if (Objects.isNull(script)) {
+            throw new NullPointerException("没有此功能");
+        }
+        script.setCallCount(script.getCallCount() + 1);
+        scriptRepository.save(script);
+
+        return ResponseData.success(script);
+    }
+
+
+}

+ 6 - 6
dtok-api/api/src/main/java/com/dtok/api/controller/CommonItemController.java

@@ -42,7 +42,7 @@ public class CommonItemController {
             }
             predicate.getExpressions().add(criteriaBuilder.and(criteriaBuilder.equal(root.get("isDefault"), true)));
 
-            predicate.getExpressions().add(criteriaBuilder.and(criteriaBuilder.equal(root.get("createdAt"), ((Account) StpUtil.getLoginId()).getId())));
+            predicate.getExpressions().add(criteriaBuilder.and(criteriaBuilder.equal(root.get("createdAt"), ((Account) StpUtil.getSession().get("loginUser")).getId())));
 
             return predicate;
         };
@@ -59,11 +59,11 @@ public class CommonItemController {
         if (!StringUtils.hasLength(commonItem.getContent()) || !StringUtils.hasLength(commonItem.getApp()) || !StringUtils.hasLength(commonItem.getType())) {
             throw new NullPointerException("属性缺省");
         }
-        if (!((Account) StpUtil.getLoginId()).getIsSuper() && commonItem.getIsDefault()) {
+        if (!((Account) StpUtil.getSession().get("loginUser")).getIsSuper() && commonItem.getIsDefault()) {
             throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
         }
 
-        commonItem.setCreatedAt(((Account) StpUtil.getLoginId()).getId());
+        commonItem.setCreatedAt(((Account) StpUtil.getSession().get("loginUser")).getId());
         commonItem.setCreatedTime(new Date());
         commonItemRepository.save(commonItem);
         return ResponseData.success("添加成功");
@@ -81,12 +81,12 @@ public class CommonItemController {
         if (!StringUtils.hasLength(commonItem.getContent()) || !StringUtils.hasLength(commonItem.getApp()) || !StringUtils.hasLength(commonItem.getType())) {
             throw new NullPointerException("属性缺省");
         }
-        if (!((Account) StpUtil.getLoginId()).getIsSuper() && commonItem.getIsDefault()) {
+        if (!((Account) StpUtil.getSession().get("loginUser")).getIsSuper() && commonItem.getIsDefault()) {
             throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
         }
 
         commonItem.setId(Long.valueOf(id));
-        commonItem.setCreatedAt(((Account) StpUtil.getLoginId()).getId());
+        commonItem.setCreatedAt(((Account) StpUtil.getSession().get("loginUser")).getId());
         commonItem.setCreatedTime(new Date());
         commonItemRepository.save(commonItem);
         return ResponseData.success("添加成功");
@@ -107,7 +107,7 @@ public class CommonItemController {
 
         CommonItem commonItemAlready = commonItemRepository.getOne(String.valueOf(id));
 
-        if (!((Account) StpUtil.getLoginId()).getIsSuper() && commonItemAlready.getIsDefault()) {
+        if (!((Account) StpUtil.getSession().get("loginUser")).getIsSuper() && commonItemAlready.getIsDefault()) {
             throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
         }
 

+ 125 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/DeviceController.java

@@ -0,0 +1,125 @@
+package com.dtok.api.controller;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.lang.generator.UUIDGenerator;
+import com.dtok.entity.Account;
+import com.dtok.entity.Devices;
+import com.dtok.entity.Script;
+import com.dtok.framework.exception.AuthenticateException;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.IpUtil;
+import com.dtok.framework.util.ToolUtil;
+import com.dtok.repository.AccountRepository;
+import com.dtok.repository.DevicesRepository;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.persistence.criteria.Predicate;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+@RestController
+@RequestMapping("/device")
+public class DeviceController {
+
+    @Autowired
+    DevicesRepository devicesRepository;
+
+
+    @Autowired
+    AccountRepository accountRepository;
+
+    @PostMapping("/search")
+    public ResponseData search() {
+        Specification<Devices> query = (root, query1, criteriaBuilder) -> {
+
+            Predicate predicate = criteriaBuilder.conjunction();
+            Account account = ((Account) StpUtil.getSession().get("loginUser"));
+            if (!account.getIsSuper()) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("account"), account.getId())));
+            }
+            return predicate;
+        };
+        List<Devices> result = devicesRepository.findAll(query);
+        return ResponseData.success(result);
+    }
+
+    @PostMapping("/registerDevice/{token}")
+    public ResponseData registerDevice(Devices devices, @PathVariable String token) {
+        String username = (String) StpUtil.getLoginIdByToken(token);
+        if (!StpUtil.getTokenValue().equals(token)) {
+            throw new AuthenticateException(401, "非法注册");
+        }
+        if (!StringUtils.hasLength(username)) {
+            throw new AuthenticateException(401, "登录信息失效");
+        }
+        if (!StringUtils.hasLength(devices.getDeviceBrand())) {
+            throw new AuthenticateException(404, "注册信息缺失");
+        }
+        if (!StringUtils.hasLength(devices.getDeviceName())) {
+            throw new AuthenticateException(404, "注册信息缺失");
+        }
+        if (!StringUtils.hasLength(devices.getDeviceVersion())) {
+            throw new AuthenticateException(404, "注册信息缺失");
+        }
+        if (!StringUtils.hasLength(devices.getAndroidId())) {
+            throw new AuthenticateException(404, "注册信息缺失");
+        }
+
+
+        Account account = accountRepository.getUserLoginEntity(username);
+
+        List<Devices> devicesList = devicesRepository.searchAllByAccountUsername(username);
+
+        Integer alreadyRegister = devicesRepository.countByAndroidId(devices.getAndroidId());
+
+
+        if (alreadyRegister > 0) {
+            throw new AuthenticateException(403, "设备已注册,请解绑");
+        }
+
+
+        if (devicesList.stream().anyMatch(obj -> obj.getAndroidId().equals(devices.getAndroidId()))) {
+            throw new AuthenticateException(403, "设备已注册");
+        }
+
+
+        if (account.getMaxDevices() <= devicesList.size()) {
+            throw new AuthenticateException(402, "已达到最大设备数量");
+        }
+
+        devices.setUuid(new UUIDGenerator().next());
+        devices.setAccount(account.getId());
+        devices.setLastConnectionIp(IpUtil.getRequestIp());
+        devices.setLastConnectionTime(new DateTime());
+        devices.setStatus(Devices.OFFLINE);
+        devices.setRegisterAt(new Date());
+        devicesRepository.save(devices);
+
+        return ResponseData.success(devices);
+    }
+
+    @GetMapping("/unBundleDevice/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public ResponseData unBundleDevice(@PathVariable String id) {
+        if (!StringUtils.hasLength(id)) throw new NullPointerException("id参数不能为空");
+        Devices devices = devicesRepository.findFirstByUuid(id);
+        if (Objects.isNull(devices)) {
+            throw new NullPointerException("没找到设备");
+        }
+        Account account = (Account) StpUtil.getSession().get("loginUser");
+        if (!account.getId().equals(devices.getAccount())) {
+            throw new AuthenticateException(403, "不是你的设备");
+        }
+        devicesRepository.deleteDevicesByUuid(id);
+        return ResponseData.success("解绑完成");
+    }
+
+
+}

+ 36 - 10
dtok-api/api/src/main/java/com/dtok/api/controller/LoginController.java

@@ -5,6 +5,7 @@ import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.crypto.SecureUtil;
 
+import cn.hutool.db.nosql.redis.RedisDS;
 import com.dtok.entity.Account;
 import com.dtok.entity.AccountRole;
 import com.dtok.entity.LoginHistory;
@@ -12,9 +13,11 @@ import com.dtok.entity.emum.LOGIN_DEVICE;
 import com.dtok.entity.params.UserResponse;
 import com.dtok.framework.exception.AuthenticateException;
 import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.exception.BusinessException;
 import com.dtok.framework.exception.ServiceException;
 import com.dtok.framework.response.ResponseData;
 import com.dtok.framework.util.IpUtil;
+import com.dtok.framework.util.RedisUtil;
 import com.dtok.repository.AccountRepository;
 import com.dtok.repository.AccountRoleRepository;
 import com.dtok.repository.LoginHistoryRepository;
@@ -28,7 +31,9 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
+import redis.clients.jedis.Jedis;
 
+import java.sql.Timestamp;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -61,12 +66,14 @@ public class LoginController {
     }
 
 
-    @GetMapping("/login")
+    @PostMapping("/login")
     @ResponseBody
     @ApiOperation("登录")
     public ResponseData login(String username, String password, String loginDevice) {
         // get user
-        Account user = userRepository.getFirstByUsername(username);
+        Account user = userRepository.getUserLoginEntity(username);
+
+
         if (Objects.isNull(user)) {
             throw new AuthenticateException(BizExceptionEnum.NO_THIS_USER);
         }
@@ -86,6 +93,11 @@ public class LoginController {
         if (!loginDevice.equals(LOGIN_DEVICE.DEVICE.getType()) && !loginDevice.equals(LOGIN_DEVICE.PC.getType())) {
             throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
         }
+        Timestamp timestamp = new Timestamp((new Date()).getTime());
+
+        if (!Objects.isNull(user.getExpireAt()) && user.getExpireAt().before(timestamp)){
+            throw new AuthenticateException(BizExceptionEnum.ACCOUNT_EXPIRE);
+        }
 
         Optional<AccountRole> role = roleRepository.findById(user.getRoleCode());
         if (!role.isPresent()) {
@@ -93,12 +105,24 @@ public class LoginController {
         }
 
 
-        // set login info
-        StpUtil.login(user, loginDevice);
 
-        StpUtil.getSession().set("loginUser", user);
+        String token;
 
-        String token = StpUtil.getTokenValue();
+        token = StpUtil.getTokenValueByLoginId(username);
+        //没有token执行登录
+        if (!StringUtils.hasLength(token)) {
+            StpUtil.login(username, loginDevice);
+            token = StpUtil.getTokenValue();
+            StpUtil.setTokenValue(token);
+            StpUtil.getSession().set("loginUser", user);
+        }
+
+        if (loginDevice.equals(LOGIN_DEVICE.DEVICE.getType())){
+            Map<String,Object> stringStringMap = new HashMap<>();
+            stringStringMap.put("token",token);
+            stringStringMap.put("user",user);
+            return ResponseData.success(stringStringMap);
+        }
 
         LOGIN_LOG.info(String.format("用户 %s 登录 ... token: %s", user.getName(), token));
         UserResponse userResponse = new UserResponse();
@@ -121,22 +145,24 @@ public class LoginController {
 
     @GetMapping("/logout")
     public ResponseData logout(@RequestParam("loginDevice") String loginDevice) {
-        if (!StringUtils.hasLength(loginDevice)){
+        if (!StringUtils.hasLength(loginDevice)) {
             throw new ServiceException(BizExceptionEnum.SERVER_ERROR);
         }
 
         if (!loginDevice.equals(LOGIN_DEVICE.DEVICE.getType()) && !loginDevice.equals(LOGIN_DEVICE.PC.getType())) {
             throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
         }
+        if (loginDevice.equals(LOGIN_DEVICE.PC.getType())){
+            StpUtil.login(StpUtil.getLoginId(), LOGIN_DEVICE.PC.getType());
+        }
         LoginHistory loginHistory = new LoginHistory();
         loginHistory.setIp(IpUtil.getLocalhostIp());
-        loginHistory.setUser(((Account)StpUtil.getSession().get("loginUser")).getId());
+        loginHistory.setUser(((Account) StpUtil.getSession().get("loginUser")).getId());
         loginHistory.setHappenTime(new DateTime());
         loginHistory.setActionType(0);
-        loginHistory.setUsername(((Account)StpUtil.getSession().get("loginUser")).getUsername());
+        loginHistory.setUsername(((Account) StpUtil.getSession().get("loginUser")).getUsername());
         loginHistory.setLoginSys(loginDevice);
         loginHistoryRepository.save(loginHistory);
-        StpUtil.logout();
         return ResponseData.success("注销成功");
     }
 

+ 45 - 17
dtok-api/api/src/main/java/com/dtok/api/controller/ScriptController.java

@@ -2,6 +2,7 @@ package com.dtok.api.controller;
 
 import cn.dev33.satoken.annotation.SaCheckRole;
 import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.io.file.FileReader;
 import cn.hutool.core.lang.generator.UUIDGenerator;
 import com.dtok.entity.Account;
 import com.dtok.entity.LoginHistory;
@@ -12,6 +13,7 @@ import com.dtok.framework.base.BaseController;
 import com.dtok.framework.exception.BizExceptionEnum;
 import com.dtok.framework.response.ResponseData;
 import com.dtok.framework.util.ToolUtil;
+import com.dtok.framework.util.UploadUtils;
 import com.dtok.repository.ScriptHistoryRepository;
 import com.dtok.repository.ScriptRepository;
 import org.springframework.beans.BeanUtils;
@@ -24,9 +26,14 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.persistence.Transient;
 import javax.persistence.criteria.Predicate;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
@@ -34,7 +41,7 @@ import java.util.UUID;
 
 @RestController
 @RequestMapping("/script")
-@SaCheckRole(type = Account.FINAL_ROLE)
+@SaCheckRole(Account.FINAL_ROLE)
 public class ScriptController extends BaseController {
 
     @Autowired
@@ -53,7 +60,7 @@ public class ScriptController extends BaseController {
                 predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("app"), app)));
             }
             if (ToolUtil.isNotEmpty(module)) {
-                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("name"), module)));
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("module"), module)));
             }
             return predicate;
         };
@@ -61,27 +68,37 @@ public class ScriptController extends BaseController {
         return ResponseData.success(result);
     }
 
+    @GetMapping("/getScript/{id}")
+    public ResponseData getScript(@PathVariable String id) {
+        return ResponseData.success(scriptRepository.findFirstByUuid(id));
+    }
+
     @PostMapping("/add")
-    public ResponseData add(@RequestBody ScriptFormData scriptFormData) throws IOException {
+    public ResponseData add(ScriptFormData scriptFormData) throws IOException {
         if (Objects.isNull(scriptFormData.getFile())) {
             throw new NullPointerException("文件不能为空");
         }
-        if (StringUtils.hasLength(scriptFormData.getModule())) {
+        if (!StringUtils.hasLength(scriptFormData.getModule())) {
             throw new NullPointerException("模块不能为空");
         }
-        if (StringUtils.hasLength(scriptFormData.getGroupName())) {
+        if (!StringUtils.hasLength(scriptFormData.getGroupName())) {
             throw new NullPointerException("组不能为空");
         }
-        if (StringUtils.hasLength(scriptFormData.getApp())) {
+        if (!StringUtils.hasLength(scriptFormData.getApp())) {
             throw new NullPointerException("APP不能为空");
         }
         MultipartFile multipartFile = scriptFormData.getFile();
         InputStream inputStream = multipartFile.getInputStream();
-        byte[] bytes = new byte[inputStream.available()];
-        String content = new String(bytes, StandardCharsets.UTF_8);
-        scriptFormData.setScriptContent(content);
+        Path filepath = Paths.get(UploadUtils.getExcelDirFile(), multipartFile.getOriginalFilename());
+        try (OutputStream os = Files.newOutputStream(filepath)) {
+            os.write(multipartFile.getBytes());
+        }
+        File file = new File(filepath.toUri());
+        FileReader fileReader = new FileReader(file);
+        scriptFormData.setScriptContent(fileReader.readString());
+        file.delete();
         Script script = new Script();
-        BeanUtils.copyProperties(script, scriptFormData);
+        BeanUtils.copyProperties(scriptFormData, script);
         script.setUuid(new UUIDGenerator().next());
         script.setCreatedTime(new Date());
         script.setCallCount(0L);
@@ -91,14 +108,14 @@ public class ScriptController extends BaseController {
     }
 
     @PostMapping("/update/{id}")
-    public ResponseData update(@RequestBody ScriptFormData scriptFormData, @PathVariable String id) throws IOException {
-        if (StringUtils.hasLength(scriptFormData.getModule())) {
+    public ResponseData update(Script scriptFormData, @PathVariable String id) throws IOException {
+        if (!StringUtils.hasLength(scriptFormData.getModule())) {
             throw new NullPointerException("模块不能为空");
         }
-        if (StringUtils.hasLength(scriptFormData.getGroupName())) {
+        if (!StringUtils.hasLength(scriptFormData.getGroupName())) {
             throw new NullPointerException("组不能为空");
         }
-        if (StringUtils.hasLength(scriptFormData.getApp())) {
+        if (!StringUtils.hasLength(scriptFormData.getApp())) {
             throw new NullPointerException("APP不能为空");
         }
         Script script = scriptRepository.findFirstByUuid(id);
@@ -106,14 +123,25 @@ public class ScriptController extends BaseController {
             throw new NullPointerException(BizExceptionEnum.FILE_NOT_FOUND.getMessage());
         }
         script.setApp(scriptFormData.getApp());
-        script.setModule(script.getModule());
-        script.setGroupName(script.getGroupName());
+        script.setModule(scriptFormData.getModule());
+        script.setGroupName(scriptFormData.getGroupName());
         script.setEncrypt(scriptFormData.getEncrypt());
         scriptRepository.save(script);
         return ResponseData.success("添加成功");
     }
 
 
+    @GetMapping("/getAllVersionHistoryById/{id}")
+    public ResponseData getAllVersionHistoryById(@PathVariable String id) {
+        return ResponseData.success(scriptHistoryRepository.searchAllByScriptId(id));
+    }
+
+    @GetMapping("/getVersionHistoryById/{id}")
+    public ResponseData getVersionHistoryById(@PathVariable String id) {
+        return ResponseData.success(scriptHistoryRepository.findFirstByScriptId(id));
+    }
+
+
     @PostMapping("/versionChange/{id}")
     @Transactional(rollbackFor = Exception.class)
     public ResponseData versionChange(String scriptContent, @PathVariable String id) {
@@ -144,7 +172,7 @@ public class ScriptController extends BaseController {
     @Transactional(rollbackFor = Exception.class)
     public ResponseData delete(@PathVariable String id) {
         Script script = scriptRepository.findFirstByUuid(id);
-        if (!Objects.isNull(script)) {
+        if (Objects.isNull(script)) {
             throw new NullPointerException("没有找到脚本");
         }
 

+ 11 - 6
dtok-api/api/src/main/java/com/dtok/api/controller/UserController.java

@@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.secure.SaSecureUtil;
 import cn.hutool.crypto.SecureUtil;
 
+import cn.hutool.db.nosql.redis.RedisDS;
 import com.dtok.entity.Account;
 import com.dtok.framework.exception.BizExceptionEnum;
 import com.dtok.framework.exception.ServiceException;
@@ -17,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
+import redis.clients.jedis.Jedis;
 
 import javax.persistence.criteria.JoinType;
 import javax.persistence.criteria.Predicate;
@@ -34,6 +36,7 @@ public class UserController {
     @GetMapping("/search")
     public ResponseData search(@RequestParam(value = "username", required = false) String username,
                                @RequestParam(value = "name", required = false) String name) {
+
         Specification<Account> query = (root, query1, criteriaBuilder) -> {
             Predicate predicate = criteriaBuilder.conjunction();
             root.join("role", JoinType.LEFT);
@@ -51,15 +54,13 @@ public class UserController {
     }
 
 
-    @GetMapping("/delete/{id}")
-
+    @GetMapping("/delete/{username}")
     @Transactional(rollbackFor = Exception.class)
-    public ResponseData delete(@PathVariable("id") Integer id) {
-        Optional<Account> userOptional = userRepository.findById(id);
-        if (!userOptional.isPresent()) {
+    public ResponseData delete(@PathVariable("username") String username) {
+        Account user = userRepository.getFirstByUsername(username);
+        if (Objects.isNull(user)) {
             throw new ServiceException(BizExceptionEnum.NO_THIS_USER);
         }
-        Account user = userOptional.get();
 
         if (user.getRoleCode().equals(Account.FINAL_ROLE)) {
             throw new ServiceException(BizExceptionEnum.CANT_DELETE_ADMIN);
@@ -110,6 +111,10 @@ public class UserController {
         if (!ToolUtil.isNotEmpty(user.getName())) {
             throw new NullPointerException("姓名不能为空");
         }
+        Account account = userRepository.getUserLoginEntity(user.getUsername());
+        if (!Objects.isNull(account)) {
+            throw new ServiceException(BizExceptionEnum.USER_ALREADY);
+        }
         if (user.getIsSuper()) {
             user.setRoleCode(Account.FINAL_ROLE);
         }

+ 1 - 1
dtok-api/entity/src/main/java/com/dtok/entity/Account.java

@@ -62,7 +62,7 @@ public class Account implements Serializable {
 	 * 最大设备数量
 	 */
 	@Column(name = "max_devices" )
-	private String maxDevices;
+	private Integer maxDevices;
 	/**
 	 * 手机号
 	 */

+ 10 - 4
dtok-api/entity/src/main/java/com/dtok/entity/CommonItem.java

@@ -1,9 +1,6 @@
 package com.dtok.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import javax.persistence.*;
 import java.io.Serializable;
 
 import lombok.Data;
@@ -29,6 +26,7 @@ public class CommonItem implements Serializable {
 
     @Id
     @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
 
     @Column(name = "app")
@@ -50,6 +48,14 @@ public class CommonItem implements Serializable {
     private Date createdTime;
 
 
+    @OneToOne
+    @JoinColumn(name = "app", referencedColumnName = "package_name", insertable = false, updatable = false)
+    private AppInfo appInfo;
+
+    @OneToOne
+    @JoinColumn(name = "created_at", referencedColumnName = "id", insertable = false, updatable = false)
+    private Account createdUser;
+
     /**
      * 创建
      */

+ 12 - 0
dtok-api/entity/src/main/java/com/dtok/entity/Devices.java

@@ -25,6 +25,9 @@ public class Devices  implements Serializable {
 
 	private static final long serialVersionUID =  7336812044556799572L;
 
+	public static final String ONLINE="ONLINE";
+	public static final String OFFLINE="OFFLINE";
+
 	/**
 	 * 自增ID
 
@@ -89,4 +92,13 @@ OFFLINE 离线
    	@Column(name = "last_connection_ip" )
 	private String lastConnectionIp;
 
+
+
+	/**
+	 * 最后登录IP
+
+	 */
+	@Column(name = "register_at" )
+	private Date registerAt;
+
 }

+ 4 - 4
dtok-api/entity/src/main/java/com/dtok/entity/Script.java

@@ -1,9 +1,6 @@
 package com.dtok.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import javax.persistence.*;
 import java.io.Serializable;
 
 import lombok.Data;
@@ -37,6 +34,9 @@ public class Script implements Serializable {
     @Column(name = "app")
     private String app;
 
+    @OneToOne
+    @JoinColumn(name = "app", referencedColumnName = "package_name", insertable = false, updatable = false)
+    private AppInfo appInfo;
     /**
      * 模块
      */

+ 7 - 4
dtok-api/entity/src/main/java/com/dtok/entity/ScriptHistory.java

@@ -1,9 +1,6 @@
 package com.dtok.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import javax.persistence.*;
 import java.io.Serializable;
 import lombok.Data;
 import lombok.AllArgsConstructor;
@@ -27,11 +24,17 @@ public class ScriptHistory  implements Serializable {
 
 	@Id
    	@Column(name = "id" )
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
 	private Long id;
 
    	@Column(name = "script_id" )
 	private String scriptId;
 
+
+	@OneToOne
+	@JoinColumn(name = "script_id", referencedColumnName = "uuid", insertable = false, updatable = false)
+	private Script script;
+
    	@Column(name = "version" )
 	private Long version;
 

+ 17 - 0
dtok-api/entity/src/main/java/com/dtok/entity/jedisvo/LoginItem.java

@@ -0,0 +1,17 @@
+package com.dtok.entity.jedisvo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class LoginItem implements Serializable {
+
+    String username;
+
+    String userId;
+
+    Integer pcOnlineCount;
+
+    Integer deviceOnlineCount;
+}

TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/Account.class


TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/CommonItem.class


TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/Devices.class


TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/Script.class


TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/ScriptHistory.class


TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/jedisvo/LoginItem.class


TEMPAT SAMPAH
dtok-api/entity/target/classes/com/dtok/entity/params/ScriptFormData.class


+ 1 - 2
dtok-api/framework/pom.xml

@@ -45,8 +45,7 @@
         <!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
         <dependency>
             <groupId>cn.dev33</groupId>
-            <artifactId>sa-token-dao-redis</artifactId>
-            <version>1.25.0</version>
+            <artifactId>sa-token-redis-jackson</artifactId>
         </dependency>
         <dependency>
             <groupId>com.dtok</groupId>

+ 3 - 2
dtok-api/framework/src/main/java/com/dtok/framework/authenticate/StpInterfaceImpl.java

@@ -27,14 +27,15 @@ public class StpInterfaceImpl implements StpInterface {
 
     @Override
     public List<String> getPermissionList(Object o, String s) {
-        List<Permission> permissions = permissionRepository.findPermissionByUsername(((Account) o).getUsername());
+        List<Permission> permissions = permissionRepository.findPermissionByUsername((String) o);
         return permissions.stream().map(Permission::getCode).collect(Collectors.toList());
     }
 
     @Override
     public List<String> getRoleList(Object o, String s) {
+        Account account = userRepository.getFirstByUsername((String) o);
         List<String> role = new ArrayList<>();
-        role.add(((Account)o).getRoleCode());
+        role.add(account.getRoleCode());
         return role;
     }
 }

+ 27 - 32
dtok-api/framework/src/main/java/com/dtok/framework/configure/SaTokenConfigure.java

@@ -1,32 +1,27 @@
-//package com.dtok.framework.configure;
-//
-//import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
-//import cn.dev33.satoken.interceptor.SaRouteInterceptor;
-//import cn.dev33.satoken.router.SaRouter;
-//import cn.dev33.satoken.stp.StpUtil;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-//
-//import java.util.Arrays;
-//import java.util.Collections;
-//
-//@Configuration
-//public class SaTokenConfigure implements WebMvcConfigurer {
-//    // 注册拦截器
-//    @Override
-//    public void addInterceptors(InterceptorRegistry registry) {
-//        // 注册 Sa-Token 的路由拦截器
-//        registry.addInterceptor(new SaRouteInterceptor())
-//                .addPathPatterns("/**")
-//                .excludePathPatterns("/login","/logout","/static/**");
-//    }
-//
-//
-//    @Override
-//    public void addResourceHandlers(ResourceHandlerRegistry registry) {
-//        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
-//        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
-//    }
-//}
+package com.dtok.framework.configure;
+
+import cn.dev33.satoken.interceptor.SaInterceptor;
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class SaTokenConfigure implements WebMvcConfigurer {
+    // 注册拦截器
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 注册 Sa-Token 的路由拦截器
+        registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
+                .addPathPatterns("/**")
+                .excludePathPatterns("/login","/logout","/static/**");
+    }
+
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
+        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
+    }
+}

+ 2 - 11
dtok-api/framework/src/main/java/com/dtok/framework/configure/WebConfigurer.java

@@ -1,21 +1,12 @@
 package com.dtok.framework.configure;
 
-import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+import cn.dev33.satoken.interceptor.SaInterceptor;
 import com.dtok.framework.util.UploadUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.expression.ParseException;
-import org.springframework.format.FormatterRegistry;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-
 @Configuration
 public class WebConfigurer implements WebMvcConfigurer {
 
@@ -29,7 +20,7 @@ public class WebConfigurer implements WebMvcConfigurer {
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
         // 注册 Sa-Token 的路由拦截器
-        registry.addInterceptor(new SaRouteInterceptor())
+        registry.addInterceptor(new SaInterceptor())
                 .addPathPatterns("/**").excludePathPatterns("/login");
     }
 

+ 3 - 1
dtok-api/framework/src/main/java/com/dtok/framework/exception/BizExceptionEnum.java

@@ -55,6 +55,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum {
     USER_ALREADY_REG(401, "该用户已经注册"),
     NO_THIS_USER(400, "没有此用户"),
     USER_NOT_EXISTED(400, "没有此用户"),
+    ACCOUNT_EXPIRE(401, "账户过期"),
     ACCOUNT_FREEZED(401, "账号被冻结"),
     OLD_PWD_NOT_RIGHT(402, "原密码不正确"),
     TWO_PWD_NOT_MATCH(405, "两次输入密码不一致"),
@@ -96,7 +97,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum {
 
     NOT_FIND_COMPANY(404, "没有找到公司"),
 
-    NO_COMPANY_PERMISSION(403, "没有该公司权限");
+    NO_COMPANY_PERMISSION(403, "没有该公司权限"),
+    DEVICE_NOT_REGISTER(499, "设备未注册");
 
     BizExceptionEnum(int code, String message) {
         this.code = code;

+ 27 - 26
dtok-api/framework/src/main/java/com/dtok/framework/listener/MySaTokenListener.java

@@ -16,13 +16,11 @@ public class MySaTokenListener implements SaTokenListener {
 
     private static final Logger LOGGER= LoggerFactory.getLogger("loginLog");
 
-    /**
-     * 每次登录时触发
-     */
+
+
     @Override
-    public void doLogin(String loginType, Object loginId, SaLoginModel loginModel) {
-        LOGGER.info(String.format("登录 : %s\t%s\t%s\t", loginType, loginId, loginModel.getDevice()));
-        // ...
+    public void doLogin(String s, Object o, String s1, SaLoginModel saLoginModel) {
+
     }
 
     /**
@@ -33,36 +31,34 @@ public class MySaTokenListener implements SaTokenListener {
         // ...
     }
 
-    /**
-     * 每次被踢下线时触发
-     */
     @Override
-    public void doLogoutByLoginId(String loginType, Object loginId, String tokenValue, String device) {
-        // ...
+    public void doKickout(String s, Object o, String s1) {
+
     }
 
-    /**
-     * 每次被顶下线时触发
-     */
     @Override
-    public void doReplaced(String loginType, Object loginId, String tokenValue, String device) {
-        // ...
+    public void doReplaced(String s, Object o, String s1) {
+
     }
 
-    /**
-     * 每次被封禁时触发
-     */
     @Override
-    public void doDisable(String loginType, Object loginId, long disableTime) {
-        // ...
+    public void doDisable(String s, Object o, String s1, int i, long l) {
+
     }
 
-    /**
-     * 每次被解封时触发
-     */
     @Override
-    public void doUntieDisable(String loginType, Object loginId) {
-        // ...
+    public void doUntieDisable(String s, Object o, String s1) {
+
+    }
+
+    @Override
+    public void doOpenSafe(String s, String s1, String s2, long l) {
+
+    }
+
+    @Override
+    public void doCloseSafe(String s, String s1, String s2) {
+
     }
 
     /**
@@ -82,4 +78,9 @@ public class MySaTokenListener implements SaTokenListener {
         // ...
     }
 
+    @Override
+    public void doRenewTimeout(String s, Object o, long l) {
+
+    }
+
 }

+ 24 - 2300
dtok-api/framework/src/main/java/com/dtok/framework/util/RedisUtil.java

@@ -1,2307 +1,31 @@
 package com.dtok.framework.util;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
+import cn.hutool.db.nosql.redis.RedisDS;
+import cn.hutool.json.JSONUtil;
+import cn.hutool.setting.Setting;
+import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-
 import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.ListPosition;
-import redis.clients.jedis.SortingParams;
-
-@Component
-@Slf4j
-public class RedisUtil{
-
-	@Autowired
-	private JedisPool jedisPool;
-
-	/**
-	 * <p>
-	 * 通过key获取储存在redis中的value
-	 * </p>
-	 * <p>
-	 * 并释放连接
-	 * </p>
-	 *
-	 * @param key
-	 * @param indexdb 选择redis库 0-15
-	 * @return 成功返回value 失败返回null
-	 */
-	public String get(String key,int indexdb) {
-		Jedis jedis = null;
-		String value = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			value = jedis.get(key);
-			log.info(value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return value;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取储存在redis中的value
-	 * </p>
-	 * <p>
-	 * 并释放连接
-	 * </p>
-	 *
-	 * @param key
-	 * @param indexdb 选择redis库 0-15
-	 * @return 成功返回value 失败返回null
-	 */
-	public byte[] get(byte[] key,int indexdb) {
-		Jedis jedis = null;
-		byte[] value = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			value = jedis.get(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return value;
-	}
-	/**
-	 * <p>
-	 * 向redis存入key和value,并释放连接资源
-	 * </p>
-	 * <p>
-	 * 如果key已经存在 则覆盖
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @param indexdb 选择redis库 0-15
-	 * @return 成功 返回OK 失败返回 0
-	 */
-	public String set(String key, String value,int indexdb) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			return jedis.set(key, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return "0";
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-	/**
-	 * <p>
-	 * 向redis存入key和value,并释放连接资源
-	 * </p>
-	 * <p>
-	 * 如果key已经存在 则覆盖
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @param indexdb 选择redis库 0-15
-	 * @return 成功 返回OK 失败返回 0
-	 */
-	public String set(byte[] key, byte[] value,int indexdb) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			return jedis.set(key, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return "0";
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-	/**
-	 * <p>
-	 * 删除指定的key,也可以传入一个包含key的数组
-	 * </p>
-	 *
-	 * @param keys 一个key 也可以使 string 数组
-	 * @return 返回删除成功的个数
-	 */
-	public Long del(String... keys) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.del(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-	/**
-	 * <p>
-	 * 删除指定的key,也可以传入一个包含key的数组
-	 * </p>
-	 * @param indexdb 选择redis库 0-15
-	 * @param keys 一个key 也可以使 string 数组
-	 * @return 返回删除成功的个数
-	 */
-	public Long del(int indexdb,String... keys) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			return jedis.del(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-	/**
-	 * <p>
-	 * 删除指定的key,也可以传入一个包含key的数组
-	 * </p>
-	 * @param indexdb 选择redis库 0-15
-	 * @param keys 一个key 也可以使 string 数组
-	 * @return 返回删除成功的个数
-	 */
-	public Long del(int indexdb,byte[]... keys) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			return jedis.del(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-	/**
-	 * <p>
-	 * 通过key向指定的value值追加值
-	 * </p>
-	 *
-	 * @param key
-	 * @param str
-	 * @return 成功返回 添加后value的长度 失败 返回 添加的 value 的长度 异常返回0L
-	 */
-	public Long append(String key, String str) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.append(key, str);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 判断key是否存在
-	 * </p>
-	 *
-	 * @param key
-	 * @return true OR false
-	 */
-	public Boolean exists(String key) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.exists(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return false;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 清空当前数据库中的所有 key,此命令从不失败。
-	 * </p>
-	 *
-	 * @return 总是返回 OK
-	 */
-	public String flushDB() {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.flushDB();
-		} catch (Exception e) {
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 *            过期时间,单位:秒
-	 * @return 成功返回1 如果存在 和 发生异常 返回 0
-	 */
-	public Long expire(String key, int value, int indexdb) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			return jedis.expire(key, value);
-		} catch (Exception e) {
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 以秒为单位,返回给定 key 的剩余生存时间
-	 * </p>
-	 *
-	 * @param key
-	 * @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key
-	 *         的剩余生存时间。 发生异常 返回 0
-	 */
-	public Long ttl(String key,int indexdb) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			return jedis.ttl(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )
-	 * </p>
-	 *
-	 * @param key
-	 * @return 当生存时间移除成功时,返回 1 .如果 key 不存在或 key 没有设置生存时间,返回 0 , 发生异常 返回 -1
-	 */
-	public Long persist(String key) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.persist(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return -1L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 新增key,并将 key 的生存时间 (以秒为单位)
-	 * </p>
-	 *
-	 * @param key
-	 * @param seconds
-	 *            生存时间 单位:秒
-	 * @param value
-	 * @return 设置成功时返回 OK 。当 seconds 参数不合法时,返回一个错误。
-	 */
-	public String setex(String key, int seconds, String value) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.setex(key, seconds, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 设置key value,如果key已经存在则返回0,nx==> not exist
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @return 成功返回1 如果存在 和 发生异常 返回 0
-	 */
-	public Long setnx(String key, String value) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.setnx(key, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
-	 * </p>
-	 * <p>
-	 * 当 key 存在但不是字符串类型时,返回一个错误。
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @return 返回给定 key 的旧值。当 key 没有旧值时,也即是, key 不存在时,返回 nil
-	 */
-	public String getSet(String key, String value) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.getSet(key, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 设置key value并制定这个键值的有效期
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @param seconds
-	 *            单位:秒
-	 * @return 成功返回OK 失败和异常返回null
-	 */
-	public String setex(String key, String value, int seconds) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.setex(key, seconds, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key 和offset 从指定的位置开始将原先value替换
-	 * </p>
-	 * <p>
-	 * 下标从0开始,offset表示从offset下标开始替换
-	 * </p>
-	 * <p>
-	 * 如果替换的字符串长度过小则会这样
-	 * </p>
-	 * <p>
-	 * example:
-	 * </p>
-	 * <p>
-	 * value : bigsea@zto.cn
-	 * </p>
-	 * <p>
-	 * str : abc
-	 * </p>
-	 * <P>
-	 * 从下标7开始替换 则结果为
-	 * </p>
-	 * <p>
-	 * RES : bigsea.abc.cn
-	 * </p>
-	 *
-	 * @param key
-	 * @param str
-	 * @param offset
-	 *            下标位置
-	 * @return 返回替换后 value 的长度
-	 */
-	public Long setrange(String key, String str, int offset) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.setrange(key, offset, str);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 通过批量的key获取批量的value
-	 * </p>
-	 *
-	 * @param keys
-	 *            string数组 也可以是一个key
-	 * @return 成功返回value的集合, 失败返回null的集合 ,异常返回空
-	 */
-	public List<String> mget(String... keys) {
-		Jedis jedis = null;
-		List<String> values = null;
-		try {
-			jedis = jedisPool.getResource();
-			values = jedis.mget(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return values;
-	}
-
-	/**
-	 * <p>
-	 * 批量的设置key:value,可以一个
-	 * </p>
-	 * <p>
-	 * example:
-	 * </p>
-	 * <p>
-	 * obj.mset(new String[]{"key2","value1","key2","value2"})
-	 * </p>
-	 *
-	 * @param keysvalues
-	 * @return 成功返回OK 失败 异常 返回 null
-	 *
-	 */
-	public String mset(String... keysvalues) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.mset(keysvalues);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 批量的设置key:value,可以一个,如果key已经存在则会失败,操作会回滚
-	 * </p>
-	 * <p>
-	 * example:
-	 * </p>
-	 * <p>
-	 * obj.msetnx(new String[]{"key2","value1","key2","value2"})
-	 * </p>
-	 *
-	 * @param keysvalues
-	 * @return 成功返回1 失败返回0
-	 */
-	public Long msetnx(String... keysvalues) {
-		Jedis jedis = null;
-		Long res = 0L;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.msetnx(keysvalues);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 设置key的值,并返回一个旧值
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @return 旧值 如果key不存在 则返回null
-	 */
-	public String getset(String key, String value) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.getSet(key, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过下标 和key 获取指定下标位置的 value
-	 * </p>
-	 *
-	 * @param key
-	 * @param startOffset
-	 *            开始位置 从0 开始 负数表示从右边开始截取
-	 * @param endOffset
-	 * @return 如果没有返回null
-	 */
-	public String getrange(String key, int startOffset, int endOffset) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.getrange(key, startOffset, endOffset);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key 对value进行加值+1操作,当value不是int类型时会返回错误,当key不存在是则value为1
-	 * </p>
-	 *
-	 * @param key
-	 * @return 加值后的结果
-	 */
-	public Long incr(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.incr(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key给指定的value加值,如果key不存在,则这是value为该值
-	 * </p>
-	 *
-	 * @param key
-	 * @param integer
-	 * @return
-	 */
-	public Long incrBy(String key, Long integer) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.incrBy(key, integer);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 对key的值做减减操作,如果key不存在,则设置key为-1
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Long decr(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.decr(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 减去指定的值
-	 * </p>
-	 *
-	 * @param key
-	 * @param integer
-	 * @return
-	 */
-	public Long decrBy(String key, Long integer) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.decrBy(key, integer);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取value值的长度
-	 * </p>
-	 *
-	 * @param key
-	 * @return 失败返回null
-	 */
-	public Long serlen(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.strlen(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key给field设置指定的值,如果key不存在,则先创建
-	 * </p>
-	 *
-	 * @param key
-	 * @param field
-	 *            字段
-	 * @param value
-	 * @return 如果存在返回0 异常返回null
-	 */
-	public Long hset(String key, String field, String value) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hset(key, field, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key给field设置指定的值,如果key不存在则先创建,如果field已经存在,返回0
-	 * </p>
-	 *
-	 * @param key
-	 * @param field
-	 * @param value
-	 * @return
-	 */
-	public Long hsetnx(String key, String field, String value) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hsetnx(key, field, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key同时设置 hash的多个field
-	 * </p>
-	 *
-	 * @param key
-	 * @param hash
-	 * @return 返回OK 异常返回null
-	 */
-	public String hmset(String key, Map<String, String> hash, int indexdb) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.hmset(key, hash);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key 和 field 获取指定的 value
-	 * </p>
-	 *
-	 * @param key
-	 * @param field
-	 * @return 没有返回null
-	 */
-	public String hget(String key, String field) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hget(key, field);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key 和 fields 获取指定的value 如果没有对应的value则返回null
-	 * </p>
-	 *
-	 * @param key
-	 * @param fields
-	 *            可以使 一个String 也可以是 String数组
-	 * @return
-	 */
-	public List<String> hmget(String key, int indexdb, String... fields) {
-		Jedis jedis = null;
-		List<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.hmget(key, fields);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key给指定的field的value加上给定的值
-	 * </p>
-	 *
-	 * @param key
-	 * @param field
-	 * @param value
-	 * @return
-	 */
-	public Long hincrby(String key, String field, Long value) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hincrBy(key, field, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key和field判断是否有指定的value存在
-	 * </p>
-	 *
-	 * @param key
-	 * @param field
-	 * @return
-	 */
-	public Boolean hexists(String key, String field) {
-		Jedis jedis = null;
-		Boolean res = false;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hexists(key, field);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回field的数量
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Long hlen(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hlen(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-
-	}
-
-	/**
-	 * <p>
-	 * 通过key 删除指定的 field
-	 * </p>
-	 *
-	 * @param key
-	 * @param fields
-	 *            可以是 一个 field 也可以是 一个数组
-	 * @return
-	 */
-	public Long hdel(String key, String... fields) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hdel(key, fields);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回所有的field
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Set<String> hkeys(String key) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hkeys(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回所有和key有关的value
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public List<String> hvals(String key) {
-		Jedis jedis = null;
-		List<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.hvals(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取所有的field和value
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Map<String, String> hgetall(String key, int indexdb) {
-		Jedis jedis = null;
-		Map<String, String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.hgetAll(key);
-		} catch (Exception e) {
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key向list头部添加字符串
-	 * </p>
-	 *
-	 * @param key
-	 * @param strs
-	 *            可以使一个string 也可以使string数组
-	 * @return 返回list的value个数
-	 */
-	public Long lpush(int indexdb, String key, String... strs) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.lpush(key, strs);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key向list尾部添加字符串
-	 * </p>
-	 *
-	 * @param key
-	 * @param strs
-	 *            可以使一个string 也可以使string数组
-	 * @return 返回list的value个数
-	 */
-	public Long rpush(String key, String... strs) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.rpush(key, strs);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key在list指定的位置之前或者之后 添加字符串元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param where
-	 *            LIST_POSITION枚举类型
-	 * @param pivot
-	 *            list里面的value
-	 * @param value
-	 *            添加的value
-	 * @return
-	 */
-	public Long linsert(String key, ListPosition where, String pivot,
-						String value) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.linsert(key, where, pivot, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key设置list指定下标位置的value
-	 * </p>
-	 * <p>
-	 * 如果下标超过list里面value的个数则报错
-	 * </p>
-	 *
-	 * @param key
-	 * @param index
-	 *            从0开始
-	 * @param value
-	 * @return 成功返回OK
-	 */
-	public String lset(String key, Long index, String value) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.lset(key, index, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key从对应的list中删除指定的count个 和 value相同的元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param count
-	 *            当count为0时删除全部
-	 * @param value
-	 * @return 返回被删除的个数
-	 */
-	public Long lrem(String key, long count, String value) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.lrem(key, count, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key保留list中从strat下标开始到end下标结束的value值
-	 * </p>
-	 *
-	 * @param key
-	 * @param start
-	 * @param end
-	 * @return 成功返回OK
-	 */
-	public String ltrim(String key, long start, long end) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.ltrim(key, start, end);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key从list的头部删除一个value,并返回该value
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	synchronized public String lpop(String key) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.lpop(key);
-		} catch (Exception e) {
 
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
 
-	/**
-	 * <p>
-	 * 通过key从list尾部删除一个value,并返回该元素
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	synchronized public String rpop(String key, int indexdb) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.rpop(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key从一个list的尾部删除一个value并添加到另一个list的头部,并返回该value
-	 * </p>
-	 * <p>
-	 * 如果第一个list为空或者不存在则返回null
-	 * </p>
-	 *
-	 * @param srckey
-	 * @param dstkey
-	 * @return
-	 */
-	public String rpoplpush(String srckey, String dstkey, int indexdb) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.rpoplpush(srckey, dstkey);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取list中指定下标位置的value
-	 * </p>
-	 *
-	 * @param key
-	 * @param index
-	 * @return 如果没有返回null
-	 */
-	public String lindex(String key, long index) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.lindex(key, index);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回list的长度
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Long llen(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.llen(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取list指定下标位置的value
-	 * </p>
-	 * <p>
-	 * 如果start 为 0 end 为 -1 则返回全部的list中的value
-	 * </p>
-	 *
-	 * @param key
-	 * @param start
-	 * @param end
-	 * @return
-	 */
-	public List<String> lrange(String key, long start, long end, int indexdb) {
-		Jedis jedis = null;
-		List<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(indexdb);
-			res = jedis.lrange(key, start, end);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 将列表 key 下标为 index 的元素的值设置为 value
-	 * </p>
-	 *
-	 * @param key
-	 * @param index
-	 * @param value
-	 * @return 操作成功返回 ok ,否则返回错误信息
-	 */
-	public String lset(String key, long index, String value) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.lset(key, index, value);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 返回给定排序后的结果
-	 * </p>
-	 *
-	 * @param key
-	 * @param sortingParameters
-	 * @return 返回列表形式的排序结果
-	 */
-	public List<String> sort(String key, SortingParams sortingParameters) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.sort(key, sortingParameters);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 返回排序后的结果,排序默认以数字作为对象,值被解释为双精度浮点数,然后进行比较。
-	 * </p>
-	 *
-	 * @param key
-	 * @return 返回列表形式的排序结果
-	 */
-	public List<String> sort(String key) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.sort(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 通过key向指定的set中添加value
-	 * </p>
-	 *
-	 * @param key
-	 * @param members
-	 *            可以是一个String 也可以是一个String数组
-	 * @return 添加成功的个数
-	 */
-	public Long sadd(String key, String... members) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sadd(key, members);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key删除set中对应的value值
-	 * </p>
-	 *
-	 * @param key
-	 * @param members
-	 *            可以是一个String 也可以是一个String数组
-	 * @return 删除的个数
-	 */
-	public Long srem(String key, String... members) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.srem(key, members);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key随机删除一个set中的value并返回该值
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public String spop(String key) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.spop(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取set中的差集
-	 * </p>
-	 * <p>
-	 * 以第一个set为标准
-	 * </p>
-	 *
-	 * @param keys
-	 *            可以使一个string 则返回set中所有的value 也可以是string数组
-	 * @return
-	 */
-	public Set<String> sdiff(String... keys) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sdiff(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取set中的差集并存入到另一个key中
-	 * </p>
-	 * <p>
-	 * 以第一个set为标准
-	 * </p>
-	 *
-	 * @param dstkey
-	 *            差集存入的key
-	 * @param keys
-	 *            可以使一个string 则返回set中所有的value 也可以是string数组
-	 * @return
-	 */
-	public Long sdiffstore(String dstkey, String... keys) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sdiffstore(dstkey, keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取指定set中的交集
-	 * </p>
-	 *
-	 * @param keys
-	 *            可以使一个string 也可以是一个string数组
-	 * @return
-	 */
-	public Set<String> sinter(String... keys) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sinter(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取指定set中的交集 并将结果存入新的set中
-	 * </p>
-	 *
-	 * @param dstkey
-	 * @param keys
-	 *            可以使一个string 也可以是一个string数组
-	 * @return
-	 */
-	public Long sinterstore(String dstkey, String... keys) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sinterstore(dstkey, keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回所有set的并集
-	 * </p>
-	 *
-	 * @param keys
-	 *            可以使一个string 也可以是一个string数组
-	 * @return
-	 */
-	public Set<String> sunion(String... keys) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sunion(keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回所有set的并集,并存入到新的set中
-	 * </p>
-	 *
-	 * @param dstkey
-	 * @param keys
-	 *            可以使一个string 也可以是一个string数组
-	 * @return
-	 */
-	public Long sunionstore(String dstkey, String... keys) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sunionstore(dstkey, keys);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key将set中的value移除并添加到第二个set中
-	 * </p>
-	 *
-	 * @param srckey
-	 *            需要移除的
-	 * @param dstkey
-	 *            添加的
-	 * @param member
-	 *            set中的value
-	 * @return
-	 */
-	public Long smove(String srckey, String dstkey, String member) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.smove(srckey, dstkey, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取set中value的个数
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Long scard(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.scard(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key判断value是否是set中的元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param member
-	 * @return
-	 */
-	public Boolean sismember(String key, String member) {
-		Jedis jedis = null;
-		Boolean res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.sismember(key, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取set中随机的value,不删除元素
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public String srandmember(String key) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.srandmember(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取set中所有的value
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Set<String> smembers(String key) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.smembers(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key向zset中添加value,score,其中score就是用来排序的
-	 * </p>
-	 * <p>
-	 * 如果该value已经存在则根据score更新元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param score
-	 * @param member
-	 * @return
-	 */
-	public Long zadd(String key, double score, String member) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zadd(key, score, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 返回有序集 key 中,指定区间内的成员。min=0,max=-1代表所有元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param min
-	 * @param max
-	 * @return 指定区间内的有序集成员的列表。
-	 */
-	public Set<String> zrange(String key, long min, long max) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.zrange(key, min, max);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return null;
-	}
-
-	/**
-	 * <p>
-	 * 统计有序集 key 中,值在 min 和 max 之间的成员的数量
-	 * </p>
-	 *
-	 * @param key
-	 * @param min
-	 * @param max
-	 * @return 值在 min 和 max 之间的成员的数量。异常返回0
-	 */
-	public Long zcount(String key, double min, double max) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.zcount(key, min, max);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-
-	}
-
-	/**
-	 * <p>
-	 * 为哈希表 key 中的域 field 的值加上增量 increment 。增量也可以为负数,相当于对给定域进行减法操作。 如果 key
-	 * 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。
-	 * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。本操作的值被限制在 64 位(bit)有符号数字表示之内。
-	 * </p>
-	 * <p>
-	 * 将名称为key的hash中field的value增加integer
-	 * </p>
-	 *
-	 * @param key
-	 * @param value
-	 * @param increment
-	 * @return 执行 HINCRBY 命令之后,哈希表 key 中域 field的值。异常返回0
-	 */
-	public Long hincrBy(String key, String value, long increment) {
-		Jedis jedis = null;
-		try {
-			jedis = jedisPool.getResource();
-			return jedis.hincrBy(key, value, increment);
-		} catch (Exception e) {
-			log.error(e.getMessage());
-			return 0L;
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-
-	}
-
-	/**
-	 * <p>
-	 * 通过key删除在zset中指定的value
-	 * </p>
-	 *
-	 * @param key
-	 * @param members
-	 *            可以使一个string 也可以是一个string数组
-	 * @return
-	 */
-	public Long zrem(String key, String... members) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zrem(key, members);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key增加该zset中value的score的值
-	 * </p>
-	 *
-	 * @param key
-	 * @param score
-	 * @param member
-	 * @return
-	 */
-	public Double zincrby(String key, double score, String member) {
-		Jedis jedis = null;
-		Double res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zincrby(key, score, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回zset中value的排名
-	 * </p>
-	 * <p>
-	 * 下标从小到大排序
-	 * </p>
-	 *
-	 * @param key
-	 * @param member
-	 * @return
-	 */
-	public Long zrank(String key, String member) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zrank(key, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回zset中value的排名
-	 * </p>
-	 * <p>
-	 * 下标从大到小排序
-	 * </p>
-	 *
-	 * @param key
-	 * @param member
-	 * @return
-	 */
-	public Long zrevrank(String key, String member) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zrevrank(key, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key将获取score从start到end中zset的value
-	 * </p>
-	 * <p>
-	 * socre从大到小排序
-	 * </p>
-	 * <p>
-	 * 当start为0 end为-1时返回全部
-	 * </p>
-	 *
-	 * @param key
-	 * @param start
-	 * @param end
-	 * @return
-	 */
-	public Set<String> zrevrange(String key, long start, long end) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zrevrange(key, start, end);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回指定score内zset中的value
-	 * </p>
-	 *
-	 * @param key
-	 * @param max
-	 * @param min
-	 * @return
-	 */
-	public Set<String> zrangebyscore(String key, String max, String min) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zrevrangeByScore(key, max, min);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回指定score内zset中的value
-	 * </p>
-	 *
-	 * @param key
-	 * @param max
-	 * @param min
-	 * @return
-	 */
-	public Set<String> zrangeByScore(String key, double max, double min) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zrevrangeByScore(key, max, min);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 返回指定区间内zset中value的数量
-	 * </p>
-	 *
-	 * @param key
-	 * @param min
-	 * @param max
-	 * @return
-	 */
-	public Long zcount(String key, String min, String max) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zcount(key, min, max);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key返回zset中的value个数
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public Long zcard(String key) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zcard(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key获取zset中value的score值
-	 * </p>
-	 *
-	 * @param key
-	 * @param member
-	 * @return
-	 */
-	public Double zscore(String key, String member) {
-		Jedis jedis = null;
-		Double res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zscore(key, member);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key删除给定区间内的元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param start
-	 * @param end
-	 * @return
-	 */
-	public Long zremrangeByRank(String key, long start, long end) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zremrangeByRank(key, start, end);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 通过key删除指定score内的元素
-	 * </p>
-	 *
-	 * @param key
-	 * @param start
-	 * @param end
-	 * @return
-	 */
-	public Long zremrangeByScore(String key, double start, double end) {
-		Jedis jedis = null;
-		Long res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.zremrangeByScore(key, start, end);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * <p>
-	 * 返回满足pattern表达式的所有key
-	 * </p>
-	 * <p>
-	 * keys(*)
-	 * </p>
-	 * <p>
-	 * 返回所有的key
-	 * </p>
-	 *
-	 * @param pattern
-	 * @return
-	 */
-	public Set<String> keys(String pattern) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.keys(pattern);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	public Set<String> keysBySelect(String pattern,int database) {
-		Jedis jedis = null;
-		Set<String> res = null;
-		try {
-			jedis = jedisPool.getResource();
-			jedis.select(database);
-			res = jedis.keys(pattern);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-
-	/**
-	 * <p>
-	 * 通过key判断值得类型
-	 * </p>
-	 *
-	 * @param key
-	 * @return
-	 */
-	public String type(String key) {
-		Jedis jedis = null;
-		String res = null;
-		try {
-			jedis = jedisPool.getResource();
-			res = jedis.type(key);
-		} catch (Exception e) {
-
-			log.error(e.getMessage());
-		} finally {
-			returnResource(jedisPool, jedis);
-		}
-		return res;
-	}
-
-	/**
-	 * 序列化对象
-	 * @param obj
-	 * @return
-	 * 对象需实现Serializable接口
-	 */
-	public static byte[] ObjTOSerialize(Object obj) {
-		ObjectOutputStream oos = null;
-		ByteArrayOutputStream byteOut = null;
-		try {
-			byteOut = new ByteArrayOutputStream();
-			oos = new ObjectOutputStream(byteOut);
-			oos.writeObject(obj);
-			byte[] bytes = byteOut.toByteArray();
-			return bytes;
-		} catch (Exception e) {
-		}
-		return null;
-	}
-
-	/**
-	 * 反序列化对象
-	 * @param bytes
-	 * @return
-	 * 对象需实现Serializable接口
-	 */
-	public static Object unserialize(byte[] bytes) {
-		ByteArrayInputStream bais = null;
-		try {
-			//反序列化
-			bais = new ByteArrayInputStream(bytes);
-			ObjectInputStream ois = new ObjectInputStream(bais);
-			return ois.readObject();
-		} catch (Exception e) {
-		}
-		return null;
-	}
-
-	/**
-	 * 返还到连接池
-	 *
-	 * @param jedisPool
-	 * @param jedis
-	 */
-	public static void returnResource(JedisPool jedisPool, Jedis jedis) {
-		if (jedis != null) {
-			jedisPool.returnResource(jedis);
-		}
-	}
-
-	// public static RedisUtil getRu() {
-	// return ru;
-	// }
-	//
-	// public static void setRu(RedisUtil ru) {
-	// RedisUtil.ru = ru;
-	// }
-
-	public static void main(String[] args) {
-		/*JedisPool jedisPool = new JedisPool(null,"localhost",6379,100,"123456");
-		Jedis jedis = jedisPool.getResource();
-		//r.get("", RedisConstants.datebase4);
-		jedis.select(RedisConstants.datebase4);
-		Set<String> str =  jedis.keys("*");
-		for (String string : str) {
-			System.out.println(string);
-		}*/
-	}
-}
+/**
+ * redis工具类
+ *
+ * @author Thomas
+ * @since 2021-08-13
+ */
+@Slf4j
+@Component
+@Data
+public class RedisUtil {
+
+    private static Jedis instance;
+
+    public static Jedis getInstance() {
+        if (instance == null) {
+            instance = RedisDS.create().getJedis();
+        }
+        return instance;
+    }
+}

+ 4 - 4
dtok-api/framework/src/main/resources/application.properties

@@ -8,13 +8,13 @@ spring.servlet.multipart.max-file-size=10MB
 spring.servlet.multipart.max-request-size=10MB
 sa-token.token-name=satoken
 sa-token.timeout=2592000
-sa-token.activity-timeout=-1
-sa-token.is-concurrent=false
-sa-token.is-share=false
+sa-token.active-timeout=-1
+sa-token.is-concurrent=true
+sa-token.is-share=true
 # token风格
 sa-token.token-style=uuid
 # 是否输出操作日志
-sa-token.is-log=false
+sa-token.is-log=true
 logging.config=classpath:log4j2-spring.xml
 logging.level.com.dtok.repository:trace
 file.tempDir=E:\\MyProject\\DTok

+ 4 - 4
dtok-api/framework/target/classes/application.properties

@@ -8,13 +8,13 @@ spring.servlet.multipart.max-file-size=10MB
 spring.servlet.multipart.max-request-size=10MB
 sa-token.token-name=satoken
 sa-token.timeout=2592000
-sa-token.activity-timeout=-1
-sa-token.is-concurrent=false
-sa-token.is-share=false
+sa-token.active-timeout=-1
+sa-token.is-concurrent=true
+sa-token.is-share=true
 # token风格
 sa-token.token-style=uuid
 # 是否输出操作日志
-sa-token.is-log=false
+sa-token.is-log=true
 logging.config=classpath:log4j2-spring.xml
 logging.level.com.dtok.repository:trace
 file.tempDir=E:\\MyProject\\DTok

TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/authenticate/StpInterfaceImpl.class


TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/configure/SaTokenConfigure.class


TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/configure/WebConfigurer.class


TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/configure/WebSocketConfig.class


TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/exception/BizExceptionEnum.class


TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/listener/MySaTokenListener.class


TEMPAT SAMPAH
dtok-api/framework/target/classes/com/dtok/framework/util/RedisUtil.class


+ 6 - 6
dtok-api/pom.xml

@@ -29,8 +29,8 @@
         <lombok.version>1.18.14</lombok.version>
         <jpa.version>2.5.2</jpa.version>
         <gson.version>2.2.4</gson.version>
-        <satoken.version>1.24.0</satoken.version>
-        <saredis.version>1.24.0</saredis.version>
+        <satoken.version>1.37.0</satoken.version>
+        <saredis.version>1.37.0</saredis.version>
         <commons.version>2.11.1</commons.version>
 
         <hutool.version>5.7.6</hutool.version>
@@ -62,13 +62,13 @@
                 <artifactId>sa-token-spring-boot-starter</artifactId>
                 <version>${satoken.version}</version>
             </dependency>
-
-            <!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
+            <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
             <dependency>
                 <groupId>cn.dev33</groupId>
-                <artifactId>sa-token-dao-redis-jackson</artifactId>
-                <version>${saredis.version}</version>
+                <artifactId>sa-token-redis-jackson</artifactId>
+                <version>${satoken.version}</version>
             </dependency>
+
             <dependency>
                 <groupId>com.dtok</groupId>
                 <artifactId>entity</artifactId>

+ 11 - 3
dtok-api/repository/src/main/java/com/dtok/repository/AccountRepository.java

@@ -1,14 +1,17 @@
 package com.dtok.repository;
+
 import com.dtok.entity.Account;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 
 import java.util.List;
 
 /**
- * @Description  
- * @Author  C.J
- * @Date 2024-03-08 
+ * @Description
+ * @Author C.J
+ * @Date 2024-03-08
  */
 
 public interface AccountRepository extends JpaRepository<Account, Integer>, JpaSpecificationExecutor<Account> {
@@ -16,8 +19,13 @@ public interface AccountRepository extends JpaRepository<Account, Integer>, JpaS
     Account findUserByUsernameAndPassword(String code, String password);
 
     Account findUserByUsername(String code);
+
+    Account findFirstById(Integer id);
     Account getFirstByUsername(String code);
 
+    @Query(value = "select * from acc_account  where binary username = :username", nativeQuery = true)
+    Account getUserLoginEntity(@Param("username") String code);
+
     List<Account> findUsersByRoleCode(String roleCode);
 
 

+ 5 - 0
dtok-api/repository/src/main/java/com/dtok/repository/CommonItemRepository.java

@@ -3,6 +3,7 @@ import com.dtok.entity.CommonItem;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import java.util.Date;
+import java.util.List;
 
 /**
  * @Description  
@@ -12,4 +13,8 @@ import java.util.Date;
 
 public interface CommonItemRepository  extends JpaRepository<CommonItem, String>, JpaSpecificationExecutor<CommonItem> {
 
+
+    List<CommonItem> findAllByApp(String app);
+    List<CommonItem> findAllByAppAndCreatedAt(String app,Long id);
+    List<CommonItem> findAllByAppAndIsDefaultOrCreatedAt(String app,Boolean isDefault,Long id);
 }

+ 19 - 4
dtok-api/repository/src/main/java/com/dtok/repository/DevicesRepository.java

@@ -1,15 +1,30 @@
 package com.dtok.repository;
+
 import com.dtok.entity.Devices;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
 import java.util.Date;
+import java.util.List;
 
 /**
- * @Description  
- * @Author  C.J
- * @Date 2024-03-09 
+ * @Description
+ * @Author C.J
+ * @Date 2024-03-10
  */
 
-public interface DevicesRepository  extends JpaRepository<Devices, String>, JpaSpecificationExecutor<Devices> {
+public interface DevicesRepository extends JpaRepository<Devices, String>, JpaSpecificationExecutor<Devices> {
+
+
+    @Query(value = "select d from Devices d left join Account a on d.account = a.id where a.username = :username")
+    List<Devices> searchAllByAccountUsername(@Param("username") String username);
+
+    Devices findFirstByAccountAndAndroidId(Long user,String androidId);
+
+    Devices findFirstByUuid(String uuid);
 
+    Integer countByAndroidId(String androidId);
+    void deleteDevicesByUuid(String uuid);
 }

+ 5 - 0
dtok-api/repository/src/main/java/com/dtok/repository/ScriptHistoryRepository.java

@@ -5,6 +5,7 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.repository.query.Param;
 
 import java.util.Date;
+import java.util.List;
 
 /**
  * @Description  
@@ -15,6 +16,10 @@ import java.util.Date;
 public interface ScriptHistoryRepository  extends JpaRepository<ScriptHistory, String>, JpaSpecificationExecutor<ScriptHistory> {
 
 
+    List<ScriptHistory> searchAllByScriptId(String id);
 
+
+    ScriptHistory findFirstByScriptId(String id);
     void deleteAllByScriptId(@Param("scriptId") String scriptId);
+
 }

+ 7 - 4
dtok-api/repository/src/main/java/com/dtok/repository/ScriptRepository.java

@@ -1,4 +1,5 @@
 package com.dtok.repository;
+
 import com.dtok.entity.Script;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -7,13 +8,15 @@ import org.springframework.data.repository.query.Param;
 import java.util.Date;
 
 /**
- * @Description  
- * @Author  C.J
- * @Date 2024-03-09 
+ * @Description
+ * @Author C.J
+ * @Date 2024-03-09
  */
 
-public interface ScriptRepository  extends JpaRepository<Script, String>, JpaSpecificationExecutor<Script> {
+public interface ScriptRepository extends JpaRepository<Script, String>, JpaSpecificationExecutor<Script> {
 
 
     Script findFirstByUuid(@Param("uuid") String uuid);
+
+    Script findFirstByModuleAndApp(String module,String app);
 }

TEMPAT SAMPAH
dtok-api/repository/target/classes/com/dtok/repository/AccountRepository.class


TEMPAT SAMPAH
dtok-api/repository/target/classes/com/dtok/repository/CommonItemRepository.class


TEMPAT SAMPAH
dtok-api/repository/target/classes/com/dtok/repository/DevicesRepository.class


TEMPAT SAMPAH
dtok-api/repository/target/classes/com/dtok/repository/ScriptHistoryRepository.class


TEMPAT SAMPAH
dtok-api/repository/target/classes/com/dtok/repository/ScriptRepository.class


TEMPAT SAMPAH
dtok-app/dtok-final/back.png


TEMPAT SAMPAH
dtok-app/dtok-final/close.png


+ 3 - 0
dtok-app/dtok-final/common/ScriptConf.js

@@ -0,0 +1,3 @@
+var SCRIPT_CONF = {}
+
+module.exports = SCRIPT_CONF;

+ 316 - 0
dtok-app/dtok-final/floatywindow.js

@@ -0,0 +1,316 @@
+let SCRIPT_CONF = require('./common/ScriptConf.js')
+
+/**
+ * 作者: 大柒
+ * 日期:  20190307
+ * 
+ */
+
+let floatyWindow = {}
+floatyWindow.isShow = false
+floatyWindow.showWindow = function () {
+    toastLog(floatyWindow.isShow)
+    if(floatyWindow.isShow){
+        return
+    }
+    threads.start(function () {
+        floatyWindow.isShow = true
+
+        var window = floaty.rawWindow(
+            `  <frame id="xx1"  h="875px" w="150px" >
+            <img id="cd_1" layout_gravity="bottom|center" w="100px" h="100px" src="file://./start.png" rotation="-90" />
+            <img id="cd_2" layout_gravity="bottom|center" w="100px" h="100px" src="file://./resume.png" rotation="-90" />
+            <img id="cd_3" layout_gravity="bottom|center" w="100px" h="100px" src="file://./back.png" rotation="-90" />
+            </frame>
+`);
+        var window1 = floaty.window(
+            ` <frame  h="150px" w="150px" >
+   <img id="jia" layout_gravity="bottom|left" w="150px" h="150px" src="file://./test.png" />
+</frame>`
+        );
+
+
+        //cd1值 菜单的默认加载位置 b,d,e 跟随C值 这个自己摸索
+        //jiaodu值 加载图标的旋转开始角度 
+        //sleep0值 动画时间 0为无延迟  数值越小 加载越快 反之则慢
+        //date0_sj值 按下手指不移动时等待多少毫秒关闭悬浮窗
+        //move0值 手指移动的距离小于该值 则判断为 未移动
+        //date1_sj 值 手指触摸时间小于该值 则判断为点击
+        var cd1 = 180;
+        var jiaodu = 0;
+        var sleep0 = 1;
+        var date0_sj = 1000;
+        var move0 = 60;
+        var date1_sj = 200;
+        var y2 = false,
+            y1 = true;
+        let cd2 = cd1, cd3 = cd1, cd4 = cd1
+        let windowWidth
+        let windowHeight
+        let window1Width
+        let window1Height
+
+        ui.post(function () {
+            windowWidth = window.getWidth();
+            windowHeight = window.getHeight();
+            window1Width = window1.getWidth();
+            window1Height = window1.getHeight();
+        }, 1000);
+        window.cd_1.setPivotY(cd1)
+        window.cd_1.setPivotX(cd1)
+        window.cd_2.setPivotY(cd2)
+        window.cd_2.setPivotX(cd2)
+        window.cd_3.setPivotY(cd3)
+        window.cd_3.setPivotX(cd3)
+        window.setTouchable(false);
+
+
+        //两个悬浮窗Y值差值
+        var Y_cz = 800
+        //两个悬浮窗初始位置 
+        window.setPosition(50, device.height - (400 + Y_cz))
+        window1.setPosition(50, device.height - 400)
+
+        function jz() {
+            threads.start(function () {
+                if (y1) {
+                    y1 = false
+                    if (y2) {
+                        y2 = false
+                        for (let i = 0; i < 100; i++) {
+                            if (i % 2) {
+                                window1.jia.setRotation(jiaodu += 1)
+                            }
+                            window.cd_1.setPivotY(cd1 += 4)
+                            window.cd_1.setPivotX(cd1)
+                            window.cd_2.setPivotY(cd2 += 3)
+                            window.cd_2.setPivotX(cd2)
+                            window.cd_3.setPivotY(cd3 += 2)
+                            window.cd_3.setPivotX(cd3)
+                            sleep(sleep0)
+                        }
+                    } else {
+                        for (let i = 100; i > 0; i--) {
+                            if (i % 2) {
+                                window1.jia.setRotation(jiaodu -= 1)
+                            }
+                            window.cd_1.setPivotY(cd1 -= 4)
+                            window.cd_1.setPivotX(cd1)
+                            window.cd_2.setPivotY(cd2 -= 3)
+                            window.cd_2.setPivotX(cd2)
+                            window.cd_3.setPivotY(cd3 -= 2)
+                            window.cd_3.setPivotX(cd3)
+                            sleep(sleep0)
+                        }
+                        y2 = true;
+                    }
+                    y1 = true
+                }
+            })
+        }
+
+
+
+        window.cd_1.on("click", () => {
+            if (y2) {
+                if('myEngine' in SCRIPT_CONF){
+                    if (!SCRIPT_CONF.myEngine.getEngine().isDestroyed()) {
+                        toast(`任务运行中: ${SCRIPT_CONF.module}`)
+                        return
+                    }
+                }
+              
+                try {
+                    let obj = SCRIPT_CONF.script
+                    let obj1 = SCRIPT_CONF.conf
+                    let obj2 = SCRIPT_CONF.module
+                    let obj3 = "const ENV_CONF = " + JSON.stringify(obj1) + ";\r\n";
+                    obj3 += obj
+                    SCRIPT_CONF.myEngine = engines.execScript(obj2, obj3)
+
+                } catch (err) {
+                    
+                }
+                jz();
+                window.setTouchable(false);
+            }
+        })
+        window.cd_2.on("click", () => {
+            if (y2) {
+                if('myEngine' in SCRIPT_CONF){
+                    if(!SCRIPT_CONF.myEngine.getEngine().isDestroyed()){
+                        SCRIPT_CONF.myEngine.getEngine().forceStop()
+                        toastLog(`已停止任务:${SCRIPT_CONF.module}`)
+                    }
+                }
+                jz();
+                window.setTouchable(false);
+            }
+        })
+        window.cd_3.on("click", () => {
+            if (y2) {
+                if('myEngine' in SCRIPT_CONF){
+                    if(!SCRIPT_CONF.myEngine.getEngine().isDestroyed()){
+                        SCRIPT_CONF.myEngine.getEngine().forceStop()
+                        toastLog(`已停止任务:${SCRIPT_CONF.module}`)
+                    }
+                }
+                threads.start(function(){
+                    floatyWindow.hideWindow()
+                })
+               
+            }
+        })
+
+    
+
+
+        var fn = () => {
+        }
+        var id = setInterval(
+            fn, 3000
+        )
+        //记录按键被按下时的触摸坐标
+        var x = 0,
+            y = 0;
+        //记录按键被按下时的悬浮窗位置
+        var windowX, windowY;
+        //记录按键被按下的时间以便判断长按等动作
+        var downTime;
+        yd = false;
+
+        window1.jia.setOnTouchListener(function (view, event) {
+            switch (event.getAction()) {
+                case event.ACTION_DOWN:
+                    x = event.getRawX();
+                    y = event.getRawY();
+                    windowX = window.getX();
+                    windowY = window.getY();
+                    windowX1 = window1.getX();
+                    windowY1 = window1.getY();
+                    downTime = new Date().getTime();
+                    return true;
+                case event.ACTION_MOVE:
+                    if (!yd) { //如果移动的距离大于h值 则判断为移动 yd为真
+                        if (Math.abs(event.getRawY() - y) > move0 || Math.abs(event.getRawX() - x) > move0) {
+                            yd = true
+                        }
+                        //如果按下的时间超过g值并且yd值为假判断为长按,退出脚本 
+                        if (new Date().getTime() - downTime > date0_sj) {
+                            log(new Date().getTime() - downTime);
+                            exit();
+
+                            //关闭悬浮窗
+                            //window.close()
+                            //window1.close()
+                        }
+                    } else { //移动手指时调整两个悬浮窗位置
+
+                        windowHeight = window1Height
+                        windowWidth = window1Width
+
+                        let xAxisMovingDistance = event.getRawX() - x;
+                        let yAxisMovingDistance = event.getRawY() - y;
+                        if (windowX + xAxisMovingDistance < 0) {
+                            if (windowY + yAxisMovingDistance < 0) {
+                                window.setPosition(10,
+                                    windowY + (event.getRawY() - y));
+                                window1.setPosition(10,
+                                    windowY + ((event.getRawY() - y) + Y_cz));
+                                console.log("触发了8")
+                            } else if (windowY + windowHeight + yAxisMovingDistance > device.height) {
+                                window.setPosition(10,
+                                    device.height - windowHeight);
+                                window1.setPosition(10,
+                                    device.height - windowHeight + Y_cz);
+                                console.log("触发了7")
+
+                                // window.setPosition(0, );
+                            } else {
+                                console.log("触发了6")
+                                window.setPosition(10,
+                                    windowY + yAxisMovingDistance);
+                                window1.setPosition(10,
+                                    windowY + yAxisMovingDistance + Y_cz);
+
+                                // window.setPosition(0, windowY + yAxisMovingDistance);
+                            }
+                        } else if (windowX + xAxisMovingDistance > device.width - windowWidth) {
+
+                            if (windowY + yAxisMovingDistance < 0) {
+                                console.log("触发了5")
+                                window.setPosition(device.width - windowWidth,
+                                    windowY + yAxisMovingDistance);
+                                window1.setPosition(device.width - windowWidth,
+                                    windowY + yAxisMovingDistance + Y_cz);
+
+                            } else if (windowY + windowHeight + yAxisMovingDistance > device.height) {
+                                console.log("触发了4")
+                                window.setPosition(device.width - windowWidth,
+                                    device.height - window1Height);
+                                window1.setPosition(device.width - windowWidth,
+                                    device.height - windowHeight + Y_cz);
+                                // window.setPosition(device.width - windowWidth, device.height - windowHeight);
+                            } else {
+                                console.log("触发了3")
+                                window.setPosition(device.width - windowWidth,
+                                    windowY + yAxisMovingDistance);
+                                window1.setPosition(device.width - windowWidth,
+                                    windowY + yAxisMovingDistance + Y_cz);
+                                // window.setPosition(device.width - windowWidth, windowY + yAxisMovingDistance);
+                            }
+                        } else {
+                            if (windowY + yAxisMovingDistance < 0) {
+                                console.log("触发了1")
+                                window.setPosition(windowX + xAxisMovingDistance,
+                                    0);
+                                window1.setPosition(windowX + xAxisMovingDistance,
+                                    0 + Y_cz);
+                                // window.setPosition(device.width - windowWidth, windowY + yAxisMovingDistance);
+                                // window.setPosition(windowX + xAxisMovingDistance, 0);
+                            } else if (windowY1 + windowHeight + yAxisMovingDistance + 50 > device.height) {
+                                console.log("触发了2")
+
+                                window.setPosition(windowX + xAxisMovingDistance,
+                                    device.height - windowHeight - Y_cz);
+                                window1.setPosition(windowX + xAxisMovingDistance,
+                                    device.height - windowHeight - 50);
+                                // window.setPosition(windowX + xAxisMovingDistance, device.height - windowHeight);
+                            } else {
+                                window.setPosition(windowX + xAxisMovingDistance,
+                                    windowY + yAxisMovingDistance);
+                                window1.setPosition(windowX + xAxisMovingDistance,
+                                    windowY + yAxisMovingDistance + Y_cz);
+                                // window.setPosition(windowX + xAxisMovingDistance, windowY + yAxisMovingDistance);
+                            }
+                        }
+
+
+                    }
+                    return true;
+                case event.ACTION_UP:
+                    //触摸时间小于 200毫秒 则判断为 点击
+                    if (new Date().getTime() - downTime < date1_sj) {
+                        jz();
+                        //根据Y2值 设置悬浮窗是否可以触摸
+                        if (y2) {
+                            window.setTouchable(false);
+                        } else {
+                            window.setTouchable(true);
+                        }
+                    }
+                    yd = false
+                    return true;
+            }
+            return true;
+        });
+
+    })
+}
+floatyWindow.hideWindow = function () {
+    floatyWindow.isShow = false
+    floaty.closeAll()
+}
+
+// floatyWindow.showWindow()
+module.exports = floatyWindow;

TEMPAT SAMPAH
dtok-app/dtok-final/logo.png


+ 298 - 0
dtok-app/dtok-final/main.js

@@ -0,0 +1,298 @@
+"ui";
+
+ui.layout(
+    `
+  <vertical padding="0" id="parent">
+  <webview id="web" h="*" w="*"  />
+
+</vertical>
+  `
+);
+let SCRIPT_CONF = require('./common/ScriptConf.js')
+let floatyObj = require('./floatywindow.js');
+initUi('http://192.168.2.24:8080')
+
+// ui.emitter.on("back_pressed", (e) => {
+//     e.consumed = true;
+//     activity.moveTaskToBack(true);
+//   });
+
+var storage = storages.create("dtok");
+
+function initUi(htmlPath) {
+    webViewExpand_init(ui.web)
+    var settings = ui.web.getSettings();
+    settings.setSupportZoom(false); // 是否支持页面缩放
+    settings.setBuiltInZoomControls(false); // 是否出现缩放工具
+    settings.setDisplayZoomControls(false);
+    if (htmlPath.indexOf('http') === 0) {
+        ui.web.loadUrl(htmlPath)
+    } else {
+        let path = 'file:' + files.path(htmlPath)
+        ui.web.loadUrl(path)
+    }
+}
+
+let conf = {
+    //baseUrl: "https://ruanjian168.cc/"
+    baseUrl: "http://192.168.2.24:9090/",
+    apiUrl: "http://192.168.2.24:9090/api/",
+    deviceType: 'DEVICE',
+    androidId:device.getAndroidId(),
+    deviceName:device.device,
+    deviceBrand:device.brand,
+    deviceVersion:device.release
+}
+
+
+ui.web.jsBridge.registerHandler("doLogin", (data, callBack) => {
+    let loginUrl = conf.baseUrl + 'login'
+    if (data == null) {
+        toastLog("请填写用户名密码")
+        callBack(null)
+        return;
+    }
+    let loginObj = JSON.parse(data)
+
+    if (!loginObj.hasOwnProperty('username')) {
+        toastLog("请填写用户名")
+        callBack(null)
+        return;
+    }
+    if (!loginObj.hasOwnProperty('password')) {
+        toastLog("请填写密码")
+        callBack(null)
+        return;
+    }
+    threads.start(function () {
+        let res = http.post(loginUrl, {
+            "username": loginObj.username,
+            "password": loginObj.password,
+            "loginDevice": conf.deviceType
+        })
+        var loginRespObj = res.body.json();
+        if (loginRespObj.code !== 200) {
+            toastLog(loginRespObj.message)
+            callBack(null)
+        } else {
+            storage.put("token", loginRespObj.data.token)
+            storage.put("userInfo", JSON.stringify(loginRespObj.data.user))
+            callBack(loginRespObj.data.token)
+        }
+    });
+
+
+})
+
+ui.web.jsBridge.registerHandler("doCheckAccountStatus", (data,callBack) => {
+    let checkLoginUrl = conf.apiUrl + 'checkLogin'
+    let token = storage.get("token")
+    console.log(token)
+    threads.start(function () {
+        let res = http.get(checkLoginUrl, {
+            headers: {
+                "satoken": token
+            }
+        })
+        let respObj = res.body.json()
+        if (respObj.code > 200){
+            console.log("未登录,清除")
+            toastLog("请先登录")
+            storage.remove("token")
+            storage.remove("userInfo")
+        }
+
+        callBack(JSON.stringify(respObj).toString())
+    })
+})
+
+
+ui.web.jsBridge.registerHandler("checkRegister", (data,callBack) => {
+    let token = storage.get("token")
+    let checkRegisterUrl = conf.apiUrl + `checkRegister/${token}/${conf.androidId}` 
+    console.log(token)
+    threads.start(function () {
+        let res = http.get(checkRegisterUrl, {
+            headers: {
+                "satoken": token
+            }
+        })
+        let respObj = res.body.json()
+        callBack(JSON.stringify(respObj).toString())
+    })
+})
+
+ui.web.jsBridge.registerHandler("logout", (data,callBack) => {
+    storage.remove("token")
+    storage.remove("userInfo")
+    callBack('1')
+})
+
+ui.web.jsBridge.registerHandler("registerDevice", (data,callBack) => {
+    let token = storage.get("token")
+    let registerUrl = conf.baseUrl + `device/registerDevice/${token}` 
+    console.log(registerUrl)
+    threads.start(function () {
+        console.log(conf)
+        let res = http.post(registerUrl,{
+            "deviceName": conf.deviceName,
+            "deviceVersion":conf.deviceVersion,
+            "deviceBrand":conf.deviceBrand,
+            "androidId":conf.androidId
+        }, {
+            headers: {
+                "satoken": token
+            },
+        })
+        let respObj = res.body.json()
+        callBack(JSON.stringify(respObj).toString())
+    })
+})
+
+ui.web.jsBridge.registerHandler("unBundleDevice", (data,callBack) => {
+    console.log('解绑',data)
+    let token = storage.get("token")
+    let unRegisterUrl = conf.baseUrl + `device/unBundleDevice/` + data 
+    console.log(unRegisterUrl)
+    threads.start(function () {
+        console.log(conf)
+        let res = http.get(unRegisterUrl, {
+            headers: {
+                "satoken": token
+            },
+        })
+        let respObj = res.body.json()
+        callBack(JSON.stringify(respObj).toString())
+    })
+})
+
+ui.web.jsBridge.registerHandler("getCommonItem", (data,callBack) => {
+    let token = storage.get("token")
+    let commonItemUrl = conf.apiUrl + "getCommonItem" 
+    threads.start(function () {
+        let res = http.get(commonItemUrl, {
+            headers: {
+                "satoken": token
+            },
+        })
+        let respObj = res.body.json()
+        callBack(JSON.stringify(respObj).toString())
+    })
+})
+
+ui.web.jsBridge.registerHandler("reload", (data, callBack) => {
+    console.log("刷新...")
+    ui.web.reload()
+})
+
+ui.web.jsBridge.registerHandler("startScript", (data, callBack) => {
+    let dataObj = JSON.parse(data)
+    let scriptUrl = conf.apiUrl + 'getExecScript/' + dataObj.uuid
+    let token = storage.get("token")
+    console.log("URL", scriptUrl)
+
+    threads.start(function () {
+        let res = http.post(scriptUrl, {
+            "module": dataObj.module
+        }, {
+            headers: {
+                "satoken": token
+            },
+        });
+
+        let scriptObj = res.body.json()
+        if (scriptObj.code !== 200) {
+            toastLog(scriptObj.message)
+            callBack(JSON.stringify(scriptObj).toString())
+            return
+        }
+        SCRIPT_CONF.script = scriptObj.data.scriptContent
+        SCRIPT_CONF.conf = dataObj.conf
+        SCRIPT_CONF.module = dataObj.module
+        var packageName = scriptObj.data.app; // 视频App的包名
+
+        floatyObj.showWindow()
+        // 打开视频App
+        launch(packageName);
+
+    });
+})
+
+ui.web.jsBridge.registerHandler("getToken", (data, callBack) => {
+    let token = storage.get("token")
+    console.log("获取TOKEN", token)
+    callBack(token)
+})
+
+
+
+
+ui.web.jsBridge.registerHandler("getUserInfo", (data, callBack) => {
+    let userInfo = storage.get("userInfo")
+    console.log("获取用户信息", userInfo)
+    callBack(userInfo)
+})
+
+
+ui.web.jsBridge.registerHandler("logout", (data, callBack) => {
+    storage.remove("token")
+    callBack(200)
+})
+ui.web.jsBridge.registerHandler("showToast", (data, callBack) => {
+    console.log(data)
+    toastLog(data)
+})
+// setTimeout(() => {
+//     ui.web.jsBridge.callHandler('jsTest', '数据', (data) => {})
+// }, 1000)
+
+
+
+function webViewExpand_init(webview) {
+    webview.setOnKeyListener(
+        new android.view.View.OnKeyListener({
+            onKey: function (v, keyCode, event) {
+                if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
+                        //表示按返回键
+                        log("返回键");
+                        ui.web.goBack(); //后退
+                        //webview.goForward();//前进
+                        return true; //已处理
+                    }
+                }
+                return false;
+            },
+        })
+    );
+
+    webview.webViewClient = new JavaAdapter(android.webkit.WebViewClient, {
+        /** 页面开始加载, 此时还没有加载 index.html 中的代码 */
+        onPageStarted: (webView, url, favicon) => {},
+        /** 页面加载完成, 在 window.onload 之后触发 */
+        onPageFinished: (webView, curUrl) => {
+            webview.injectionJsBridge()
+        },
+        onReceivedError: (webView, webResourceRequest, webResourceError) => {
+            let url = webResourceRequest.getUrl()
+            let errorCode = webResourceError.getErrorCode()
+            let description = webResourceError.getDescription()
+            console.trace(errorCode + ' ' + description + ' ' + url)
+        },
+    })
+
+
+
+    webview.webChromeClient = new JavaAdapter(android.webkit.WebChromeClient, {
+        /** 拦截 web console 消息 */
+        onConsoleMessage: (consoleMessage) => {
+            /** @type {string} */
+            let msg = consoleMessage.message()
+            let sourceId = consoleMessage.sourceId().split('/')
+            let sourceIdStr = sourceId[sourceId.length - 1]
+            let lineNumber = consoleMessage.lineNumber()
+            let msgLevel = consoleMessage.messageLevel()
+            console.log(msg)
+        },
+    })
+}

+ 37 - 0
dtok-app/dtok-final/project.json

@@ -0,0 +1,37 @@
+{
+
+    "assets": [],
+    "build": {
+      "build_id": "035D3905-6",
+      "build_number": 6,
+      "build_time": 1647676173470,
+      "release": false
+    },
+    "encryptLevel": 0,
+    "useFeatures": [],
+    "launchConfig": {
+      "displaySplash": true,
+      "hideLogs": false,
+      "splashLayoutXml": "splash.xml",
+      "splashText": "1.0.0",
+      "stableMode": false
+    },
+    "main": "main.js",
+    "name": "DTok",
+    "optimization": {
+      "removeAccessibilityService": false,
+      "removeOpenCv": true,
+      "unusedResources": false
+    },
+    "packageName": "cc.ruanjian168",
+    "permissionConfig": {
+      "manifestPermissions": [
+        "android.permission.INTERNET",
+        "android.permission.ACCESS_NETWORK_STATE"
+      ],
+      "requestListOnStartup": []
+    },
+    "scripts": {},
+    "versionCode": 1,
+    "versionName": "1.0.0"
+  }

TEMPAT SAMPAH
dtok-app/dtok-final/resume.png


TEMPAT SAMPAH
dtok-app/dtok-final/start.png


+ 1 - 0
dtok-app/dtok-final/test.js

@@ -0,0 +1 @@
+toastLog(device.getAndroidId())

TEMPAT SAMPAH
dtok-app/dtok-final/test.png


+ 181 - 271
dtok-app/dtok/demo.js

@@ -1,291 +1,201 @@
-let SCRIPT_CONF = require('./common/ScriptConf.js')
-
 /**
  * 作者: 大柒
  * 日期:  20190307
  * 
  */
-var window = floaty.rawWindow(
-    <frame id="xx1"  h="800px" w="150px" >
-            <img id="cd_1" layout_gravity="bottom|center" w="100px" h="100px" src="file://./start.png" rotation="-90" />
-            <img id="cd_2" layout_gravity="bottom|center" w="100px" h="100px" src="file://./resume.png" rotation="-90" />
-            <img id="cd_3" layout_gravity="bottom|center" w="100px" h="100px" src="file://./back.png" rotation="-90" />
-    </frame>
-);
-var window1 = floaty.window(
-    <frame  h="150px" w="150px" >
-        <img id="jia" layout_gravity="bottom|left" w="150px" h="150px" src="file://./test.png" />
-    </frame>
-);
-
-
-//cd1值 菜单的默认加载位置 b,d,e 跟随C值 这个自己摸索
-//jiaodu值 加载图标的旋转开始角度 
-//sleep0值 动画时间 0为无延迟  数值越小 加载越快 反之则慢
-//date0_sj值 按下手指不移动时等待多少毫秒关闭悬浮窗
-//move0值 手指移动的距离小于该值 则判断为 未移动
-//date1_sj 值 手指触摸时间小于该值 则判断为点击
-var cd1 = 180;
-var jiaodu = 0;
-var sleep0=1;
-var date0_sj=1000;
-var move0=60;
-var date1_sj=200;
-var y2 = false, y1 = true;
-let cd2 = cd1, cd3 = cd1
-let windowWidth
-let windowHeight
-let window1Width
-let window1Height
-let lockStart = false
-
-ui.post(function () {
-    windowWidth = window.getWidth();
-    windowHeight = window.getHeight();
-    window1Width = window1.getWidth();
-    window1Height = window1.getHeight();
-  }, 1000);
-window.cd_1.setPivotY(cd1)
-window.cd_1.setPivotX(cd1)
-window.cd_2.setPivotY(cd2)
-window.cd_2.setPivotX(cd2)
-window.cd_3.setPivotY(cd3)
-window.cd_3.setPivotX(cd3)
-window.setTouchable(false);
-
-
-//两个悬浮窗Y值差值
-var Y_cz=725
-//两个悬浮窗初始位置 
-window.setPosition(50, device.height - (400+Y_cz))
-
-// window.setPosition(device.width - 200, device.height - (400+Y_cz))
-window1.setPosition(50, device.height - 400)
-function jz() {
+let floatyWindow = {}
+floatyWindow.showWindow = function () {
     threads.start(function () {
-        if (y1) {
-            y1 = false
-            if (y2) {
-                y2 = false
-                for (let i = 0; i < 100; i++) {
-                    if (i % 2) { window1.jia.setRotation(jiaodu += 1) }
-                    window.cd_1.setPivotY(cd1 += 4)
-                    window.cd_1.setPivotX(cd1)
-                    window.cd_2.setPivotY(cd2 += 3)
-                    window.cd_2.setPivotX(cd2)
-                    window.cd_3.setPivotY(cd3 += 2)
-                    window.cd_3.setPivotX(cd3)
-                    sleep(sleep0)
-                }
-            } else {
-                for (let i = 100; i > 0; i--) {
-                    if (i % 2) { window1.jia.setRotation(jiaodu -= 1) }
-                    window.cd_1.setPivotY(cd1 -= 4)
-                    window.cd_1.setPivotX(cd1)
-                    window.cd_2.setPivotY(cd2 -= 3)
-                    window.cd_2.setPivotX(cd2)
-                    window.cd_3.setPivotY(cd3 -= 2)
-                    window.cd_3.setPivotX(cd3)
-                    sleep(sleep0)
-                }
-                y2 = true;
-            }
-            y1 = true
-        }
-    })
-}
 
-
-
-window.cd_1.on("click", () => {
-    if (y2) {
-        if(!lockStart){
-            if(SCRIPT_CONF){
-                lockStart = true
-                let obj = SCRIPT_CONF.script
-                let obj1 = SCRIPT_CONF.conf
-                let obj2 = SCRIPT_CONF.module
-                let obj3 = "const ENV_CONF = " + JSON.stringify(obj1) + ";\r\n" ;
-                obj3 += obj
-                engines.execScript(obj2,obj3)
-                lockStart = false
-            }
-        }else{
-            toastLog("脚本已经在运行")
-        }
-        
-        jz();
-        window.setTouchable(false);
-    }
-})
-window.cd_2.on("click", () => {
-    if (y2) {
-        engines.stopAll()
-        jz();
-        window.setTouchable(false);
-    }
-})
-window.cd_3.on("click", () => {
-    if (y2) {
-        toastLog("系统")
-        jz();
+        var window = floaty.rawWindow(
+            ` <frame id="xx1"  h="875px" w="150px" >
+   <img id="cd_1" layout_gravity="bottom|center" w="100px" h="100px" src="file://./start.png" rotation="-90" />
+  <img id="cd_2" layout_gravity="bottom|center" w="100px" h="100px" src="file://./resume.png" rotation="-90" />
+  <img id="cd_3" layout_gravity="bottom|center" w="100px" h="100px" src="file://./back.png" rotation="-90" />
+  <img id="cd_4" layout_gravity="bottom|center" w="100px" h="100px" src="file://./back.png" rotation="-90" />
+</frame>`
+        );
+        var window1 = floaty.window(
+            `  <frame  h="150px" w="150px" >
+  <img id="jia" layout_gravity="bottom|left" w="150px" h="150px" src="file://./logo.png" />
+</frame>`
+        );
+
+        //cd1值 菜单的默认加载位置 b,d,e 跟随C值 这个自己摸索
+        //jiaodu值 加载图标的旋转开始角度 
+        //sleep0值 动画时间 0为无延迟  数值越小 加载越快 反之则慢
+        //date0_sj值 按下手指不移动时等待多少毫秒关闭悬浮窗
+        //move0值 手指移动的距离小于该值 则判断为 未移动
+        //date1_sj 值 手指触摸时间小于该值 则判断为点击
+        var cd1 = 180;
+        var jiaodu = 0;
+        var sleep0 = 1;
+        var date0_sj = 1000;
+        var move0 = 60;
+        var date1_sj = 200;
+        var y2 = false,
+            y1 = true;
+        let cd2 = cd1,
+            cd3 = cd1,
+            cd4 = cd1
+
+
+
+        window.cd_1.setPivotY(cd1)
+        window.cd_1.setPivotX(cd1)
+        window.cd_2.setPivotY(cd2)
+        window.cd_2.setPivotX(cd2)
+        window.cd_3.setPivotY(cd3)
+        window.cd_3.setPivotX(cd3)
+        window.cd_4.setPivotY(cd4)
+        window.cd_4.setPivotX(cd4)
         window.setTouchable(false);
-    }
-})
-
-
 
-var fn = () => { }
-var id = setInterval(
-    fn, 3000
-)
-//记录按键被按下时的触摸坐标
-var x = 0,
-    y = 0;
-//记录按键被按下时的悬浮窗位置
-var windowX, windowY;
-//记录按键被按下的时间以便判断长按等动作
-var downTime;yd=false;
 
-window1.jia.setOnTouchListener(function (view, event) {
-    switch (event.getAction()) {
-        case event.ACTION_DOWN:
-            x = event.getRawX();
-            y = event.getRawY();
-            windowX = window.getX();
-            windowY = window.getY();
-            windowX1 = window1.getX();
-            windowY1 = window1.getY();
-            downTime = new Date().getTime();
-            return true;
-        case event.ACTION_MOVE:
-            if(!yd){//如果移动的距离大于h值 则判断为移动 yd为真
-                if (Math.abs(event.getRawY() - y) >move0 || Math.abs(event.getRawX() - x) > move0) {yd=true}
-                //如果按下的时间超过g值并且yd值为假判断为长按,退出脚本 
-                if (new Date().getTime() - downTime > date0_sj) {
-                    log(new Date().getTime() - downTime);
-                    exit();
-
-                    //关闭悬浮窗
-                    //window.close()
-                    //window1.close()
+        //两个悬浮窗Y值差值
+        var Y_cz = 725
+        //两个悬浮窗初始位置 
+        window.setPosition(device.width - 200, device.height - (400 + Y_cz))
+        window1.setPosition(device.width - 200, device.height - 400)
+
+        function jz() {
+            threads.start(function () {
+                if (y1) {
+                    y1 = false
+                    if (y2) {
+                        y2 = false
+                        for (let i = 0; i < 100; i++) {
+                            if (i % 2) {
+                                window1.jia.setRotation(jiaodu += 1)
+                            }
+                            window.cd_1.setPivotY(cd1 += 4)
+                            window.cd_1.setPivotX(cd1)
+                            window.cd_2.setPivotY(cd2 += 3)
+                            window.cd_2.setPivotX(cd2)
+                            window.cd_3.setPivotY(cd3 += 2)
+                            window.cd_3.setPivotX(cd3)
+                            window.cd_4.setPivotY(cd4 += 1)
+                            window.cd_4.setPivotX(cd4)
+                            sleep(sleep0)
+                        }
+                    } else {
+                        for (let i = 100; i > 0; i--) {
+                            if (i % 2) {
+                                window1.jia.setRotation(jiaodu -= 1)
+                            }
+                            window.cd_1.setPivotY(cd1 -= 4)
+                            window.cd_1.setPivotX(cd1)
+                            window.cd_2.setPivotY(cd2 -= 3)
+                            window.cd_2.setPivotX(cd2)
+                            window.cd_3.setPivotY(cd3 -= 2)
+                            window.cd_3.setPivotX(cd3)
+                            window.cd_4.setPivotY(cd4 -= 1)
+                            window.cd_4.setPivotX(cd4)
+                            sleep(sleep0)
+                        }
+                        y2 = true;
+                    }
+                    y1 = true
                 }
-            }else{//移动手指时调整两个悬浮窗位置
-
-                windowHeight = window1Height
-                windowWidth = window1Width
-
-                let xAxisMovingDistance = event.getRawX() - x;
-                let yAxisMovingDistance = event.getRawY() - y;
-                if (windowX + xAxisMovingDistance < 0) {
-                  if (windowY + yAxisMovingDistance < 0) {
-                    window.setPosition(10,
-                    windowY + (event.getRawY() - y));
-                    window1.setPosition(10,
-                    windowY + ((event.getRawY() - y)+Y_cz));
-                    console.log("触发了8")
-                  } else if (windowY + windowHeight + yAxisMovingDistance > device.height) {
-                    window.setPosition(10,
-                    device.height - windowHeight);
-                    window1.setPosition(10,
-                    device.height - windowHeight+Y_cz);
-                    console.log("触发了7")
-
-                    // window.setPosition(0, );
-                  } else {
-                    console.log("触发了6")
-                    window.setPosition(10,
-                    windowY + yAxisMovingDistance);
-                    window1.setPosition(10,
-                    windowY + yAxisMovingDistance+Y_cz);
-                    
-                    // window.setPosition(0, windowY + yAxisMovingDistance);
-                  }
-                } else if (windowX + xAxisMovingDistance > device.width - windowWidth) {
-                    
-                  if (windowY + yAxisMovingDistance < 0) {
-                    console.log("触发了5")
-                    window.setPosition(device.width - windowWidth,
-                    windowY + yAxisMovingDistance);
-                    window1.setPosition(device.width - windowWidth,
-                    windowY + yAxisMovingDistance+Y_cz);
-                    
-                  } else if (windowY + windowHeight + yAxisMovingDistance > device.height) {
-                    console.log("触发了4")
-                    window.setPosition(device.width - windowWidth,
-                        device.height - window1Height);
-                        window1.setPosition(device.width - windowWidth,
-                        device.height - windowHeight+Y_cz);
-                    // window.setPosition(device.width - windowWidth, device.height - windowHeight);
-                  } else {
-                    console.log("触发了3")
-                    window.setPosition(device.width - windowWidth,
-                        windowY + yAxisMovingDistance);
-                        window1.setPosition(device.width - windowWidth,
-                            windowY + yAxisMovingDistance+Y_cz);
-                    // window.setPosition(device.width - windowWidth, windowY + yAxisMovingDistance);
-                  }
-                } else {
-                  if (windowY + yAxisMovingDistance < 0) {
-                    console.log("触发了1")
-                    window.setPosition(windowX + xAxisMovingDistance,
-                        0);
-                        window1.setPosition(windowX + xAxisMovingDistance,
-                            0 +Y_cz);
-                    // window.setPosition(device.width - windowWidth, windowY + yAxisMovingDistance);
-                    // window.setPosition(windowX + xAxisMovingDistance, 0);
-                  } else if (windowY1 + windowHeight + yAxisMovingDistance + 50> device.height) {
-                    console.log("触发了2")
+            })
+        }
 
-                    window.setPosition(windowX + xAxisMovingDistance,
-                        device.height - windowHeight - Y_cz);
-                        window1.setPosition(windowX + xAxisMovingDistance,
-                            device.height - windowHeight  - 50);
-                    // window.setPosition(windowX + xAxisMovingDistance, device.height - windowHeight);
-                  } else {
-                    window.setPosition(windowX + xAxisMovingDistance,
-                        windowY + yAxisMovingDistance);
-                        window1.setPosition(windowX + xAxisMovingDistance,
-                            windowY + yAxisMovingDistance +Y_cz);
-                    // window.setPosition(windowX + xAxisMovingDistance, windowY + yAxisMovingDistance);
-                  }
-                }
-                
-                
+        window.cd_1.on("click", () => {
+            if (y2) {
+                toastLog("首页")
+                jz();
+                window.setTouchable(false);
             }
-            return true;
-        case event.ACTION_UP:
-            //触摸时间小于 200毫秒 则判断为 点击
-            if (new Date().getTime() - downTime < date1_sj) {
+        })
+        window.cd_2.on("click", () => {
+            if (y2) {
+                toastLog("设置")
                 jz();
-                //根据Y2值 设置悬浮窗是否可以触摸
-                if(y2){
-                    window.setTouchable(false);
-                }else{
-                    window.setTouchable(true);
-                }
+                window.setTouchable(false);
+            }
+        })
+        window.cd_3.on("click", () => {
+            if (y2) {
+                toastLog("系统")
+                jz();
+                window.setTouchable(false);
+            }
+        })
+        window.cd_4.on("click", () => {
+            if (y2) {
+                toastLog("我的")
+                jz();
+                window.setTouchable(false);
+            }
+        })
+
+
+        var fn = () => {}
+        var id = setInterval(
+            fn, 3000
+        )
+        //记录按键被按下时的触摸坐标
+        var x = 0,
+            y = 0;
+        //记录按键被按下时的悬浮窗位置
+        var windowX, windowY;
+        //记录按键被按下的时间以便判断长按等动作
+        var downTime;
+        yd = false;
+
+        window1.jia.setOnTouchListener(function (view, event) {
+            switch (event.getAction()) {
+                case event.ACTION_DOWN:
+                    x = event.getRawX();
+                    y = event.getRawY();
+                    windowX = window.getX();
+                    windowY = window.getY();
+                    downTime = new Date().getTime();
+                    return true;
+                case event.ACTION_MOVE:
+                    if (!yd) { //如果移动的距离大于h值 则判断为移动 yd为真
+                        if (Math.abs(event.getRawY() - y) > move0 || Math.abs(event.getRawX() - x) > move0) {
+                            yd = true
+                        }
+                        //如果按下的时间超过g值并且yd值为假判断为长按,退出脚本 
+                        if (new Date().getTime() - downTime > date0_sj) {
+                            log(new Date().getTime() - downTime);
+                            exit();
+
+                            //关闭悬浮窗
+                            //window.close()
+                            //window1.close()
+                        }
+                    } else { //移动手指时调整两个悬浮窗位置
+                        window.setPosition(windowX + (event.getRawX() - x),
+                            windowY + (event.getRawY() - y));
+                        window1.setPosition(windowX + (event.getRawX() - x),
+                            windowY + ((event.getRawY() - y) + Y_cz));
+
+                    }
+                    return true;
+                case event.ACTION_UP:
+                    //触摸时间小于 200毫秒 则判断为 点击
+                    if (new Date().getTime() - downTime < date1_sj) {
+                        jz();
+                        //根据Y2值 设置悬浮窗是否可以触摸
+                        if (y2) {
+                            window.setTouchable(false);
+                        } else {
+                            window.setTouchable(true);
+                        }
+                    }
+                    yd = false
+                    return true;
             }
-            yd=false
             return true;
-    }
-    return true;
-});
-var floatyObj = {}
-floatyObj.show = function(){
-    var Y_cz=725
-    //两个悬浮窗初始位置 
-    window.setPosition(50, device.height - (400+Y_cz))
-    
-    // window.setPosition(device.width - 200, device.height - (400+Y_cz))
-    window1.setPosition(50, device.height - 400)
+        });
+    })
 }
 
-floatyObj.hide = function(){
+floatyWindow.closeWindow = function(){
+    floaty.closeAll()
+} 
 
-    window.setPosition(-3000, device.height - (400+Y_cz))
-
-    // window.setPosition(device.width - 200, device.height - (400+Y_cz))
-    window1.setPosition(-3000, device.height - 400)
-}
 
-module.exports = floatyObj;
+floatyWindow.showWindow()