行政区联动组件
· 阅读需 2 分钟
表单使用
- 必须跟着一个国家选择器
- 联动规则:
- 当国家选择器值变化时,联动组件的 label 值会变化(如果接口有返回该国家的行政区名称的话),如果没有返回则显示默认文案「行政区」。
- 当国家选择器有值时,联动组件必填;当国家选择器无值时,联动组件非必填。
- 联动组件的 options 由接口返回,接口参数为国家选择器的值,接口返回的 options 中包含 label 和 value 两个字段。
- 联动组件的 label 默认文案为「行政区」,可自定义文案。
{
fieldName: 'customerCountry',
label: $t('web.crmCustomer.create.form.customerCountry', {
defaultValue: '注册地国家/地区',
}),
component: 'ApiSelect',
componentProps: {
api: async () => {
const countries = await getSimpleCountryList();
return (countries || []).map((c) => ({
label: `${c.text} (${c.countryCode})`,
value: c.countryCode,
}));
},
labelField: 'label',
valueField: 'value',
placeholder: $t(
'web.crmCustomer.create.form.placeholder.selectCustomerCountry',
{ defaultValue: '请选择注册地国家/地区' },
),
showSearch: true,
optionFilterProp: 'label',
getPopupContainer: getSelectPopupContainer,
},
defaultValue: undefined,
rules: z
.string({
required_error: $t(
'web.crmCustomer.create.form.validation.customerCountryRequired',
{ defaultValue: '注册地国家/地区不能为空' },
),
invalid_type_error: $t(
'web.crmCustomer.create.form.validation.customerCountryRequired',
{ defaultValue: '注册地国家/地区不能为空' },
),
})
.trim()
.min(
1,
$t('web.crmCustomer.create.form.validation.customerCountryRequired', {
defaultValue: '注册地国家/地区不能为空',
}),
),
formItemClass: 'col-span-1',
},
{
fieldName: 'adminDiv',
label: getAdminDivDefaultName(),
component: 'AdminDivSelector',
componentProps: {
countryCode: undefined,
},
dependencies: {
triggerFields: ['customerCountry'],
show: (values: any) => !!(values.customerCountry ?? '').trim(),
trigger: async (values: any, actions: any) => {
const countryCode = (values?.customerCountry ?? '').trim();
const locale = preferences.app.locale || 'zh-CN';
const nextLabel = countryCode
? (
await getAdminDivDisplayName({
countryCode,
locale,
})
)?.displayName || getAdminDivDefaultName()
: getAdminDivDefaultName();
const currentSchema = actions?.state?.schema ?? [];
const currentLabel = currentSchema.find(
(item: any) => item?.fieldName === 'adminDiv',
)?.label;
// 仅在文案变化时更新,避免重复 setState 触发联动抖动
if (
typeof currentLabel === 'string' &&
currentLabel.trim() === nextLabel.trim()
) {
return;
}
actions?.updateSchema?.([
{
fieldName: 'adminDiv',
label: nextLabel,
},
]);
},
componentProps: (values: any) => ({
countryCode: (values.customerCountry ?? '').trim() || undefined,
}),
rules: (values: any) => {
// 提交时在 create.vue 中做显式校验,避免国家切换时即时触发必填报错
return z.string().optional();
},
},
defaultValue: undefined,
rules: z.string().optional(),
formItemClass: 'col-span-1',
},
表单详情使用
行政区的 code,拼装好传到接口,后端去查,然后把显示名称组织好返回前端 ,需要加个这样的接口,根据请求的语言,返回对应的内容
