Appearance
BizRegionCascader 省市区选择
省 / 市 / 区三级联动选择:行政区划数据由业务侧注入(组件不含数据,保持库体积为零),level 控制深度、v-model 为区划代码路径、getRegionText() 反查名称文本。
生产接入建议:
china-divisionnpm 包(全量国标数据)或后端区划字典接口;示例中使用节选数据。
基础用法
data 注入区划树(code/name/children);change 携带代码路径与节点路径;getRegionText() 输出 江苏省 / 南京市 / 雨花台区 式文本。<script setup lang="ts">
/** 基础用法:数据注入的三级选择(示例数据;生产接 china-division 或后端字典) */
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizRegionCascader } from 'vue3-ep-biz-lib'
import type { BizRegionCascaderInstance, BizRegionNode } from 'vue3-ep-biz-lib'
/** 示例区划树(生产建议接入完整国标数据) */
const regions: BizRegionNode[] = [
{
code: '320000', name: '江苏省',
children: [
{
code: '320100', name: '南京市',
children: [
{ code: '320102', name: '玄武区' },
{ code: '320114', name: '雨花台区' },
{ code: '320111', name: '浦口区' },
],
},
{ code: '320500', name: '苏州市', children: [{ code: '320508', name: '姑苏区' }, { code: '320505', name: '虎丘区' }] },
],
},
{
code: '110000', name: '北京市',
children: [
{ code: '110101', name: '东城区' },
{ code: '110102', name: '西城区' },
],
},
{ code: '330000', name: '浙江省', children: [{ code: '330100', name: '杭州市', children: [{ code: '330105', name: '拱墅区' }] }] },
]
const codes = ref<string[]>(['320000', '320100', '320114'])
const regionRef = ref<BizRegionCascaderInstance>()
const onChange = (value: string[], nodes: BizRegionNode[]): void => {
if (value.length === 0) return
ElMessage.info(`${nodes.map((n) => n.name).join(' / ')}(代码 ${value.join('-')})`)
}
</script>
<template>
<div style="max-width: 420px; display: flex; flex-direction: column; gap: 10px">
<BizRegionCascader ref="regionRef" v-model="codes" :data="regions" @change="onChange" />
<span style="font-size: 13px; color: var(--el-text-color-secondary)">
getRegionText():{{ regionRef?.getRegionText() || '(未选择)' }}
</span>
</div>
</template>
显示代码
收货地址表单(level=2)
level=2 自动裁剪到市级(区级选项不可见);配合详细地址输入组成完整地址表单。<script setup lang="ts">
/** 场景:收货地址表单——level=2 到市级 + 详细地址联动 */
import { ref } from 'vue'
import { ElButton, ElInput, ElMessage } from 'element-plus'
import { BizRegionCascader } from 'vue3-ep-biz-lib'
import type { BizRegionNode } from 'vue3-ep-biz-lib'
const regions: BizRegionNode[] = [
{
code: '320000', name: '江苏省',
children: [{ code: '320100', name: '南京市' }, { code: '320500', name: '苏州市' }],
},
{ code: '110000', name: '北京市', children: [] },
]
const city = ref<string[]>([])
const detail = ref('')
const onSubmit = (): void => {
if (city.value.length === 0 || detail.value.trim() === '') {
ElMessage.warning('请选择城市并填写详细地址')
return
}
const cityNames = city.value.join('/')
ElMessage.success(`收货地址:${cityNames} ${detail.value}`)
}
</script>
<template>
<div style="max-width: 480px; display: flex; flex-direction: column; gap: 12px">
<BizRegionCascader v-model="city" :data="regions" :level="2" placeholder="选择发货城市(省 / 市)" style="width: 100%" />
<ElInput v-model="detail" placeholder="详细地址(街道 / 楼宇 / 门牌号)" maxlength="60" />
<ElButton type="primary" @click="onSubmit">保存收货地址</ElButton>
</div>
</template>
显示代码
设备安装位置登记
IoT 场景:区划选择 + 楼宇门牌输入,登记结果入表;change 携带代码路径便于落库。
<script setup lang="ts">
/** 场景:设备安装位置——区划 + 楼宇门牌联动入表 */
import { ref } from 'vue'
import { ElButton, ElInput, ElMessage, ElTable, ElTableColumn } from 'element-plus'
import { BizRegionCascader } from 'vue3-ep-biz-lib'
import type { BizRegionNode } from 'vue3-ep-biz-lib'
const regions: BizRegionNode[] = [
{
code: '320000', name: '江苏省',
children: [{ code: '320100', name: '南京市', children: [{ code: '320114', name: '雨花台区' }, { code: '320102', name: '玄武区' }] }],
},
{ code: '110000', name: '北京市', children: [{ code: '110101', name: '东城区' }] },
]
const codes = ref<string[]>([])
const detail = ref('')
const devices = ref<{ id: number; region: string; detail: string }[]>([])
const onAdd = (): void => {
if (codes.value.length === 0 || detail.value.trim() === '') {
ElMessage.warning('请选择区划并填写详细位置')
return
}
const names = codes.value.length
void names
devices.value.push({ id: devices.value.length + 1, region: `区划码 ${codes.value.join('-')}`, detail: detail.value })
ElMessage.success('已登记安装位置')
}
</script>
<template>
<div style="max-width: 640px; display: flex; flex-direction: column; gap: 12px">
<div style="display: flex; gap: 10px">
<BizRegionCascader v-model="codes" :data="regions" style="width: 260px" />
<ElInput v-model="detail" placeholder="楼宇 / 层 / 门牌(如 A 栋 8 层 802)" style="flex: 1" maxlength="40" />
<ElButton type="primary" @click="onAdd">登记</ElButton>
</div>
<ElTable v-if="devices.length > 0" :data="devices" size="small" border>
<ElTableColumn prop="id" label="#" width="50" />
<ElTableColumn prop="region" label="区划" width="200" />
<ElTableColumn prop="detail" label="详细位置" />
</ElTable>
</div>
</template>
显示代码
省级覆盖范围(level=1)
尚未设置覆盖省份
渠道场景:level=1 仅省级;多次选择累积为覆盖范围徽标集,可单个移除。
<script setup lang="ts">
/** 场景:省级覆盖范围——level=1 多个单选并置(区域覆盖徽标) */
import { ref } from 'vue'
import { ElButton, ElMessage, ElTag } from 'element-plus'
import { BizRegionCascader } from 'vue3-ep-biz-lib'
import type { BizRegionNode } from 'vue3-ep-biz-lib'
const provinces: BizRegionNode[] = [
{ code: '320000', name: '江苏省' },
{ code: '330000', name: '浙江省' },
{ code: '440000', name: '广东省' },
{ code: '110000', name: '北京市' },
]
const current = ref<string[]>([])
const covered = ref<string[]>([])
const onAdd = (): void => {
const code = current.value[0]
if (code === undefined) return
if (!covered.value.includes(code)) covered.value.push(code)
current.value = []
ElMessage.success('已加入覆盖范围')
}
</script>
<template>
<div style="max-width: 560px; display: flex; flex-direction: column; gap: 12px">
<div style="display: flex; gap: 10px; align-items: center">
<BizRegionCascader v-model="current" :data="provinces" :level="1" placeholder="选择省份" style="width: 200px" />
<ElButton size="small" type="primary" plain @click="onAdd">加入覆盖</ElButton>
</div>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<ElTag v-for="code in covered" :key="code" closable @close="covered = covered.filter((item) => item !== code)">
{{ provinces.find((p) => p.code === code)?.name ?? code }}
</ElTag>
<span v-if="covered.length === 0" style="font-size: 13px; color: var(--el-text-color-placeholder)">尚未设置覆盖省份</span>
</div>
</div>
</template>
显示代码
区划代码查询工具
数据治理场景:change 节点路径反查全名 / 代码路径 / 层级结构,供清洗对照。
<script setup lang="ts">
/** 场景:区划代码查询工具——change 节点路径反查全名与代码 */
import { ref } from 'vue'
import { BizRegionCascader } from 'vue3-ep-biz-lib'
import type { BizRegionNode } from 'vue3-ep-biz-lib'
const regions: BizRegionNode[] = [
{
code: '320000', name: '江苏省',
children: [{ code: '320100', name: '南京市', children: [{ code: '320114', name: '雨花台区' }] }],
},
{ code: '110000', name: '北京市', children: [{ code: '110101', name: '东城区' }] },
]
const codes = ref<string[]>(['320000', '320100', '320114'])
const picked = ref<BizRegionNode[]>([])
const onChange = (_codes: string[], nodes: BizRegionNode[]): void => {
picked.value = nodes
}
</script>
<template>
<div style="max-width: 520px; display: flex; flex-direction: column; gap: 12px">
<BizRegionCascader v-model="codes" :data="regions" @change="onChange" />
<div v-if="picked.length > 0" style="display: flex; flex-direction: column; gap: 6px; padding: 12px; background: var(--el-fill-color-light); border-radius: 6px; font-size: 13px">
<span>全名:{{ picked.map((node) => node.name).join(' / ') }}</span>
<span>代码路径:{{ codes.join('-') }}(末端 {{ codes[codes.length - 1] }})</span>
<span>层级:{{ picked.map((node, index) => `${index + 1}级 ${node.name}`).join(' → ') }}</span>
</div>
</div>
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| v-model | string[] | [] | 区划代码路径 |
| data | BizRegionNode[] | [] | 区划数据树(业务注入) |
| level | 1 | 2 | 3 | 3 | 选择深度(省/省市/省市区) |
| separator | string | ' / ' | 回显文本分隔符 |
| placeholder | string | '请选择省 / 市 / 区' | 占位文案 |
| disabled / clearable | boolean | false / true | 禁用 / 可清空 |
其余 attrs 透传 el-cascader。
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| update:modelValue | (codes) | 代码路径变化 |
| change | (codes, nodes) | 选择变化(携带节点路径) |
Slots
| 插槽名 | 说明 |
|---|---|
| — | 无自定义插槽(视觉复用 el-cascader) |
Expose
| 属性/方法 | 说明 |
|---|---|
| getRegionText() | 当前选中区划文本(空选择返回空串) |