Administrator 2 năm trước cách đây
mục cha
commit
46562194c6
23 tập tin đã thay đổi với 840 bổ sung84 xóa
  1. 6 1
      pom.xml
  2. 105 0
      src/main/java/com/sysu/admin/api/user/ApiUserController.java
  3. 9 0
      src/main/java/com/sysu/admin/api/user/ApiUserVo.java
  4. 5 0
      src/main/java/com/sysu/admin/controller/city/City.java
  5. 7 0
      src/main/java/com/sysu/admin/controller/crop/CropLand.java
  6. 104 11
      src/main/java/com/sysu/admin/controller/crop/CropLandController.java
  7. 0 17
      src/main/java/com/sysu/admin/controller/crop/CropLandService.java
  8. 2 2
      src/main/java/com/sysu/admin/support/base/BaseComponent.java
  9. 79 0
      src/main/java/com/sysu/admin/support/sms/Sms.java
  10. 125 0
      src/main/java/com/sysu/admin/support/sms/SmsController.java
  11. 21 0
      src/main/java/com/sysu/admin/support/sms/SmsRepository.java
  12. 30 0
      src/main/java/com/sysu/admin/support/sms/SmsReqVo.java
  13. 16 0
      src/main/java/com/sysu/admin/support/sms/SmsReqVoValid.java
  14. 121 0
      src/main/java/com/sysu/admin/support/sms/SmsService.java
  15. 112 0
      src/main/java/com/sysu/admin/support/sms/aliyun/AliSmsSenderHelper.java
  16. 2 0
      src/main/java/com/sysu/admin/support/system/organ/Organ.java
  17. 2 2
      src/main/java/com/sysu/admin/support/system/organ/OrganService.java
  18. 0 14
      src/main/java/com/sysu/admin/support/system/role/SRole.java
  19. 4 2
      src/main/java/com/sysu/admin/support/system/user/User.java
  20. 35 3
      src/main/java/com/sysu/admin/utils/GenericsUtil.java
  21. 4 1
      src/main/resources/application.yml
  22. 48 29
      src/main/webapp/static/package/cityland.js
  23. 3 2
      src/main/webapp/static/package/style.js

+ 6 - 1
pom.xml

@@ -156,7 +156,12 @@
 			<version>2.5.1</version>
 		</dependency>
 
-
+		<!-- https://mvnrepository.com/artifact/com.github.zhangquanli/aliyun-sms-spring-boot-starter -->
+		<dependency>
+			<groupId>com.github.zhangquanli</groupId>
+			<artifactId>aliyun-sms-spring-boot-starter</artifactId>
+			<version>1.0.2</version>
+		</dependency>
 
 		<dependency>
 			<groupId>com.alibaba</groupId>

+ 105 - 0
src/main/java/com/sysu/admin/api/user/ApiUserController.java

@@ -0,0 +1,105 @@
+package com.sysu.admin.api.user;
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.collect.Maps;
+import com.sysu.admin.support.base.BaseComponent;
+import com.sysu.admin.support.sms.SmsReqVo;
+import com.sysu.admin.support.sms.SmsService;
+import com.sysu.admin.support.sms.aliyun.AliSmsSenderHelper;
+import com.sysu.admin.support.system.organ.Organ;
+import com.sysu.admin.support.system.role.SRole;
+import com.sysu.admin.support.system.user.User;
+import com.sysu.admin.support.system.user.UserService;
+import com.xiesx.fastboot.base.result.BaseResult;
+import com.xiesx.fastboot.base.result.R;
+import com.xiesx.fastboot.core.token.JwtHelper;
+import com.xiesx.fastboot.core.token.cfg.TokenCfg;
+import com.xiesx.fastboot.core.token.handle.CurrentToken;
+import io.jsonwebtoken.Claims;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.xmlbeans.impl.xb.ltgfmt.FileDesc;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Date;
+import java.util.Map;
+
+@RequestMapping("/api/user")
+@RestController
+@Slf4j
+public class ApiUserController extends BaseComponent {
+    @Autowired
+    AliSmsSenderHelper mSmsSenderHelper;
+    @Autowired
+    SmsService mSmsService;
+    @Autowired
+    UserService userService;
+    /**
+     * 会员登录并返回用户信息集合
+     * @return
+     */
+    @PostMapping("/login")
+    public BaseResult login(@RequestBody String data) {
+        SmsReqVo sms = JSON.parseObject(data, SmsReqVo.class);
+        if(StringUtils.isNotEmpty(sms.getToken())){
+            return R.succ(getTokenUser(sms.getToken()));
+        }else{
+            if(ObjectUtils.isEmpty(sms.getCode())){
+                return R.fail("请输入验证码!");
+            }
+            log.warn("正在登陆:" + sms.getMobile() + " 验证码:" + sms.getCode());
+            // 判断验证码
+            BaseResult smsRes = mSmsService.validate(sms.getMobile(), sms.getCode());
+            if (smsRes.isFail()) {
+                return smsRes;
+            }
+            return R.succ(getUser(sms.getCode(), sms.getMobile()));
+        }
+
+    }
+
+    private User getTokenUser(String token){
+        mSmsSenderHelper.checkToken(token);
+        CurrentToken currentToken = CurrentToken.getCurrentToken(token);
+        Long userId = Long.valueOf(currentToken.getUserId());
+        User user = userService.findOne(userId);
+        Map<String, Object> claims = Maps.newConcurrentMap();
+        claims.put(TokenCfg.USERID, user.getId());
+        claims.put(TokenCfg.USERNAME, user.getUsername());
+        String newToken = JwtHelper.create("sysuimars", "api", claims, JwtHelper.JWT_EXPIRE_D_1 * 20);
+        user.setToken(newToken);
+        return user;
+    }
+
+    public static void main(String[] args) {
+        Map<String, Object> claims = Maps.newConcurrentMap();
+        claims.put(TokenCfg.USERID, 380402566221008896L);
+        claims.put(TokenCfg.USERNAME, "13797066447");
+        String newToken = JwtHelper.create("sysuimars", "api", claims, JwtHelper.JWT_EXPIRE_D_1 * 20);
+        AliSmsSenderHelper mSmsSenderHelper = new AliSmsSenderHelper();
+        mSmsSenderHelper.checkToken(newToken);
+    }
+
+    private User getUser(String code, String mobile){
+        User user = userService.findByUsername(mobile);
+        if(user == null) {
+            user = new User().setCode(code).setUsername(mobile).setIsBlack(0).setIsDel(0).setIsEnable(0)
+                    .setRoleId((long) SRole.RoleEnum.zjxc.ordinal()).setNickname("")
+                    .setPassword(DigestUtils.md5Hex(mobile + code)).setOrganId(Organ.defaultOrgan);
+            userService.saveAndFlush(user);
+        }
+        Map<String, Object> claims = Maps.newConcurrentMap();
+        claims.put(TokenCfg.USERID, user.getId());
+        claims.put(TokenCfg.USERNAME, user.getUsername());
+        String token = JwtHelper.create("sysuimars", "api", claims, JwtHelper.JWT_EXPIRE_D_30);
+        user.setToken(token);
+        return user;
+    }
+}

+ 9 - 0
src/main/java/com/sysu/admin/api/user/ApiUserVo.java

@@ -0,0 +1,9 @@
+package com.sysu.admin.api.user;
+
+import com.sysu.admin.support.sms.SmsReqVo;
+import lombok.Data;
+
+@Data
+public class ApiUserVo extends SmsReqVo {
+
+}

+ 5 - 0
src/main/java/com/sysu/admin/controller/city/City.java

@@ -10,6 +10,7 @@ import org.hibernate.annotations.DynamicUpdate;
 import org.locationtech.jts.geom.MultiPolygon;
 
 import javax.persistence.*;
+import java.util.List;
 
 @Data
 @Accessors(chain = true)
@@ -34,4 +35,8 @@ public class City{
     @Column()
     private Integer code;
 
+    @Transient
+    @JSONField(serialize = false)
+    private List<District> districtList;
+
 }

+ 7 - 0
src/main/java/com/sysu/admin/controller/crop/CropLand.java

@@ -79,6 +79,9 @@ public class CropLand {
     private Date createDate;
 
     @Column(nullable = false)
+    private Date updateDate;
+
+    @Column(nullable = false)
     private Date receiveDate;
 
     @Column(nullable = false)
@@ -121,6 +124,10 @@ public class CropLand {
     private Integer city;
     @Column
     private Integer district;
+    @Column
+    private String name;
+    @Column
+    private String address;
 
 
 }

+ 104 - 11
src/main/java/com/sysu/admin/controller/crop/CropLandController.java

@@ -1,15 +1,21 @@
 package com.sysu.admin.controller.crop;
 
 import com.alibaba.fastjson.JSON;
+import com.querydsl.core.BooleanBuilder;
+import com.querydsl.core.types.Predicate;
+import com.querydsl.core.types.dsl.BooleanExpression;
+import com.querydsl.core.types.dsl.PathBuilder;
+import com.querydsl.jpa.impl.JPAUpdateClause;
 import com.sysu.admin.api.crop.CropVo;
-import com.sysu.admin.controller.city.District;
-import com.sysu.admin.controller.city.DistrictRepository;
+import com.sysu.admin.controller.city.*;
 import com.sysu.admin.controller.crop.CropLand;
 import com.sysu.admin.controller.crop.CropLandService;
 import com.sysu.admin.controller.crop.CropLandVo;
 import com.sysu.admin.controller.geo.land.LandTaskStatus;
 import com.sysu.admin.support.base.BaseVo;
+import com.sysu.admin.support.base.ServiceContext;
 import com.sysu.admin.support.shiro.ShiroService;
+import com.sysu.admin.utils.GenericsUtil;
 import com.sysu.admin.utils.shape.GeoCastUtil;
 import com.xiesx.fastboot.base.result.BaseResult;
 import com.xiesx.fastboot.base.result.R;
@@ -17,21 +23,25 @@ import com.xiesx.fastboot.utils.CopyUtils;
 import org.locationtech.jts.geom.MultiPolygon;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.transaction.Transactional;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 /**
  * 读取地图数据信息
  */
 @RequestMapping("/crop")
 @Controller
-public class CropLandController {
+public class CropLandController extends ServiceContext {
 
     @Autowired
     CropLandService cityLandService;
@@ -39,6 +49,8 @@ public class CropLandController {
     ShiroService shiroService;
     @Autowired
     DistrictRepository districtRepository;
+    @Autowired
+    CityRepository cityRepository;
 
     @RequestMapping("/getInfo")
     @ResponseBody
@@ -72,6 +84,18 @@ public class CropLandController {
         return R.succ(bean);
     }
 
+    @RequestMapping("/publish")
+    @ResponseBody
+    public BaseResult publish(CropLandVo vo){
+        CropLand bean = cityLandService.findOne(vo.getId());
+        if(bean.getStatus().intValue() != LandTaskStatus.unpublished.ordinal()){
+            return R.fail("不是未发布的地块!");
+        }
+        bean.setStatus(LandTaskStatus.published.ordinal());
+        cityLandService.save(bean);
+        return R.succ();
+    }
+
 
 
     @RequestMapping("/publish_index")
@@ -81,8 +105,27 @@ public class CropLandController {
 
     @RequestMapping("/batchPublish")
     @ResponseBody
+    @Transactional
     public BaseResult batchPublish(CropLandVo vo){
-
+        QCropLand qCropLand = QCropLand.cropLand;
+        JPAUpdateClause jpaUpdateClause = mJPAQueryFactory.update(qCropLand);
+        jpaUpdateClause.set(qCropLand.status, LandTaskStatus.published.ordinal());
+        jpaUpdateClause.set(qCropLand.updateDate, new Date());
+        Predicate predicate = null;
+        if(vo.getProvinceId() != null){
+            predicate = qCropLand.province.eq(vo.getProvinceId());
+        }
+        if(vo.getCityId() != null){
+            predicate = qCropLand.city.eq(vo.getCityId()).and(predicate);
+        }
+        if(vo.getDistrictId() != null){
+            predicate = qCropLand.district.eq(vo.getDistrictId()).and(predicate);
+        }
+        if(predicate != null){
+            predicate = qCropLand.status.eq(LandTaskStatus.unpublished.ordinal()).and(predicate);
+            jpaUpdateClause.where(predicate);
+            jpaUpdateClause.execute();
+        }
         return R.succ();
     }
 
@@ -101,17 +144,67 @@ public class CropLandController {
         return R.succ();
     }
 
-    @Transactional
-    public BaseResult saveTest(){
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                cityLandService.saveCityAll();
+    Executor executor = Executors.newFixedThreadPool(10);
+    int size = 0;
+
+    @RequestMapping("/saveTestAll")
+    @ResponseBody
+    public BaseResult saveTestAll(){
+        QCropLand qCropLand = QCropLand.cropLand;
+        List<CropLand> landList = cityLandService.findAll(qCropLand.district.isNull());
+        List<District> districtList = districtRepository.findAll(Sort.by(District.FIELDS.code));
+        List<City> cityList = cityRepository.findAll(Sort.by(City.FIELDS.code));
+        int i=0;
+        for(City city : cityList){
+            List<District> districts = new ArrayList<>();
+            while(i < districtList.size()){
+                if(city.getCode() / 100 == districtList.get(i).getCode() / 100){
+                    districts.add(districtList.get(i));
+                    i++;
+                }else{
+                    break;
+                }
             }
-        });
+            city.setDistrictList(districts);
+        }
+        size = landList.size();
+        System.out.println("landList load finnish");
+        GenericsUtil<CropLand> genericsUtil = new GenericsUtil<>(CropLand.class);
+        List<List<CropLand>> list = genericsUtil.subListBySegment(landList, 10);
+        for(List<CropLand> cropLandList : list){
+            executor.execute(() -> {
+                for(CropLand bean : cropLandList){
+                    District district = withinDistrict(cityList, bean);
+                    if(district != null){
+                        cityLandService.setCity(bean, district);
+                        cityLandService.save(bean);
+                        synchronized (this) {
+                            System.out.println("剩余:" + (--size));
+                        }
+                    }
+                }
+            });
+        }
         return R.succ();
     }
 
+    private District withinDistrict(List<City> cityList, CropLand bean){
+        for(City city : cityList){
+            if(bean.getCenterPoint() == null){
+                bean.setCenterPoint(cityLandService.getCenterPoint(bean.getGeom()));
+            }
+            if(bean.getCenterPoint().within(city.getGeom())){
+                for(District district : city.getDistrictList()){
+                    if(bean.getCenterPoint().within(district.getGeom())){
+                        return district;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+
 }
 
 

+ 0 - 17
src/main/java/com/sysu/admin/controller/crop/CropLandService.java

@@ -149,23 +149,6 @@ public class CropLandService extends BaseService<CropLand, Long> {
         return newFileName;
     }
 
-    @Transactional
-    public void saveCityAll(){
-        QCropLand qCropLand = QCropLand.cropLand;
-        List<CropLand> landList = findAll(qCropLand.district.isNull());
-        System.out.println("landList load finnish");
-        int size = landList.size();
-        for(CropLand bean : landList){
-            bean.getCenterPoint().setSRID(4326);
-            District district = districtRepository.findByPoint(bean.getCenterPoint());
-            if(district != null){
-                setCity(bean, district);
-                System.out.println("剩余:" + (--size));
-            }
-        }
-        saveAll(landList);
-    }
-
     @Override
     public JpaPlusRepository<CropLand, Long> r() {
         return mCropLandRepository;

+ 2 - 2
src/main/java/com/sysu/admin/support/base/BaseComponent.java

@@ -19,10 +19,10 @@ public class BaseComponent {
 
 
 
-    protected void validate(@Valid Object obj) {
+    protected void validate(@Valid Object obj, Class... groups) {
         Set<ConstraintViolation<Object>> validateSet = Validation.buildDefaultValidatorFactory()
                 .getValidator()
-                .validate(obj, new Class[0]);
+                .validate(obj, groups);
         if (!CollectionUtils.isEmpty(validateSet)) {
             String messages = validateSet.stream()
                     .map(ConstraintViolation::getMessage)

+ 79 - 0
src/main/java/com/sysu/admin/support/sms/Sms.java

@@ -0,0 +1,79 @@
+package com.sysu.admin.support.sms;
+
+import com.xiesx.fastboot.core.jpa.entity.JpaPlusEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import lombok.experimental.FieldNameConstants;
+import org.hibernate.annotations.*;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @title Sms.java (generator)
+ * @description 短信
+ * @author 谢思贤
+ * @date 2020-05-28
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@FieldNameConstants(innerTypeName = "FIELDS")
+@Table(name = "sys_sms")
+@Entity
+@EntityListeners(AuditingEntityListener.class)
+@DynamicInsert
+@DynamicUpdate
+@Where(clause = "is_use=0")
+@SQLDelete(sql = "update sys_sms set is_use=1 where id = ?")
+@SQLDeleteAll(sql = "update sys_sms set is_use=1 where id = ?")
+public class Sms extends JpaPlusEntity<Sms> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @GeneratedValue(generator = "idGenerator")
+    @GenericGenerator(name = "idGenerator", strategy = "com.xiesx.fastboot.core.jpa.identifier.IdWorkerGenerator")
+    private Long id;
+
+    /**
+     * 手机号
+     */
+    @Column
+    private String mobile;
+
+    /**
+     * 验证码
+     */
+    @Column
+    private String code;
+
+    /**
+     * 创建时间
+     */
+    @Column
+    private Date createDate;
+
+    /**
+     * 过期时间
+     */
+    @Column
+    private Date expireDate;
+
+    /**
+     * 是否使用(0:未使用、1:已使用、2:已过期)
+     */
+    @Column
+    private Integer isUse;
+
+    public boolean isExpried() {
+        return new Date().after(expireDate);
+    }
+}

+ 125 - 0
src/main/java/com/sysu/admin/support/sms/SmsController.java

@@ -0,0 +1,125 @@
+package com.sysu.admin.support.sms;
+
+import com.alibaba.fastjson.JSON;
+import com.github.zhangquanli.aliyun.sms.response.SendSmsResponse;
+import com.google.common.collect.Maps;
+import com.sysu.admin.support.base.BaseComponent;
+import com.sysu.admin.support.base.ServiceContext;
+import com.sysu.admin.support.sms.aliyun.AliSmsSenderHelper;
+import com.xiesx.fastboot.base.result.BaseResult;
+import com.xiesx.fastboot.base.result.R;
+import com.xiesx.fastboot.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpSession;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * @title SmsController
+ * @description
+ * @author XIE
+ * @date 2020年4月24日下午10:10:33
+ */
+@Validated
+@RestController
+@RequestMapping(value = "/api/sms")
+public class SmsController extends BaseComponent {
+
+    @Autowired
+    SmsService mSmsService;
+
+    @Autowired
+    SmsRepository mSmsRepository;
+
+    @Autowired
+    AliSmsSenderHelper mSmsSenderHelper;
+
+    /**
+     * 发送短信
+     *
+     * @param data
+     * @return
+     */
+    @RequestMapping("/test")
+    public BaseResult test(@RequestBody String data) {
+        SmsReqVo req = JSON.parseObject(data, SmsReqVo.class);
+        super.validate(req, SmsReqVoValid.SmsSendValid.class);
+        // 生成验证码
+        String code = String.valueOf(new Random().nextInt(899999) + 100000);
+        // 先把未使用的删除
+        List<Sms> list = mSmsRepository.findByMobile(req.getMobile());
+        for (Sms sms : list) {
+            mSmsRepository.delete(sms);
+        }
+        // 存储到db,web、api都可以用,单纯web可以用session
+        Sms sms = new Sms();
+        sms.setMobile(req.getMobile());
+        sms.setCode(code);
+        sms.setIsUse(0);
+        sms.setCreateDate(new Date());
+        sms.setExpireDate(DateUtils.addMinutes(sms.getCreateDate(), 5));
+        int row = mSmsRepository.insertOrUpdate(sms);
+        Map<String, Object> map = Maps.newHashMap();
+        map.put("code", code);
+        map.put("date", new Date());
+        // return (row >= 1) ? R.succ("发送成功:", map) : R.fail("发送失败", map);
+        return (row >= 1) ? R.succ("发送成功",map) : R.fail("发送失败");
+    }
+
+    /**
+     * 发送短信
+     *
+     * @param data
+     * @return
+     */
+    @RequestMapping("/send")
+    public BaseResult send(@RequestBody String data) {
+        SmsReqVo req = JSON.parseObject(data, SmsReqVo.class);
+        super.validate(req, SmsReqVoValid.SmsSendValid.class);
+        // 生成验证码
+        String code = String.valueOf(new Random().nextInt(899999) + 100000);
+        // 发送验证码
+        SendSmsResponse response = mSmsSenderHelper.sendSms(req.getMobile(), req.getTemplate(), code);
+        if (response.getCode().equals("OK")) {
+            // 先把未使用的删除
+            List<Sms> list = mSmsRepository.findByMobile(req.getMobile());
+            for (Sms sms : list) {
+                mSmsRepository.delete(sms);
+            }
+            // 存储到db,web、api都可以用,单纯web可以用session
+            Sms sms = new Sms();
+            sms.setMobile(req.getMobile());
+            sms.setCode(code);
+            sms.setCreateDate(new Date());
+            sms.setIsUse(0);
+            sms.setExpireDate(DateUtils.addMinutes(sms.getCreateDate(), 5));
+            int row = mSmsRepository.insertOrUpdate(sms);
+            Map<String, Object> map = Maps.newHashMap();
+            map.put("code", code);
+            map.put("date", new Date());
+            return (row >= 1) ? R.succ("发送成功", map) : R.fail("发送失败", map);
+        } else {
+            return R.fail("发送失败");
+        }
+    }
+
+    /**
+     * 查询短信
+     *
+     * @param req
+     * @return
+     */
+    @ResponseBody
+    @RequestMapping("/validate")
+    public BaseResult validate(@Validated(value = SmsReqVoValid.SmsCheckValid.class) SmsReqVo req) {
+        return mSmsService.validate(req.getMobile(), req.getCode());
+    }
+}

+ 21 - 0
src/main/java/com/sysu/admin/support/sms/SmsRepository.java

@@ -0,0 +1,21 @@
+package com.sysu.admin.support.sms;
+
+import com.xiesx.fastboot.core.jpa.JpaPlusRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+public interface SmsRepository extends JpaPlusRepository<Sms, Long> {
+
+    List<Sms> findByMobile(String mobile);
+
+    @Query(value = "select * from sys_sms where mobile = ?1 and is_use=0  order by create_date desc limit 1", nativeQuery = true)
+    Sms lastSend(String mobile);
+
+    @Transactional
+    @Modifying
+    @Query(value = "update sys_sms set is_use=2 where id = ?1", nativeQuery = true)
+    int expire(Long id);
+}

+ 30 - 0
src/main/java/com/sysu/admin/support/sms/SmsReqVo.java

@@ -0,0 +1,30 @@
+package com.sysu.admin.support.sms;
+
+import com.sysu.admin.support.base.BaseVo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotEmpty;
+
+/**
+ * @title SmsReqVO
+ * @description
+ * @author XIE
+ * @date 2020年4月24日下午10:10:10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class SmsReqVo extends BaseVo {
+
+    @NotEmpty(groups = {SmsReqVoValid.SmsCheckValid.class, SmsReqVoValid.SmsSendValid.class},message = "手机号为空")
+    private String mobile;
+
+    @NotEmpty(groups = {SmsReqVoValid.SmsCheckValid.class},message = "验证码为空")
+    private String code;
+
+    private String name;
+
+    private String template = "SMS_187310747";
+
+    private String token;
+}

+ 16 - 0
src/main/java/com/sysu/admin/support/sms/SmsReqVoValid.java

@@ -0,0 +1,16 @@
+package com.sysu.admin.support.sms;
+
+/**
+ * @title SmsReqVOValid
+ * @description
+ * @author XIE
+ * @date 2020年4月24日下午10:10:17
+ */
+public interface SmsReqVoValid {
+
+    public interface SmsCheckValid {
+    }
+
+    public interface SmsSendValid {
+    }
+}

+ 121 - 0
src/main/java/com/sysu/admin/support/sms/SmsService.java

@@ -0,0 +1,121 @@
+package com.sysu.admin.support.sms;
+
+import com.alibaba.fastjson.JSONObject;
+import com.github.zhangquanli.aliyun.sms.response.SendSmsResponse;
+import com.google.common.collect.Maps;
+import com.sysu.admin.support.base.BaseService;
+import com.sysu.admin.support.sms.aliyun.AliSmsSenderHelper;
+import com.sysu.admin.support.system.config.SConfig;
+import com.xiesx.fastboot.base.result.BaseResult;
+import com.xiesx.fastboot.base.result.R;
+import com.xiesx.fastboot.core.jpa.JpaPlusRepository;
+import com.xiesx.fastboot.utils.DateUtils;
+import lombok.NonNull;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * @title GameServiceImpl.java
+ * @description 游戏表 业务类
+ * @author 谢思贤
+ * @date 2020-04-30
+ */
+@Service
+public class SmsService extends BaseService<Sms, Long> {
+
+    @Lazy
+    @Autowired
+    AliSmsSenderHelper aliSmsSenderHelper;
+
+
+    @Lazy
+    @Autowired
+    SmsRepository mSmsRepository;
+
+    public BaseResult validate(@NonNull String mobile, @NonNull String code) {
+
+        SConfig config = serviceContext.mSConfigService.get("test");
+        if(config != null && config.getRemark().equals("1")){
+            JSONObject jsonObject = JSONObject.parseObject(config.getV());
+            String testUser = jsonObject.getString("user");
+            if(testUser.equals(mobile)){
+                String testCode = jsonObject.getString("code");
+                if(testUser.equals(mobile) && testCode.equals(code)) {
+                    return R.succ("操作成功");
+                }else{
+                    return R.fail("验证码不匹配!");
+                }
+            }
+        }
+
+        Sms sms = mSmsRepository.lastSend(mobile);
+        if (StringUtils.isEmpty(code)) {
+            return R.fail("验证码不能为空");
+        } else if (ObjectUtils.isEmpty(sms)) {
+            return R.fail("请先获取验证码");
+        } else if (!StringUtils.equals(sms.getCode(), code)) {
+            return R.fail("验证码不匹配");
+        } else if (sms.isExpried()) {
+            mSmsRepository.expire(sms.getId());
+            return R.fail("验证码已过期");
+        } else {
+            mSmsRepository.delete(sms);
+            return R.succ("操作成功");
+        }
+    }
+
+    public BaseResult send(String mobile, String template){
+        // 生成验证码
+        String code = String.valueOf(new Random().nextInt(899999) + 100000);
+        // 发送验证码
+        SendSmsResponse response = aliSmsSenderHelper.sendSms(mobile, template, code);
+        if (response.getCode().equals("OK")) {
+            // 先把未使用的删除
+            List<Sms> list = findByMobile(mobile);
+            for (Sms sms : list) {
+                mSmsRepository.delete(sms);
+            }
+            // 存储到db,web、api都可以用,单纯web可以用session
+            Sms sms = new Sms();
+            sms.setMobile(mobile);
+            sms.setCode(code);
+            sms.setCreateDate(new Date());
+            sms.setExpireDate(DateUtils.addMinutes(sms.getCreateDate(), 5));
+            mSmsRepository.save(sms);
+            Map<String, Object> map = Maps.newHashMap();
+            map.put("code", response.getCode());
+            map.put("date", new Date());
+            return R.succ("发送成功", map);
+        } else {
+            Map<String, Object> map = Maps.newHashMap();
+            map.put("code", response.getCode());
+            map.put("date", new Date());
+            return R.fail(AliSmsSenderHelper.getMessage(response.getMessage()), map);
+        }
+    }
+
+    public List<Sms> findByMobile(String mobile){
+        return mSmsRepository.findByMobile(mobile);
+    }
+
+    public Sms lastSend(String mobile){
+        return mSmsRepository.lastSend(mobile);
+    }
+
+    public int expire(Long id){
+        return mSmsRepository.expire(id);
+    }
+
+    @Override
+    public JpaPlusRepository<Sms, Long> r() {
+        return mSmsRepository;
+    }
+}

+ 112 - 0
src/main/java/com/sysu/admin/support/sms/aliyun/AliSmsSenderHelper.java

@@ -0,0 +1,112 @@
+package com.sysu.admin.support.sms.aliyun;
+
+import com.alibaba.fastjson.JSON;
+import com.github.zhangquanli.aliyun.sms.AliyunSms;
+import com.github.zhangquanli.aliyun.sms.request.QuerySendDetailsRequest;
+import com.github.zhangquanli.aliyun.sms.request.SendSmsRequest;
+import com.github.zhangquanli.aliyun.sms.response.QuerySendDetailsResponse;
+import com.github.zhangquanli.aliyun.sms.response.SendSmsResponse;
+import com.google.common.collect.Maps;
+import com.sysu.admin.utils.TextUtil;
+import com.xiesx.fastboot.core.exception.RunExc;
+import com.xiesx.fastboot.core.exception.RunException;
+import com.xiesx.fastboot.core.token.JwtHelper;
+import com.xiesx.fastboot.core.token.cfg.TokenCfg;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @title SmsSenderHelper
+ * @description
+ * @author XIE
+ * @date 2020年4月26日下午6:44:33
+ */
+@Component
+@Slf4j
+public class AliSmsSenderHelper {
+
+    @Autowired
+    AliyunSms mAliyunSms;
+
+    /**
+     * @param bizId: 短信对象的对应的bizId
+     * @param phoneNumber: 手机号
+     * @param pageSize: 分页大小
+     * @param currentPage: 当前页码
+     * @author XIE
+     * @Description: 查询发送短信的内容
+     */
+    public QuerySendDetailsResponse querySms(String bizId, String phoneNumber, Long pageSize, Long currentPage) {
+        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
+        QuerySendDetailsRequest.Builder builder = QuerySendDetailsRequest.builder();
+        builder.bizId(bizId);
+        builder.phoneNumber(phoneNumber);
+        builder.pageSize(pageSize);
+        builder.currentPage(currentPage);
+        builder.sendDate(ft.format(new Date()));
+        return mAliyunSms.querySendDetails(builder.build());
+    }
+
+    /**
+     * @param phoneNumbers: 手机号
+     * @param templateCode: 阿里云短信模板code
+     * @author XIE
+     * @Description: 对接阿里云短信服务实现短信发送 发送验证码类的短信时,每个号码每分钟最多发送一次,每个小时最多发送5次。其它类短信频控请参考阿里云
+     * @return
+     */
+    public SendSmsResponse sendSms(String phoneNumbers, String templateCode, String code) {
+        Map<String, String> map = Maps.newHashMap();
+        map.put("code", code);
+        SendSmsRequest.Builder builder = SendSmsRequest.builder();
+        builder.phoneNumbers(phoneNumbers);
+        builder.signName("智聪教育");
+        builder.templateCode(templateCode);
+        builder.templateParam(JSON.toJSONString(map));
+        // builder.smsUpExtendCode(null);
+        // builder.outId(null);
+        return mAliyunSms.sendSms(builder.build());
+    }
+
+
+    public static String getMessage(String msg){
+        String code = TextUtil.rightSubstring(":",msg);
+        if(code != null){
+            if(code.equals("1")){
+                return "每分钟只能发送一条短信";
+            }else if(code.equals("5")){
+                return "每小时钟只能发送5条短信";
+            }else if(code.equals("10")){
+                return "每天只能发送10条短信";
+            }
+        }
+        return msg;
+    }
+
+    public String checkToken(String token){
+        try {
+            // 获取token
+            Claims claims = JwtHelper.parser(token);
+            // 设置request
+            String mobile = claims.getOrDefault(TokenCfg.USERNAME,"").toString();
+            return mobile;
+        } catch (Exception e) {
+            log.error("jwt token error", e);
+            if (e instanceof ExpiredJwtException) {
+                throw new RunException(RunExc.TOKEN, "请重新登录");
+            } else {
+                throw new RunException(RunExc.TOKEN);
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        AliSmsSenderHelper a =new AliSmsSenderHelper();
+        a.sendSms("13797066447","SMS_188515112", "1234");
+    }
+}

+ 2 - 0
src/main/java/com/sysu/admin/support/system/organ/Organ.java

@@ -40,6 +40,8 @@ public class Organ extends JpaPlusEntity<Organ> {
 
     private static final long serialVersionUID = 1L;
 
+    public static final long defaultOrgan = 10216L;
+
     /**
      * 主键
      */

+ 2 - 2
src/main/java/com/sysu/admin/support/system/organ/OrganService.java

@@ -61,8 +61,8 @@ public class OrganService extends BaseService<Organ, Long> {
 
             UserRole userRole = new UserRole().setPk(new PKUR().users(user.getId())
                     .roles(organ.getIsBureau() == 1 ?
-                            SRole.RoleEnum.valueOf(SRole.RoleEnum.xjzf) :
-                            SRole.RoleEnum.valueOf(SRole.RoleEnum.zjxc)));
+                            (long)SRole.RoleEnum.xjzf.ordinal() :
+                            (long)SRole.RoleEnum.zjxc.ordinal()));
             mUserRoleRepository.save(userRole);
         });
     }

+ 0 - 14
src/main/java/com/sysu/admin/support/system/role/SRole.java

@@ -33,20 +33,6 @@ public class SRole extends JpaPlusEntity<SRole> {
 
     public enum RoleEnum {
         admin, sjzf, xjzf, zjxc;
-
-        public static long valueOf(RoleEnum roleEnum){
-            switch (roleEnum){
-                case admin:
-                    return 1;
-                case sjzf:
-                    return 2;
-                case xjzf:
-                    return 3;
-                case zjxc:
-                    return 4;
-            }
-            throw new RuntimeException();
-        }
     }
 
     private static final long serialVersionUID = 1L;

+ 4 - 2
src/main/java/com/sysu/admin/support/system/user/User.java

@@ -45,7 +45,8 @@ public class User extends JpaPlusEntity<User> {
      * 主键
      */
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GeneratedValue(generator = "idGenerator")
+    @GenericGenerator(name = "idGenerator", strategy = "com.xiesx.fastboot.core.jpa.identifier.IdWorkerGenerator")
     private Long id;
 
     /**
@@ -151,7 +152,8 @@ public class User extends JpaPlusEntity<User> {
      */
     @Transient
     private String session_key;
-
+    @Transient
+    private String token;
     @Transient
     private Map<String , Object> extData;
 }

+ 35 - 3
src/main/java/com/sysu/admin/utils/GenericsUtil.java

@@ -180,8 +180,40 @@ public class GenericsUtil<T> {
 		return ids.toString();
 	}
 
-	
-	
-	
+
+	/**
+	 * 分隔数组 根据段数分段 <多出部分在最后一个数组>
+	 *
+	 * @param data     被分隔的数组
+	 * @param segments 需要分隔的段数
+	 * @return
+	 */
+	public List<List<T>> subListBySegment(List<T> data, int segments) {
+		List<List<T>> result = new ArrayList<>();
+
+		int size = data.size();// 数据长度
+
+		if (size > 0 && segments > 0) {// segments == 0 ,不需要分隔
+
+			int count = size / segments;// 每段数量
+
+			List<T> cutList = null;// 每段List
+
+			for (int i = 0; i < segments; i++) {
+				if (i == segments - 1) {
+					cutList = data.subList(count * i, size);
+				} else {
+					cutList = data.subList(count * i, count * (i + 1));
+				}
+				result.add(cutList);
+			}
+		} else {
+			result.add(data);
+		}
+		return result;
+	}
+
+
+
 
 }

+ 4 - 1
src/main/resources/application.yml

@@ -20,7 +20,10 @@ spring:
       max-request-size: 1025MB
   messages:
     basename: i18n/message
-
+aliyun:
+  sms:
+    access-key-id: LTAI4G9aX4XJVWtxct5QvQwH
+    access-key-secret: emiM7D7AMtnRl0OXY4H0nsuJhdtKlf
 fastboot:
   sign:
     # 默认值:sign

+ 48 - 29
src/main/webapp/static/package/cityland.js

@@ -116,10 +116,22 @@ CityLandAction.prototype = {
             geometry: new ol.geom.Point(extent)
         });
         point.set("isPoint",1)
-        point.set("id",cityLand.id)
+        point.setId(cityLand.id)
+        point.set("status",cityLand.status)
         let source = this.tempVectorLayer.getSource();
         source.addFeature(point)
     },
+    // addFieldPoint(f){
+    //     let centerPoint = f.get("center_point")
+    //     let point = new ol.Feature({
+    //         geometry: new ol.geom.Point(extent)
+    //     });
+    //     point.set("isPoint",1)
+    //     point.setId(cityLand.id)
+    //     point.set("status",cityLand.status)
+    //     let source = this.tempVectorLayer.getSource();
+    //     source.addFeature(point)
+    // },
     selectedCountry(f){
         let stroke = new ol.style.Stroke({
             color: 'rgba(200,20,20,0.8)',
@@ -132,39 +144,46 @@ CityLandAction.prototype = {
             stroke: stroke,
             fill: fill
         });
-        const style2 = new ol.style.Style({
-            text:new ol.style.Text({
-                text:f.get("id"),
-                stroke: new ol.style.Stroke({
-                    color: 'rgba(239,236,236)',
-                    width: 1,
-                }),
-                fill: new ol.style.Fill({
-                    color: 'rgba(239,236,236)',
-                }),
-                font:"16px sans-serif"
-            }),
-            image: new ol.style.RegularShape({
-                stroke: new ol.style.Stroke({
-                    color: 'rgb(7,31,250)',
-                    width: 2,
-                }),
-                fill: new ol.style.Fill({
-                    color: 'rgb(7,72,238)',
-                }),
-                radius: 15,
-                points:20,
-                angle: 0
-            })
-        });
-        return f.get("isPoint") ? style2 : style1
+        return f.get("isPoint") ? globalStyle.pointStyle(f) : style1
     }
     ,loadTempVectorLayer(){
         let map = this.context.currentMap
+        let baseUrl = this.context.local_wfs_path
+        const vectorSource = new ol.source.Vector({
+            format: new ol.format.GeoJSON(),
+            loader: function(extent, resolution, projection, success, failure) {
+                const proj = projection.getCode();
+                const url = baseUrl + '?service=WFS&' +
+                    'version=1.1.0&request=GetFeature&typename=wuhan:p_crop&' +
+                    'outputFormat=application/json&srsname=' + proj + '&' +
+                    'bbox=' + extent.join(',') + ',' + proj;
+                const xhr = new XMLHttpRequest();
+                xhr.open('GET', url);
+                const onError = function() {
+                    vectorSource.removeLoadedExtent(extent);
+                    failure();
+                }
+                xhr.onerror = onError;
+                xhr.onload = function() {
+                    if (xhr.status == 200) {
+                        const features = vectorSource.getFormat().readFeatures(xhr.responseText);
+                        vectorSource.addFeatures(features);
+                        success(features);
+                    } else {
+                        onError();
+                    }
+                }
+                xhr.send();
+            },
+            strategy: ol.loadingstrategy.bbox,
+        });
+
         return new ol.layer.Vector({
             map: map,
-            source: new ol.source.Vector(),
+            source:vectorSource,
             style: this.selectedCountry,
+            minZoom:15,
+            maxZoom:20
         });
     },
     landType:{
@@ -189,7 +208,7 @@ CityLandAction.prototype = {
         return html
     },
     saveTask(that, feature){
-        layui.tool.submit("/crop/save",{"status":1,"id":feature.get("id")},function(res){
+        layui.tool.submit("/crop/publish",{"id":feature.get("id")},function(res){
             if(res.code == 0){
                 that.addFieldPointOfTempLayer(res.data)
             }

+ 3 - 2
src/main/webapp/static/package/style.js

@@ -8,6 +8,7 @@ let globalStyle = {
         });
     },
     pointStyle(f){
+        let colors = ['rgb(7,31,250)','rgb(7,31,250)','rgb(250,189,7)','rgb(7,250,11)']
         return new ol.style.Style({
             text:new ol.style.Text({
                 text:f.getId(),
@@ -22,11 +23,11 @@ let globalStyle = {
             }),
             image: new ol.style.RegularShape({
                 stroke: new ol.style.Stroke({
-                    color: 'rgb(7,31,250)',
+                    color: colors[f.get('status')],
                     width: 2,
                 }),
                 fill: new ol.style.Fill({
-                    color: 'rgb(7,72,238)',
+                    color: colors[f.get('status')],
                 }),
                 radius: 15,
                 points:20,