fix: 修复 Vben 表单地区选择器只展示末级地区的问题

- 新增 antd、antdv-next、ele 三端 AreaCascader 组件
- 将表单值保持为末级 areaId,展示时回显完整省市区级联路径
- 替换会员、CRM、商城交易相关表单的地区选择字段
- 按组件库默认行为保留清空和搜索默认关闭,并在使用处显式开启
pull/361/MERGE
YunaiV 2026-06-08 22:17:52 +08:00
parent 431cf8f268
commit fb80749156
24 changed files with 506 additions and 97 deletions

View File

@ -0,0 +1,125 @@
<script lang="ts" setup>
import type { CascaderProps } from 'ant-design-vue';
import type { SystemAreaApi } from '#/api/system/area';
import { onMounted, ref, watch } from 'vue';
import { Cascader } from 'ant-design-vue';
import { getAreaTree } from '#/api/system/area';
defineOptions({ name: 'AreaCascader' });
const props = withDefaults(defineProps<Props>(), {
allowClear: false,
changeOnSelect: false,
modelValue: undefined,
placeholder: '请选择省市区',
showSearch: false,
});
const emit = defineEmits<{
'update:modelValue': [value?: number];
}>();
interface Props {
allowClear?: boolean;
changeOnSelect?: boolean;
modelValue?: number;
placeholder?: string;
showSearch?: boolean;
}
type AreaTreeNode = SystemAreaApi.Area & {
children?: AreaTreeNode[];
};
const areaTree = ref<AreaTreeNode[]>([]); //
const loading = ref(false); //
const selectedPath = ref<number[]>(); //
const fieldNames = {
children: 'children', //
label: 'name', //
value: 'id', //
};
/**
* 查找地区编号对应的级联路径
*
* @param tree 地区树
* @param areaId 地区编号
* @returns 省市区编号路径
*/
function findAreaPath(
tree: AreaTreeNode[],
areaId?: number,
): number[] | undefined {
if (areaId === undefined || areaId === null) {
return undefined;
}
for (const area of tree) {
if (area.id === undefined) {
continue;
}
if (area.id === areaId) {
return [area.id];
}
const childPath = area.children?.length
? findAreaPath(area.children, areaId)
: undefined;
if (childPath) {
return [area.id, ...childPath];
}
}
}
/** 同步级联选择器展示路径 */
function syncSelectedPath() {
selectedPath.value = findAreaPath(areaTree.value, props.modelValue);
}
/** 选择地区后回写最后一级地区编号 */
const handleChange: NonNullable<CascaderProps['onChange']> = (value) => {
if (!value?.length) {
emit('update:modelValue', undefined);
return;
}
const path = Array.isArray(value[0]) ? value[0] : value;
const leafValue = path.at(-1);
const areaId =
typeof leafValue === 'number' ? leafValue : Number(leafValue);
emit('update:modelValue', Number.isNaN(areaId) ? undefined : areaId);
};
watch(() => props.modelValue, syncSelectedPath);
/** 初始化 */
onMounted(async () => {
loading.value = true;
try {
areaTree.value = (await getAreaTree()) as AreaTreeNode[];
syncSelectedPath();
} finally {
loading.value = false;
}
});
</script>
<template>
<Cascader
v-model:value="selectedPath"
:allow-clear="allowClear"
:change-on-select="changeOnSelect"
:field-names="fieldNames"
:loading="loading"
:options="areaTree"
:placeholder="placeholder"
:show-search="showSearch"
@change="handleChange"
/>
</template>

View File

@ -0,0 +1 @@
export { default as AreaCascader } from './area-cascader.vue';

View File

@ -1,12 +1,14 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -119,11 +121,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
class: '!w-full',
placeholder: '请选择地址',
showSearch: true,
},
},
{

View File

@ -1,14 +1,16 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getSimpleContactList } from '#/api/crm/contact';
import { getCustomerSimpleList } from '#/api/crm/customer';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
/** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] {
@ -143,11 +145,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
class: '!w-full',
placeholder: '请选择地址',
showSearch: true,
},
},
{

View File

@ -1,13 +1,15 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { z } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -128,12 +130,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
placeholder: '请选择地址',
allowClear: true,
class: '!w-full',
placeholder: '请选择地址',
showSearch: true,
},
},
{

View File

@ -1,12 +1,14 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { z } from '#/adapter/form';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -62,12 +64,13 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '门店所在地区',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
rules: 'required',
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
class: '!w-full',
placeholder: '请选择省市区',
showSearch: true,
},
},
{

View File

@ -2,13 +2,15 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
import { markRaw } from 'vue';
import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { convertToInteger, formatToFraction } from '@vben/utils';
import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express';
import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore';
import { getAreaTree } from '#/api/system/area';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 关联数据 */
@ -368,14 +370,13 @@ export function useAddressFormSchema(): VbenFormSchema[] {
{
fieldName: 'receiverAreaId',
label: '所在地',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
allowClear: true,
changeOnSelect: true,
class: '!w-full',
placeholder: '请选择收件人所在地',
treeDefaultExpandAll: true,
showSearch: true,
},
rules: 'required',
},

View File

@ -1,7 +1,7 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { h } from 'vue';
import { h, markRaw } from 'vue';
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
@ -13,7 +13,7 @@ import { z } from '#/adapter/form';
import { getSimpleGroupList } from '#/api/member/group';
import { getSimpleLevelList } from '#/api/member/level';
import { getSimpleTagList } from '#/api/member/tag';
import { getAreaTree } from '#/api/system/area';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -102,11 +102,13 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '所在地',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
changeOnSelect: true,
class: '!w-full',
placeholder: '请选择所在地',
showSearch: true,
},
},
{

View File

@ -0,0 +1,125 @@
<script lang="ts" setup>
import type { CascaderProps } from 'ant-design-vue';
import type { SystemAreaApi } from '#/api/system/area';
import { onMounted, ref, watch } from 'vue';
import { Cascader } from 'ant-design-vue';
import { getAreaTree } from '#/api/system/area';
defineOptions({ name: 'AreaCascader' });
const props = withDefaults(defineProps<Props>(), {
allowClear: false,
changeOnSelect: false,
modelValue: undefined,
placeholder: '请选择省市区',
showSearch: false,
});
const emit = defineEmits<{
'update:modelValue': [value?: number];
}>();
interface Props {
allowClear?: boolean;
changeOnSelect?: boolean;
modelValue?: number;
placeholder?: string;
showSearch?: boolean;
}
type AreaTreeNode = SystemAreaApi.Area & {
children?: AreaTreeNode[];
};
const areaTree = ref<AreaTreeNode[]>([]); //
const loading = ref(false); //
const selectedPath = ref<number[]>(); //
const fieldNames = {
children: 'children', //
label: 'name', //
value: 'id', //
};
/**
* 查找地区编号对应的级联路径
*
* @param tree 地区树
* @param areaId 地区编号
* @returns 省市区编号路径
*/
function findAreaPath(
tree: AreaTreeNode[],
areaId?: number,
): number[] | undefined {
if (areaId === undefined || areaId === null) {
return undefined;
}
for (const area of tree) {
if (area.id === undefined) {
continue;
}
if (area.id === areaId) {
return [area.id];
}
const childPath = area.children?.length
? findAreaPath(area.children, areaId)
: undefined;
if (childPath) {
return [area.id, ...childPath];
}
}
}
/** 同步级联选择器展示路径 */
function syncSelectedPath() {
selectedPath.value = findAreaPath(areaTree.value, props.modelValue);
}
/** 选择地区后回写最后一级地区编号 */
const handleChange: NonNullable<CascaderProps['onChange']> = (value) => {
if (!value?.length) {
emit('update:modelValue', undefined);
return;
}
const path = Array.isArray(value[0]) ? value[0] : value;
const leafValue = path.at(-1);
const areaId =
typeof leafValue === 'number' ? leafValue : Number(leafValue);
emit('update:modelValue', Number.isNaN(areaId) ? undefined : areaId);
};
watch(() => props.modelValue, syncSelectedPath);
/** 初始化 */
onMounted(async () => {
loading.value = true;
try {
areaTree.value = (await getAreaTree()) as AreaTreeNode[];
syncSelectedPath();
} finally {
loading.value = false;
}
});
</script>
<template>
<Cascader
v-model:value="selectedPath"
:allow-clear="allowClear"
:change-on-select="changeOnSelect"
:field-names="fieldNames"
:loading="loading"
:options="areaTree"
:placeholder="placeholder"
:show-search="showSearch"
@change="handleChange"
/>
</template>

View File

@ -0,0 +1 @@
export { default as AreaCascader } from './area-cascader.vue';

View File

@ -1,12 +1,14 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -119,11 +121,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
class: '!w-full',
placeholder: '请选择地址',
showSearch: true,
},
},
{

View File

@ -1,14 +1,16 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getSimpleContactList } from '#/api/crm/contact';
import { getCustomerSimpleList } from '#/api/crm/customer';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
/** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] {
@ -143,11 +145,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
class: '!w-full',
placeholder: '请选择地址',
showSearch: true,
},
},
{

View File

@ -1,13 +1,15 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { z } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -128,12 +130,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
placeholder: '请选择地址',
allowClear: true,
class: '!w-full',
placeholder: '请选择地址',
showSearch: true,
},
},
{

View File

@ -1,12 +1,14 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { z } from '#/adapter/form';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -62,12 +64,13 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '门店所在地区',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
rules: 'required',
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
class: '!w-full',
placeholder: '请选择省市区',
showSearch: true,
},
},
{

View File

@ -2,13 +2,15 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
import { markRaw } from 'vue';
import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { convertToInteger, formatToFraction } from '@vben/utils';
import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express';
import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore';
import { getAreaTree } from '#/api/system/area';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 关联数据 */
@ -368,14 +370,13 @@ export function useAddressFormSchema(): VbenFormSchema[] {
{
fieldName: 'receiverAreaId',
label: '所在地',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
allowClear: true,
changeOnSelect: true,
class: '!w-full',
placeholder: '请选择收件人所在地',
treeDefaultExpandAll: true,
showSearch: true,
},
rules: 'required',
},

View File

@ -1,7 +1,7 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { h } from 'vue';
import { h, markRaw } from 'vue';
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
@ -13,7 +13,7 @@ import { z } from '#/adapter/form';
import { getSimpleGroupList } from '#/api/member/group';
import { getSimpleLevelList } from '#/api/member/level';
import { getSimpleTagList } from '#/api/member/tag';
import { getAreaTree } from '#/api/system/area';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -102,11 +102,13 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '所在地',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
fieldNames: { label: 'name', value: 'id', children: 'children' },
allowClear: true,
changeOnSelect: true,
class: '!w-full',
placeholder: '请选择所在地',
showSearch: true,
},
},
{

View File

@ -0,0 +1,124 @@
<script lang="ts" setup>
import type { CascaderValue } from 'element-plus';
import type { SystemAreaApi } from '#/api/system/area';
import { onMounted, ref, watch } from 'vue';
import { ElCascader } from 'element-plus';
import { getAreaTree } from '#/api/system/area';
defineOptions({ name: 'AreaCascader' });
const props = withDefaults(defineProps<Props>(), {
checkStrictly: false,
clearable: false,
filterable: false,
modelValue: undefined,
placeholder: '请选择省市区',
});
const emit = defineEmits<{
'update:modelValue': [value?: number];
}>();
interface Props {
checkStrictly?: boolean;
clearable?: boolean;
filterable?: boolean;
modelValue?: number;
placeholder?: string;
}
type AreaTreeNode = SystemAreaApi.Area & {
children?: AreaTreeNode[];
};
const areaTree = ref<AreaTreeNode[]>([]); //
const loading = ref(false); //
const selectedPath = ref<number[]>(); //
/**
* 查找地区编号对应的级联路径
*
* @param tree 地区树
* @param areaId 地区编号
* @returns 省市区编号路径
*/
function findAreaPath(
tree: AreaTreeNode[],
areaId?: number,
): number[] | undefined {
if (areaId === undefined || areaId === null) {
return undefined;
}
for (const area of tree) {
if (area.id === undefined) {
continue;
}
if (area.id === areaId) {
return [area.id];
}
const childPath = area.children?.length
? findAreaPath(area.children, areaId)
: undefined;
if (childPath) {
return [area.id, ...childPath];
}
}
}
/** 同步级联选择器展示路径 */
function syncSelectedPath() {
selectedPath.value = findAreaPath(areaTree.value, props.modelValue);
}
/** 选择地区后回写最后一级地区编号 */
function handleChange(value?: CascaderValue | null) {
if (!Array.isArray(value) || value.length === 0) {
emit('update:modelValue', undefined);
return;
}
const path = Array.isArray(value[0]) ? value[0] : value;
const leafValue = path.at(-1);
const areaId =
typeof leafValue === 'number' ? leafValue : Number(leafValue);
emit('update:modelValue', Number.isNaN(areaId) ? undefined : areaId);
}
watch(() => props.modelValue, syncSelectedPath);
/** 初始化 */
onMounted(async () => {
loading.value = true;
try {
areaTree.value = (await getAreaTree()) as AreaTreeNode[];
syncSelectedPath();
} finally {
loading.value = false;
}
});
</script>
<template>
<ElCascader
v-model="selectedPath"
:clearable="clearable"
:filterable="filterable"
:loading="loading"
:options="areaTree"
:placeholder="placeholder"
:props="{
checkStrictly,
children: 'children',
emitPath: true,
label: 'name',
value: 'id',
}"
@change="handleChange"
/>
</template>

View File

@ -0,0 +1 @@
export { default as AreaCascader } from './area-cascader.vue';

View File

@ -1,12 +1,14 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -119,12 +121,11 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
class: '!w-full',
clearable: true,
filterable: true,
placeholder: '请选择地址',
},
},

View File

@ -1,14 +1,16 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getSimpleContactList } from '#/api/crm/contact';
import { getCustomerSimpleList } from '#/api/crm/customer';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
/** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] {
@ -141,12 +143,11 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
class: '!w-full',
clearable: true,
filterable: true,
placeholder: '请选择地址',
},
},

View File

@ -1,13 +1,15 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { z } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useUserStore } from '@vben/stores';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -128,14 +130,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '地址',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
class: '!w-full',
clearable: true,
filterable: true,
placeholder: '请选择地址',
allowClear: true,
},
},
{

View File

@ -1,12 +1,14 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { markRaw } from 'vue';
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { z } from '#/adapter/form';
import { getAreaTree } from '#/api/system/area';
import { getSimpleUserList } from '#/api/system/user';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -62,13 +64,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '门店所在地区',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
rules: 'required',
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
class: '!w-full',
clearable: true,
filterable: true,
placeholder: '请选择省市区',
},
},

View File

@ -2,13 +2,15 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
import { markRaw } from 'vue';
import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { convertToInteger, formatToFraction } from '@vben/utils';
import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express';
import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore';
import { getAreaTree } from '#/api/system/area';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 关联数据 */
@ -369,14 +371,13 @@ export function useAddressFormSchema(): VbenFormSchema[] {
{
fieldName: 'receiverAreaId',
label: '所在地',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
checkStrictly: true,
class: '!w-full',
clearable: true,
filterable: true,
placeholder: '请选择收件人所在地',
defaultExpandAll: true,
},
rules: 'required',
},

View File

@ -1,7 +1,7 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { h } from 'vue';
import { h, markRaw } from 'vue';
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
@ -13,7 +13,7 @@ import { z } from '#/adapter/form';
import { getSimpleGroupList } from '#/api/member/group';
import { getSimpleLevelList } from '#/api/member/level';
import { getSimpleTagList } from '#/api/member/tag';
import { getAreaTree } from '#/api/system/area';
import { AreaCascader } from '#/components/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改的表单 */
@ -99,12 +99,12 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'areaId',
label: '所在地',
component: 'ApiTreeSelect',
component: markRaw(AreaCascader),
componentProps: {
api: getAreaTree,
labelField: 'name',
valueField: 'id',
childrenField: 'children',
checkStrictly: true,
class: '!w-full',
clearable: true,
filterable: true,
placeholder: '请选择所在地',
},
},