drew 5 жил өмнө
parent
commit
98b4ae9bdd

+ 30 - 11
src/main/java/com/izouma/awesomeAdmin/domain/District.java

@@ -1,13 +1,14 @@
 package com.izouma.awesomeAdmin.domain;
 
+import com.izouma.awesomeAdmin.annotations.Searchable;
+import com.izouma.awesomeAdmin.enums.DistrictLevel;
 import io.swagger.annotations.ApiModel;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.persistence.Entity;
-import javax.persistence.Id;
+import javax.persistence.*;
 
 @Data
 @Entity
@@ -17,14 +18,32 @@ import javax.persistence.Id;
 @ApiModel("行政区域")
 public class District extends AuditedEntity {
     @Id
-    private Long    id;
-    private String  name;
-    private String  fullName;
-    private double  lat;
-    private double  lng;
-    private String  pinyin;
-    private int     level;
-    private Long    parent;
-    private boolean leaf;
+    private Long id;
 
+    @Column(length = 10)
+    private String cityCode;
+
+    @Searchable
+    private String name;
+
+    private double lat;
+
+    private double lng;
+
+    @Column(length = 20)
+    @Enumerated(EnumType.STRING)
+    private DistrictLevel level;
+
+    private Long parent;
+
+    private int childCount;
+
+    private int cityCount;
+
+    private int districtCount;
+
+    private int streetCount;
+
+    @Transient
+    private Boolean leaf;
 }

+ 18 - 0
src/main/java/com/izouma/awesomeAdmin/enums/DistrictLevel.java

@@ -0,0 +1,18 @@
+package com.izouma.awesomeAdmin.enums;
+
+public enum DistrictLevel {
+    PROVINCE(1),
+    CITY(2),
+    DISTRICT(3),
+    STREET(4),
+    NONE(5);
+    private final int value;
+
+    DistrictLevel(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return value;
+    }
+}

+ 98 - 56
src/main/java/com/izouma/awesomeAdmin/service/DistrictService.java

@@ -1,79 +1,121 @@
 package com.izouma.awesomeAdmin.service;
 
+import com.alibaba.fastjson.JSON;
+import com.github.kevinsawicki.http.HttpRequest;
 import com.izouma.awesomeAdmin.domain.District;
-import com.izouma.awesomeAdmin.dto.PageQuery;
+import com.izouma.awesomeAdmin.enums.DistrictLevel;
 import com.izouma.awesomeAdmin.repo.DistrictRepo;
-import com.izouma.awesomeAdmin.utils.JpaUtils;
-import com.izouma.awesomeAdmin.utils.qqmap.DistrictResponse;
-import com.izouma.awesomeAdmin.utils.qqmap.QQMapUtil;
+import com.izouma.awesomeAdmin.utils.amap.DistrictsItem;
+import com.izouma.awesomeAdmin.utils.amap.QueryDistrictResponse;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.data.domain.Page;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 
+import javax.persistence.criteria.Predicate;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
 public class DistrictService {
 
-    private DistrictRepo districtRepo;
+    private final DistrictRepo districtRepo;
 
-    public Page<District> all(PageQuery pageQuery) {
-        return districtRepo.findAll(JpaUtils.toSpecification(pageQuery, District.class), JpaUtils.toPageRequest(pageQuery));
+    public List<District> get(DistrictLevel level, DistrictLevel maxLevel, Long parent) {
+        return districtRepo.findAll((Specification<District>) (root, criteriaQuery, criteriaBuilder) -> {
+            List<Predicate> predicates = new ArrayList<>();
+            if (level != null) {
+                predicates.add(criteriaBuilder.equal(root.get("level"), level));
+            }
+            if (parent != null) {
+                predicates.add(criteriaBuilder.equal(root.get("parent"), parent));
+            }
+            if (maxLevel != null) {
+                List<DistrictLevel> list = Arrays.stream(DistrictLevel.values())
+                        .filter(l -> l.getValue() <= maxLevel.getValue())
+                        .collect(Collectors.toList());
+                if (list.isEmpty()) {
+                    predicates.add(criteriaBuilder.equal(root.get("level"), DistrictLevel.NONE));
+                } else {
+                    predicates.add(root.get("level").in(list));
+                }
+            }
+            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+        }).stream().peek(district -> {
+            if (maxLevel != null) {
+                int childCount = 0;
+                switch (maxLevel) {
+                    case PROVINCE:
+                        break;
+                    case CITY:
+                        childCount = district.getCityCount();
+                        break;
+                    case DISTRICT:
+                        childCount = district.getCityCount() + district.getDistrictCount();
+                        break;
+                    case STREET:
+                        childCount = district.getCityCount() + district.getDistrictCount() + district.getStreetCount();
+                        break;
+                }
+                district.setLeaf(childCount == 0);
+            } else {
+                district.setLeaf(district.getChildCount() == 0);
+            }
+        }).collect(Collectors.toList());
     }
 
     public void sync() {
-        List<List<DistrictResponse.District>> res = QQMapUtil.queryDistrict().getResult();
-        for (int i = 0; i < 3; i++) {
-            for (DistrictResponse.District district : res.get(i)) {
-                District d = convert(district);
-                d.setLevel(i);
-                if (i > 0) {
-                    int finalI = i;
-                    DistrictResponse.District parent = res.get(i - 1)
-                            .stream()
-                            .filter(ii -> String.valueOf(ii.getId())
-                                    .startsWith(String.valueOf(d.getId()).substring(0, finalI == 1 ? 2 : 4)))
-                            .findFirst()
-                            .orElse(null);
-
-                    if (parent == null) {
-                        parent = res.get(0)
-                                .stream()
-                                .filter(ii -> String.valueOf(ii.getId())
-                                        .startsWith(String.valueOf(d.getId()).substring(0, 2)))
-                                .findFirst()
-                                .orElse(null);
-                        District p = convert(parent);
-                        p.setLevel(1);
-                        p.setParent(Long.parseLong(String.valueOf(parent.getId()).substring(0, 2) + "0100"));
-                        districtRepo.save(p);
-                        d.setParent(p.getId());
-                    } else {
-                        d.setParent((long) parent.getId());
-                    }
+        QueryDistrictResponse response = JSON.parseObject(HttpRequest.get("https://restapi.amap.com/v3/config/district?key=3d59fb422c5c13af59bf82a8b6f3ad54&subdistrict=4")
+                .body(), QueryDistrictResponse.class);
+        response.getDistricts().get(0).getDistricts().stream().parallel().forEach(item -> saveDistrict(item, null));
+    }
 
-                }
-                if (i == 2) {
-                    d.setLeaf(true);
-                }
-                if (i == 1 && !String.valueOf(d.getId()).substring(4).equals("00")) {
-                    d.setLeaf(true);
-                }
-                districtRepo.save(d);
-            }
+    private void saveDistrict(DistrictsItem item, Long parentId) {
+        District district = District.builder()
+                .id(Long.parseLong(item.getAdcode()))
+                .name(item.getName())
+                .parent(parentId)
+                .level(DistrictLevel.valueOf(item.getLevel().toUpperCase()))
+                .build();
+        if (district.getLevel() == DistrictLevel.STREET) {
+            district.setId(Long.parseLong(district.getId() + String.format("%02d", item.getIdx())));
+        }
+        if (StringUtils.isNotBlank(item.getCenter())) {
+            String[] arr = item.getCenter().split(",");
+            district.setLng(Double.parseDouble(arr[0]));
+            district.setLat(Double.parseDouble(arr[1]));
+        }
+        if (item.getCitycode() != null && item.getCitycode() instanceof String) {
+            district.setCityCode((String) item.getCitycode());
+        }
+        if (item.getDistricts() != null) {
+            district.setChildCount(item.getDistricts().size());
+            district.setCityCount((int) item.getDistricts()
+                    .stream()
+                    .filter(d -> DistrictLevel.valueOf(d.getLevel().toUpperCase()) == DistrictLevel.CITY)
+                    .count());
+            district.setDistrictCount((int) item.getDistricts()
+                    .stream()
+                    .filter(d -> DistrictLevel.valueOf(d.getLevel().toUpperCase()) == DistrictLevel.DISTRICT)
+                    .count());
+            district.setStreetCount((int) item.getDistricts()
+                    .stream()
+                    .filter(d -> DistrictLevel.valueOf(d.getLevel().toUpperCase()) == DistrictLevel.STREET)
+                    .count());
+        } else {
+            district.setChildCount(0);
+        }
+        districtRepo.save(district);
+        if (item.getDistricts() != null) {
+            int[] idx = {1};
+            item.getDistricts().stream().parallel().forEach(child -> {
+                child.setIdx(idx[0]++);
+                saveDistrict(child, district.getId());
+            });
         }
     }
 
-    private District convert(DistrictResponse.District district) {
-        District res = new District();
-        res.setId((long) district.getId());
-        res.setName(district.getName());
-        res.setFullName(district.getFullname());
-        res.setLat(district.getLocation().getLat());
-        res.setLng(district.getLocation().getLng());
-        res.setPinyin(StringUtils.join(district.getPinyin(), " "));
-        return res;
-    }
 }

+ 69 - 0
src/main/java/com/izouma/awesomeAdmin/utils/amap/DistrictsItem.java

@@ -0,0 +1,69 @@
+package com.izouma.awesomeAdmin.utils.amap;
+
+import java.util.List;
+
+public class DistrictsItem {
+    private Object              citycode;
+    private String              adcode;
+    private String              level;
+    private String              center;
+    private String              name;
+    private int                 idx;
+    private List<DistrictsItem> districts;
+
+    public void setCitycode(Object citycode) {
+        this.citycode = citycode;
+    }
+
+    public Object getCitycode() {
+        return citycode;
+    }
+
+    public void setAdcode(String adcode) {
+        this.adcode = adcode;
+    }
+
+    public String getAdcode() {
+        return adcode;
+    }
+
+    public void setLevel(String level) {
+        this.level = level;
+    }
+
+    public String getLevel() {
+        return level;
+    }
+
+    public void setCenter(String center) {
+        this.center = center;
+    }
+
+    public String getCenter() {
+        return center;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setDistricts(List<DistrictsItem> districts) {
+        this.districts = districts;
+    }
+
+    public List<DistrictsItem> getDistricts() {
+        return districts;
+    }
+
+    public int getIdx() {
+        return idx;
+    }
+
+    public void setIdx(int idx) {
+        this.idx = idx;
+    }
+}

+ 60 - 0
src/main/java/com/izouma/awesomeAdmin/utils/amap/QueryDistrictResponse.java

@@ -0,0 +1,60 @@
+package com.izouma.awesomeAdmin.utils.amap;
+
+import java.util.List;
+
+public class QueryDistrictResponse{
+	private Suggestion suggestion;
+	private String count;
+	private List<DistrictsItem> districts;
+	private String infocode;
+	private String status;
+	private String info;
+
+	public void setSuggestion(Suggestion suggestion){
+		this.suggestion = suggestion;
+	}
+
+	public Suggestion getSuggestion(){
+		return suggestion;
+	}
+
+	public void setCount(String count){
+		this.count = count;
+	}
+
+	public String getCount(){
+		return count;
+	}
+
+	public void setDistricts(List<DistrictsItem> districts){
+		this.districts = districts;
+	}
+
+	public List<DistrictsItem> getDistricts(){
+		return districts;
+	}
+
+	public void setInfocode(String infocode){
+		this.infocode = infocode;
+	}
+
+	public String getInfocode(){
+		return infocode;
+	}
+
+	public void setStatus(String status){
+		this.status = status;
+	}
+
+	public String getStatus(){
+		return status;
+	}
+
+	public void setInfo(String info){
+		this.info = info;
+	}
+
+	public String getInfo(){
+		return info;
+	}
+}

+ 24 - 0
src/main/java/com/izouma/awesomeAdmin/utils/amap/Suggestion.java

@@ -0,0 +1,24 @@
+package com.izouma.awesomeAdmin.utils.amap;
+
+import java.util.List;
+
+public class Suggestion{
+	private List<Object> keywords;
+	private List<Object> cities;
+
+	public void setKeywords(List<Object> keywords){
+		this.keywords = keywords;
+	}
+
+	public List<Object> getKeywords(){
+		return keywords;
+	}
+
+	public void setCities(List<Object> cities){
+		this.cities = cities;
+	}
+
+	public List<Object> getCities(){
+		return cities;
+	}
+}

+ 77 - 57
src/main/vue/src/components/DistrictChoose.vue

@@ -1,66 +1,86 @@
 <template>
     <div style="display:inline-block">
-        <el-cascader :props="props" filterable v-model="chooseValue" v-if="show" @change="onChange"></el-cascader>
+        <el-cascader
+            :props="props"
+            filterable
+            v-model="chooseValue"
+            v-if="show"
+            @change="onChange"
+            ref="cascader"
+        ></el-cascader>
     </div>
 </template>
 <script>
-export default {
-    props: {
-        value: {
-            type: Array
+    export default {
+        props: {
+            value: {
+                type: Array
+            },
+            checkStrictly: {
+                type: Boolean,
+                default: false
+            },
+            maxLevel: {}
         },
-        checkStrictly: {
-            type: Boolean,
-            default: false
-        }
-    },
-    data() {
-        return {
-            show: true,
-            chooseValue: [],
-            props: {
-                lazy: true,
-                lazyLoad: (node, resolve) => {
-                    const { level } = node;
-                    let params = { size: 10000, query: { level: level } };
-                    if (level !== 0) {
-                        params.query.parent = node.data.id;
-                    }
-                    this.$http.get('/district/all', params).then(res => {
-                        resolve(res.content);
-                    });
+        data() {
+            return {
+                show: true,
+                chooseValue: [],
+                props: {
+                    lazy: true,
+                    lazyLoad: (node, resolve) => {
+                        const { level } = node;
+                        let params = { size: 10000, query: { level: level } };
+                        if (level === 0) {
+                            params.level = 'PROVINCE';
+                        } else {
+                            params.parent = node.data.id;
+                        }
+                        if (this.maxLevel) {
+                            params.maxLevel = this.maxLevel.toUpperCase();
+                        }
+                        this.$http.get('/district', params).then(res => {
+                            if (res.length === 0) {
+                                this.$set(node, 'isLeaf', true);
+                                node.hasChildren = false;
+                                resolve(null);
+                                return;
+                            }
+                            resolve(res);
+                        });
+                    },
+                    value: 'id',
+                    label: 'name',
+                    leaf: 'leaf',
+                    checkStrictly: this.checkStrictly
                 },
-                value: 'id',
-                label: 'fullName',
-                leaf: 'leaf',
-                checkStrictly: this.checkStrictly
-            },
-            emiting: false
-        };
-    },
-    created() {
-        if (this.value) {
-            this.chooseValue = this.value;
-        }
-    },
-    methods: {
-        onChange(e) {
-            this.emiting = true;
-            this.$emit('input', [...e]);
-            this.$nextTick(() => {
-                this.emiting = false;
-            });
-        }
-    },
-    watch: {
-        value(val) {
-            if (this.emiting) return;
-            this.show = false;
-            this.$nextTick(() => {
-                this.chooseValue = val;
-                this.show = true;
-            });
+                emiting: false
+            };
+        },
+        created() {
+            if (this.value) {
+                this.chooseValue = this.value;
+            }
+        },
+        methods: {
+            onChange(e) {
+                this.emiting = true;
+                this.$emit('input', [...e]);
+                this.$emit('select', this.$refs.cascader.getCheckedNodes());
+                this.$nextTick(() => {
+                    this.emiting = false;
+                });
+            }
+        },
+        watch: {
+            value(val) {
+                if (this.emiting) return;
+                this.show = false;
+                this.$nextTick(() => {
+                    this.chooseValue = val;
+                    this.show = true;
+                });
+            }
         }
-    }
-};
+    };
 </script>