Vue element-china-area-data 数据源修改

Vue element-china-area-data 数据源修改

六月 19, 2020 阅读量

Vue前台需要省市区三级联动,但是element-china-area-data的regionData数据太旧了,而且有部分数据不符合现有系统的逻辑。于是乎……

因为前台需要省市区三级联动的控件,就选用了element-china-area-data来实现。但是实际使用中发现并不能满足现有系统的需求,最主要的原因是数据太旧了。数据来源china-area-data已经3年多没有更新了。以山东省济南市莱芜区为例,element-china-area-data中依然是市级行政单位。

element-china-area-data使用的是Element-Cascader级联选择器,稍微封装了一些方法,于是决定直接使用Element-Cascader级联选择器,后台生成需要的数据。

首先是数据来源,获取国务院-民政部最新的行政区划代码
2020年2月中华人民共和国县以上行政区划代码
,通过Excel结合公式,来生成符合数据库表结构的数据。
复制粘贴下来是这样的,需要把空格替换掉(不间断空格\u00A0,复制粘贴表格中的一个空格通过Excle替换)

然后根据我们系统中表结构分列,id和code就是行政区划代码,name对应地区名,parent_id对应上级id,parent_ids对应上级所有id,type对应省市区三级……
Excle公式计算如下:

  1. 先判断级别类型type,根据行政区域代码结尾0的数量,4个为1省级,2个为2市级,其余为3区县。公式=IF(RIGHT(F2,4)="0000",1,IF(RIGHT(F2,2)="00",2, 3))
  2. parent_id,根据type,1省级为0,2市级为行政区域代码前两位拼接0000,3区县为行政区域代码前四位拼接00为公式=IF(G2=1,0,IF(G2=2,LEFT(A2,2)&"0000",IF(G2=3,LEFT(A2,4)&"00")))
  3. parent_ids,根据type和parent_id的结果拼接。公式=IF(G2=1,B2,IF(G2=2,"0,"&B2,IF(G2=3,"0,"&LEFT(B2,2)&"0000,"&B2)))
  4. sort,排序用,公式=ROW()-1。其他字段填充就行。

因为是三级联动,4个直辖市没有中间一层,需要手动补充。在相应位置复制粘贴4个直辖市数据,把id和code的第四位从0改为1即可。

然后还有没有市级的区县,和没有区县的地级市……不过这个是在使用中发现的。上面的数据导入到数据库中,后台报错(根据上面的公式逻辑,存在没有父类的区县)。

通过高德的地理编码,可以判断以上数据均为区县。

重庆市的直接把500200的改为500100,sqlUPDATE sys_area SET parent_id = '500100', parent_ids = '0,500000,500100' WHERE parent_id = '500200'。其余的在中间加一层name为县的市级行政区(为了保证有3级数据),添加了4条数据。

然后使用中发现还没有下一级的。

然后又多加了一层,添加了5条数据。

到此,全部的数据都能三级联动。数据这块根据实际需要来做吧,因为我们必须要存在三级。

数据全部修改完成后,重新生成左右值(左右值和三联没有联系,可忽略,如何生成可以参考以前写的:从bug中学习左右值树),最终后台控制页面部分显示如下。

数据生成部分java逻辑(主要)代码如下

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
public List<AreaData> initAreaData() {
List<Map<String, Object>> list = systemDao.findAreaDataList("sys_area");
List<AreaData> areaData = createAreaData("0", null, list, new AreaData());
return areaData;
}

private List<AreaData> createAreaData(String parentId, String name, List<Map<String, Object>> list, AreaData areaData) {
List<Map<String, Object>> childrenList = list.stream().filter(e -> {
return e.get("parentId").toString().equals(parentId);
}).collect(Collectors.toList());
List<AreaData> children = Lists.newArrayList();
for (Map<String, Object> o : childrenList) {
AreaData ad = new AreaData();
ad.setValue(String.valueOf(o.get("id")));
ad.setLabel(String.valueOf(o.get("name")));
List<AreaData> adchildrenList = Lists.newArrayList();
// 递归调用
adchildrenList = createAreaData(o.get("id").toString(), String.valueOf(o.get("name")), list, new AreaData());
if (0 < adchildrenList.size()) {
ad.setChildren(adchildrenList);
}
children.add(ad);
}
return children;
}

然后npm uninstall element-china-area-data -S卸载,Vue前台修改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<el-cascader
size="large"
style="width:100%"
:options="options"
v-model="cuSelectedOptions"
@change="cuHandleChange"
></el-cascader>

export default {
data() {
return {
options: [], // 清空掉
}
},
methods: {
fetchData() {
// 具体根据自己的写
areaDataList(this.query).then(
response => {
this.options = response.data;
}
}
}

最后效果如下

因为只有数据,element-china-area-data的方法用不了,但是都有替代方案。