@bnfe/store-select
v1.0.4
Published
门店地址选择器组件,基于 Vue 3 + Element Plus 开发,支持自动数据加载、权限过滤和多种输出格式。
Readme
@bnfe/store-select
门店地址选择器组件,基于 Vue 3 + Element Plus 开发,支持自动数据加载、权限过滤和多种输出格式。
安装
pnpm add @bnfe/store-select依赖
{
"peerDependencies": {
"element-plus": ">=2.5.0",
"vue": ">=3.4.0"
}
}使用
方式一:自动模式(推荐)✅
StoreSelectWithApi 组件封装了 API 请求、数据转换和权限过滤,开箱即用:
<script setup lang="ts">
import { ref } from 'vue';
import { StoreSelectWithApi } from '@bnfe/store-select';
import '@bnfe/store-select/dist/store-select.css'
// 选中的门店ID
const selectedIds = ref<string[]>([]);
// 用户权限门店ID列表(从后端获取)
const permissionIds = ['12', '152', '108', '99'];
// 请求头配置(动态注入业务上下文)
const headers = {
Authorization: 'Bearer xxx',
'Employee-Id': 'xxx',
appkey: 'xxx'
};
</script>
<template>
<StoreSelectWithApi
v-model="selectedIds"
:api-url="'/api/stores/get-store-all-group'"
:headers="headers"
:permission-ids="permissionIds"
/>
</template>方式二:手动模式
如果需要更灵活的控制,可以使用基础 StoreSelect 组件:
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { StoreSelect, filterStoreByPermission } from '@bnfe/store-select';
import '@bnfe/store-select/dist/store-select.css'
const selectedIds = ref([]);
const storeGroup = ref({ city: [], sub_region: [] });
const permissionIds = ['12', '152', '108'];
onMounted(async () => {
// 1. 请求数据
const res = await fetch('/api/stores/get-store-all-group');
const data = await res.json();
// 2. 权限过滤
storeGroup.value = filterStoreByPermission(data.data, permissionIds);
});
</script>
<template>
<StoreSelect v-model="selectedIds" :store-group="storeGroup" />
</template>API
StoreSelectWithApi Props
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| v-model | string[] \| string | - | ✅ | 选中的门店ID,支持数组或逗号分隔字符串 |
| api-url | string | /api/stores/get-store-all-group | - | 门店数据接口地址 |
| headers | Record<string, string> | - | ✅ | 请求头对象,用于注入 Token、员工ID 等业务上下文 |
| permission-ids | string[] | - | ✅ | 用户有权限访问的门店ID数组 |
| value-type | 'array' \| 'string' | 'array' | - | 输出值类型:array 数组格式,string 逗号分隔字符串 |
| auto-load | boolean | true | - | 组件挂载后自动请求数据 |
| collapse-tags | boolean | true | - | 是否折叠Tags |
| max-collapse-tags | number | 2 | - | 最多显示的Tag数量 |
StoreSelectWithApi Events
| 事件 | 参数 | 说明 |
|------|------|------|
| @load | (data: StoreGroupInfo) => void | 数据加载成功时触发 |
| @error | (error: Error) => void | 数据加载失败时触发 |
| @update:modelValue | (value: string[] \| string) => void | 选中值变化时触发 |
StoreSelect Props
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| v-model | string[] | - | ✅ | 选中的门店ID数组 |
| store-group | StoreGroupInfo | - | ✅ | 门店数据(区域/城市分组) |
| collapse-tags | boolean | true | - | 是否折叠Tags |
| max-collapse-tags | number | 2 | - | 最多显示的Tag数量 |
工具函数
filterStoreByPermission
按权限过滤门店数据:
import { filterStoreByPermission } from '@bnfe/store-select';
const filteredData = filterStoreByPermission(originData, permissionIds);参数:
data: 原始门店数据结构userStoreIds: 用户有权限的门店ID数组
返回值: 过滤后的门店数据
数据结构
类型导入
import type { StoreGroupInfo, StoreGroupItem, StoreItem } from '@bnfe/store-select'
// StoreGroupInfo
interface StoreGroupInfo {
region: StoreGroupItem[]; // 大区列表
city: StoreGroupItem[]; // 城市列表
sub_region: StoreGroupItem[]; // 子大区列表(含子小区嵌套)
}
interface StoreGroupItem {
id: string;
name: string;
storeList?: StoreItem[]; // 直属门店列表
sub?: StoreGroupItem[]; // 子分组(含嵌套门店)
}
interface StoreItem {
jss_store_id: string;
store_id: string;
store_name: string;
}示例
完整示例
<script setup lang="ts">
import { ref, computed } from 'vue';
import { StoreSelectWithApi } from '@bnfe/store-select';
// 用户权限门店ID(实际从后端获取)
const permissionIds = ['12', '152', '108', '99', '102', '94'];
// 选中值
const selectedIds = ref<string[]>([]);
// 字符串格式(用于提交表单)
const selectedIdsString = computed(() => selectedIds.value.join(','));
// 请求头
const headers = computed(() => ({
Authorization: `Bearer ${token}`,
'Employee-Id': userId,
'User-Name': encodeURIComponent(userName),
appkey: 'your-appkey'
}));
// 回调处理
const onLoad = (data) => {
console.log('数据加载成功', data);
};
const onError = (error) => {
console.error('数据加载失败', error);
};
</script>
<template>
<div>
<!-- 组件使用 -->
<StoreSelectWithApi
v-model="selectedIds"
api-url="https://api.example.com/stores"
:headers="headers"
:permission-ids="permissionIds"
@load="onLoad"
@error="onError"
/>
<!-- 显示选中结果 -->
<p>数组格式: {{ selectedIds }}</p>
<p>字符串格式: {{ selectedIdsString }}</p>
</div>
</template>使用字符串格式
如果接口需要逗号分隔的字符串格式:
<script setup lang="ts">
const selectedIds = ref(''); // 初始值为字符串
</script>
<template>
<StoreSelectWithApi
v-model="selectedIds"
value-type="string"
:headers="headers"
:permission-ids="permissionIds"
/>
</template>注意事项
headers 配置:请求头中需要包含完整的业务上下文(Token、员工ID等),这些信息无法在组件内部获取,需要外部传入。
permission-ids 参数:用于权限过滤,只返回用户有权限访问的门店。如果为空数组或未传,则返回所有门店。
value-type 输出格式:
array(默认):输出数组格式['74', '75', '77']string:输出逗号分隔字符串'74,75,77'
竞态处理:组件内部已处理快速切换时的请求竞态问题,确保最终显示的是最新请求的结果。
错误处理:建议监听
@error事件以便在请求失败时进行适当处理。
