feat: add area cascade selector demo (#257)

This commit is contained in:
一万
2022-04-30 00:40:28 +08:00
committed by GitHub
parent 6c6d520dcb
commit 016c75c0d4
10 changed files with 400 additions and 35 deletions

View File

@@ -53,7 +53,7 @@ const props = {
};
export default defineComponent({
name: "epTableProBar",
name: "ReQrcode",
props,
emits: ["done", "click", "disabled-click"],
setup(props, { emit }) {

View File

@@ -113,10 +113,19 @@ const ableRouter = {
},
{
path: "/able/qrcode",
name: "reQarcode",
name: "reQrcode",
component: () => import("/@/views/able/qrcode.vue"),
meta: {
title: $t("menus.hsQarcode"),
title: $t("menus.hsQrcode"),
i18n: true
}
},
{
path: "/able/cascader",
name: "reCascader",
component: () => import("/@/views/able/cascader.vue"),
meta: {
title: $t("menus.hsCascader"),
i18n: true
}
}

View File

@@ -30,6 +30,11 @@
margin-left: $sideBarWidth;
position: relative;
background: #f0f2f5;
.el-scrollbar__wrap {
overflow: auto;
height: 100%;
}
}
.fixed-header {
@@ -483,11 +488,6 @@
}
}
.el-scrollbar__wrap {
overflow: auto;
height: 100%;
}
.el-menu--collapse .el-menu .el-sub-menu {
min-width: $sideBarWidth !important;
}

190
src/utils/chinaArea.ts Normal file
View File

@@ -0,0 +1,190 @@
import REGION_DATA from "china-area-data";
import { cloneDeep } from "lodash-unified";
interface ProvinceData {
value: string;
label: string;
children?: Array<ProvinceData>;
}
// code转汉字大对象,例CodeToText['110000']输出北京市
const CodeToText = {};
// 汉字转code大对象,例TextToCode['北京市']['市辖区']['朝阳区'].code输出110105
const TextToCode = {};
// 省份对象
const provinceObject = REGION_DATA["86"];
// 省市区三级联动数据(不带“全部”选项)
const regionData = [];
// 省市二级联动数据(不带“全部”选项)
let provinceAndCityData = [];
const ALL_TEXT = "全部";
CodeToText[""] = ALL_TEXT;
// 计算省
Object.keys(provinceObject).forEach(prop => {
const provinceText = provinceObject[prop];
regionData.push({
value: prop, // 省份code值
label: provinceText // 省份汉字
});
CodeToText[prop] = provinceText;
TextToCode[provinceText] = {
code: prop
};
TextToCode[provinceText][ALL_TEXT] = {
code: ""
};
});
// 计算市
regionData.forEach((item: ProvinceData) => {
const provinceCode = item.value;
const provinceText = item.label;
const provinceChildren = [];
const provinceData = REGION_DATA[provinceCode] ?? {};
Object.keys(provinceData).forEach(prop => {
provinceChildren.push({
value: prop,
label: provinceData[prop]
});
CodeToText[prop] = provinceData[prop];
TextToCode[provinceText][provinceData[prop]] = {
code: prop
};
TextToCode[provinceText][provinceData[prop]][ALL_TEXT] = {
code: ""
};
});
if (provinceChildren.length) {
item.children = provinceChildren;
}
});
provinceAndCityData = cloneDeep(regionData);
// 计算区
regionData.forEach((item: ProvinceData) => {
const province = item.children;
const provinceText = item.label;
if (province) {
province.forEach(pItem => {
const cityCode = pItem.value;
const cityText = pItem.label;
const cityChildren = [];
const cityData = REGION_DATA[cityCode] ?? {};
Object.keys(cityData).forEach(prop => {
cityChildren.push({
value: prop,
label: cityData[prop]
});
CodeToText[prop] = cityData[prop];
TextToCode[provinceText][cityText][cityData[prop]] = {
code: prop
};
});
if (cityChildren.length) {
pItem.children = cityChildren;
}
});
}
});
// 添加“全部”选项
const provinceAndCityDataPlus = cloneDeep(provinceAndCityData);
provinceAndCityDataPlus.unshift({
value: "",
label: ALL_TEXT
});
provinceAndCityDataPlus.forEach((item: ProvinceData) => {
const province = item.children;
if (province?.length) {
province.unshift({
value: "",
label: ALL_TEXT
});
province.forEach(pItem => {
const city = pItem.children;
if (city?.length) {
city.unshift({
value: "",
label: ALL_TEXT
});
}
});
}
});
const regionDataPlus = cloneDeep(regionData);
regionDataPlus.unshift({
value: "",
label: ALL_TEXT
});
regionDataPlus.forEach((item: ProvinceData) => {
const province = item.children;
if (province?.length) {
province.unshift({
value: "",
label: ALL_TEXT
});
province.forEach(pItem => {
const city = pItem.children;
if (city?.length) {
city.unshift({
value: "",
label: ALL_TEXT
});
}
});
}
});
/**
* 汉字转区域码
* @param provinceText 省
* @param cityText 市
* @param regionText 区
* @returns
*/
function convertTextToCode(
provinceText: string,
cityText: string,
regionText?: string
): string {
let code = "";
if (provinceText && TextToCode[provinceText]) {
const province = TextToCode[provinceText];
code = province.code;
if (cityText && province[cityText]) {
const city = province[cityText];
code = `${code}${cityText === ALL_TEXT ? "" : ", "}${city.code}`;
if (regionText && city[regionText]) {
code = `${code}${regionText === ALL_TEXT ? "" : ", "}${
city[regionText].code
}`;
}
}
}
return code;
}
export {
provinceAndCityData,
regionData,
provinceAndCityDataPlus,
regionDataPlus,
CodeToText,
TextToCode,
convertTextToCode
};

148
src/views/able/cascader.vue Normal file
View File

@@ -0,0 +1,148 @@
<script setup lang="ts">
import {
provinceAndCityDataPlus,
provinceAndCityData,
convertTextToCode,
regionDataPlus,
regionData,
CodeToText
} from "/@/utils/chinaArea";
import { ref } from "vue";
const selectedOptions1 = ref(["110000", "110100"]);
const selectedOptions2 = ref(["120000", "120100", "120101"]);
const selectedOptions3 = ref(["130000", ""]);
const selectedOptions4 = ref(["120000", "120100", ""]);
const handleChange = value => {
console.log(value);
};
</script>
<template>
<el-card>
<template #header> 区域级联选择器 </template>
<el-row :gutter="20">
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center">
<span class="imp">
1. 二级联动不带全部选项
<el-cascader
:options="provinceAndCityData"
v-model="selectedOptions1"
@change="handleChange"
/>
</span>
<div class="leading-10">
<div>绑定值{{ selectedOptions1 }}</div>
<div>
区域码转汉字{{ CodeToText[selectedOptions1[0]] }},{{
CodeToText[selectedOptions1[1]]
}}
</div>
<div>
汉字转区域码{{
convertTextToCode(
CodeToText[selectedOptions1[0]],
CodeToText[selectedOptions1[1]]
)
}}
</div>
</div>
</div>
</el-col>
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center mt-3">
<span class="imp">
2. 二级联动带有全部选项
<el-cascader
:options="provinceAndCityDataPlus"
v-model="selectedOptions3"
@change="handleChange"
/>
</span>
<div class="leading-10">
<div>绑定值{{ selectedOptions3 }}</div>
<div>
区域码转汉字{{ CodeToText[selectedOptions3[0]] }},{{
CodeToText[selectedOptions3[1]]
}}
</div>
<div>
汉字转区域码{{
convertTextToCode(
CodeToText[selectedOptions3[0]],
CodeToText[selectedOptions3[1]]
)
}}
</div>
</div>
</div>
</el-col>
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center mt-3">
<span class="imp">
3. 三级联动不带全部选项
<el-cascader
:options="regionData"
v-model="selectedOptions2"
@change="handleChange"
/>
</span>
<div class="leading-10">
<div>绑定值{{ selectedOptions2 }}</div>
<div>
区域码转汉字{{ CodeToText[selectedOptions2[0]] }},{{
CodeToText[selectedOptions2[1]]
}},{{ CodeToText[selectedOptions2[2]] }}
</div>
<div>
汉字转区域码{{
convertTextToCode(
CodeToText[selectedOptions2[0]],
CodeToText[selectedOptions2[1]],
CodeToText[selectedOptions2[2]]
)
}}
</div>
</div>
</div>
</el-col>
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
<div class="flex flex-col items-center justify-center mt-3">
<span class="imp">
4. 三级联动"全部选项"
<el-cascader
:options="regionDataPlus"
v-model="selectedOptions4"
@change="handleChange"
/>
</span>
<div class="leading-10">
<div>绑定值{{ selectedOptions4 }}</div>
<div>
区域码转汉字{{ CodeToText[selectedOptions4[0]] }},{{
CodeToText[selectedOptions4[1]]
}},{{ CodeToText[selectedOptions4[2]] }}
</div>
<div>
汉字转区域码{{
convertTextToCode(
CodeToText[selectedOptions4[0]],
CodeToText[selectedOptions4[1]],
CodeToText[selectedOptions4[2]]
)
}}
</div>
</div>
</div>
</el-col>
</el-row>
</el-card>
</template>
<style scoped lang="scss">
.imp {
color: var(--el-color-primary);
}
</style>

View File

@@ -116,7 +116,6 @@ const rules = {
<el-select
v-model="formData.type"
clearable
:teleported="false"
:style="{ width: '480px' }"
>
<el-option