xiangpei
2025-05-13 3655b69f8a8d278603da22fe86d5d4fe5cb64f2a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
package cn.lili.modules.system.serviceimpl;
 
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.cache.Cache;
import cn.lili.common.utils.HttpClientUtils;
import cn.lili.common.utils.SnowFlake;
import cn.lili.modules.system.entity.dos.Region;
import cn.lili.modules.system.entity.vo.RegionVO;
import cn.lili.modules.system.mapper.RegionMapper;
import cn.lili.modules.system.service.RegionService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.util.*;
 
/**
 * 行政地区业务层实现
 *
 * @author Chopper
 * @since 2020/12/2 11:11
 */
@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements RegionService {
 
    /**
     * 同步请求地址
     */
    private final String syncUrl = "https://restapi.amap.com/v3/config/district?subdistrict=4&key=e456d77800e2084a326f7b777278f89d";
 
    @Autowired
    private Cache cache;
 
 
    @Override
    @Transactional
    public boolean updateById(Region region) {
        return super.updateById(region);
    }
 
    @Transactional
    @Override
    public boolean save(Region region) {
        return super.save(region);
    }
 
    @Override
    public boolean removeByIds(List<String> idList) {
        return super.removeByIds(idList);
    }
 
    @Override
    public void synchronizationData(String url) {
        try {
 
            //清空数据
            QueryWrapper<Region> queryWrapper = new QueryWrapper<>();
            queryWrapper.ne("id", "-1");
            this.remove(queryWrapper);
 
            //读取数据
            String jsonString = HttpClientUtils.doGet(CharSequenceUtil.isEmpty(url) ? syncUrl : url, null);
 
            //构造存储数据库的对象集合
            List<Region> regions = this.initData(jsonString);
            for (int i = 0; i < (regions.size() / 100 + (regions.size() % 100 == 0 ? 0 : 1)); i++) {
                int endPoint = Math.min((100 + (i * 100)), regions.size());
                this.saveBatch(regions.subList(i * 100, endPoint));
            }
            //删除缓存
            cache.vagueDel("{regions}");
        } catch (Exception e) {
            log.error("同步行政数据错误", e);
        }
    }
 
    /**
     * 根据最后一级名称获取改所有上级地区id
     *
     * @param lastName 最后一级名称
     * @return 全部地区id
     */
    @Override
    public String getItemByLastName(String lastName) {
        StringBuilder sql = new StringBuilder();
        LambdaQueryWrapper<Region> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Region::getName, lastName);
        Region region = this.getOne(lambdaQueryWrapper, false);
        if (region != null) {
            sql.append(region.getPath()).append(",").append(region.getId());
            return sql.toString().replace(",0,", "");
        }
        return null;
    }
 
    @Override
    public List<Region> getItem(String id) {
        LambdaQueryWrapper<Region> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Region::getParentId, id);
        List<Region> regions = this.list(lambdaQueryWrapper);
        regions.sort(Comparator.comparing(Region::getOrderNum));
        return regions;
    }
 
    @Override
    public Map<String, Object> getRegion(String cityCode, String townName) {
        //获取地址信息
        Region region = this.getOne(new QueryWrapper<Region>()
                .eq("city_code", cityCode)
                .eq("name", townName), false);
        if (region != null) {
            //获取它的层级关系
            String path = region.getPath();
            String[] result = path.split(",");
            //因为有无用数据 所以先删除前两个
            result = ArrayUtils.remove(result, 0);
            result = ArrayUtils.remove(result, 0);
            //地址id
            StringBuilder regionIds = new StringBuilder();
            //地址名称
            StringBuilder regionNames = new StringBuilder();
            //循环构建新的数据
            for (String regionId : result) {
                Region reg = this.baseMapper.selectById(regionId);
                if (reg != null) {
                    regionIds.append(regionId).append(",");
                    regionNames.append(reg.getName()).append(",");
                }
            }
            regionIds.append(region.getId());
            regionNames.append(region.getName());
            //构建返回数据
            Map<String, Object> obj = new HashMap<>(2);
            obj.put("id", regionIds.toString());
            obj.put("name", regionNames.toString());
            return obj;
        }
        return Collections.emptyMap();
    }
 
    @Override
    public List<RegionVO> getAllCity() {
        LambdaQueryWrapper<Region> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //查询所有省市
        lambdaQueryWrapper.in(Region::getLevel, "city", "province");
        return regionTree(this.list(lambdaQueryWrapper));
    }
 
    private List<RegionVO> regionTree(List<Region> regions) {
        List<RegionVO> regionVOS = new ArrayList<>();
        regions.stream().filter(region -> ("province").equals(region.getLevel())).forEach(item -> regionVOS.add(new RegionVO(item)));
        regions.stream().filter(region -> ("city").equals(region.getLevel())).forEach(item -> {
            for (RegionVO region : regionVOS) {
                if (region.getId().equals(item.getParentId())) {
                    region.getChildren().add(new RegionVO(item));
                }
            }
        });
        return regionVOS;
    }
 
    /**
     * 构造数据模型
     *
     * @param jsonString
     * @throws Exception
     */
    private List<Region> initData(String jsonString) {
 
        //最终数据承载对象
        List<Region> regions = new ArrayList<>();
        JSONObject jsonObject = JSONObject.parseObject(jsonString);
        //获取到国家及下面所有的信息 开始循环插入,这里可以写成递归调用,但是不如这样方便查看、理解
        JSONArray countryAll = jsonObject.getJSONArray("districts");
        for (int i = 0; i < countryAll.size(); i++) {
            JSONObject contry = countryAll.getJSONObject(i);
            String id1 = "0";
            JSONArray provinceAll = contry.getJSONArray("districts");
            for (int j = 0; j < provinceAll.size(); j++) {
                JSONObject province = provinceAll.getJSONObject(j);
                String citycode1 = province.getString("citycode");
                String adcode1 = province.getString("adcode");
                String name1 = province.getString("name");
                String center1 = province.getString("center");
                String level1 = province.getString("level");
                //插入省
                String id2 = insert(regions, id1, citycode1, adcode1, name1, center1, level1, j, id1);
                JSONArray cityAll = province.getJSONArray("districts");
 
                for (int z = 0; z < cityAll.size(); z++) {
                    JSONObject city = cityAll.getJSONObject(z);
                    String citycode2 = city.getString("citycode");
                    String adcode2 = city.getString("adcode");
                    String name2 = city.getString("name");
                    String center2 = city.getString("center");
                    String level2 = city.getString("level");
                    //插入市
                    String id3 = insert(regions, id2, citycode2, adcode2, name2, center2, level2, z, id1, id2);
                    JSONArray districtAll = city.getJSONArray("districts");
                    for (int w = 0; w < districtAll.size(); w++) {
                        JSONObject district = districtAll.getJSONObject(w);
                        String citycode3 = district.getString("citycode");
                        String adcode3 = district.getString("adcode");
                        String name3 = district.getString("name");
                        String center3 = district.getString("center");
                        String level3 = district.getString("level");
                        //插入区县
                        String id4 = insert(regions, id3, citycode3, adcode3, name3, center3, level3, w, id1, id2, id3);
                        //有需要可以继续向下遍历
                        JSONArray streetAll = district.getJSONArray("districts");
                        for (int r = 0; r < streetAll.size(); r++) {
                            JSONObject street = streetAll.getJSONObject(r);
                            String citycode4 = street.getString("citycode");
                            String adcode4 = street.getString("adcode");
                            String name4 = street.getString("name");
                            String center4 = street.getString("center");
                            String level4 = street.getString("level");
                            //插入区县
                            insert(regions, id4, citycode4, adcode4, name4, center4, level4, r, id1, id2, id3, id4);
 
                        }
 
                    }
 
                }
            }
        }
        return regions;
    }
 
    /**
     * 公共的插入方法
     *
     * @param parentId 父id
     * @param cityCode 城市编码
     * @param adCode   区域编码  街道没有独有的adcode,均继承父类(区县)的adcode
     * @param name     城市名称 (行政区名称)
     * @param center   地理坐标
     * @param level    country:国家
     *                 province:省份(直辖市会在province和city显示)
     *                 city:市(直辖市会在province和city显示)
     *                 district:区县
     *                 street:街道
     * @param ids      地区id集合
     * @return
     */
    public String insert(List<Region> regions, String parentId, String cityCode, String adCode, String name, String center, String level, Integer order, String... ids) {
//        \"citycode\": [],\n" +
//               "        \"adcode\": \"100000\",\n" +
//               "        \"name\": \"中华人民共和国\",\n" +
//               "        \"center\": \"116.3683244,39.915085\",\n" +
//               "        \"level\": \"country\",\n" +
        Region record = new Region();
        if (!("[]").equals(adCode)) {
            record.setAdCode(adCode);
        }
        if (!("[]").equals(cityCode)) {
            record.setCityCode(cityCode);
        }
        record.setCenter(center);
        record.setLevel(level);
        record.setName(name);
        record.setParentId(parentId);
        record.setOrderNum(order);
        record.setId(String.valueOf(SnowFlake.getId()));
        StringBuilder megName = new StringBuilder(",");
        for (int i = 0; i < ids.length; i++) {
            megName.append(ids[i]);
            if (i < ids.length - 1) {
                megName.append(",");
            }
        }
        record.setPath(megName.toString());
        regions.add(record);
        return record.getId();
    }
 
}