@xfe-repo/web-components 1.6.2 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/package.json +4 -3
  2. package/skills/GUIDE.md +78 -0
  3. package/skills/SKILL.md +78 -0
  4. package/skills/TEMPLATE.md +170 -0
  5. package/skills/references/ApiService.md +136 -0
  6. package/skills/references/CInput.md +196 -0
  7. package/skills/references/CTable.md +274 -0
  8. package/skills/references/CVideo.md +94 -0
  9. package/skills/references/Clock.md +53 -0
  10. package/skills/references/ConfigProvider.md +198 -0
  11. package/skills/references/Countdown.md +109 -0
  12. package/skills/references/Counter.md +75 -0
  13. package/skills/references/Currency.md +112 -0
  14. package/skills/references/EffectAddressCascade.md +110 -0
  15. package/skills/references/EffectBrandSelect.md +231 -0
  16. package/skills/references/EffectBrandTransfer.md +143 -0
  17. package/skills/references/EffectCategoryCascade.md +228 -0
  18. package/skills/references/EffectFileUpload.md +349 -0
  19. package/skills/references/EffectLabelSelect.md +222 -0
  20. package/skills/references/EffectMerchantSelect.md +183 -0
  21. package/skills/references/EffectReservoirSelect.md +178 -0
  22. package/skills/references/EffectScopeSelect.md +220 -0
  23. package/skills/references/EffectSeriesSelect.md +205 -0
  24. package/skills/references/EffectSeriesSelectV2.md +154 -0
  25. package/skills/references/EffectSkuRecognize.md +149 -0
  26. package/skills/references/EffectSkuSelect.md +251 -0
  27. package/skills/references/EffectSkuTable.md +184 -0
  28. package/skills/references/EffectSpuSelect.md +189 -0
  29. package/skills/references/EffectStaffSelect.md +150 -0
  30. package/skills/references/EffectWarehouseSelect.md +183 -0
  31. package/skills/references/EffectWithFilePanel.md +205 -0
  32. package/skills/references/FileUpload.md +126 -0
  33. package/skills/references/Iconfont.md +31 -0
  34. package/skills/references/Loading.md +68 -0
  35. package/skills/references/MultiWindow.md +145 -0
  36. package/skills/references/OSSImage.md +230 -0
  37. package/skills/references/PrivacyField.md +90 -0
  38. package/skills/references/QRCode.md +148 -0
  39. package/skills/references/RichTextEditor.md +119 -0
  40. package/skills/references/SearchForm.md +270 -0
  41. package/skills/references/SearchList.md +128 -0
  42. package/skills/references/WithModal.md +328 -0
  43. package/skills/references/WithPanel.md +307 -0
  44. package/skills/references/commonFn.md +254 -0
@@ -0,0 +1,198 @@
1
+ # ConfigProvider
2
+
3
+ > 全局配置提供者,集成 Ant Design 配置、API 服务、国际化和主题,是所有 Effect 组件的运行基础。
4
+
5
+ ## 导入
6
+
7
+ ```tsx
8
+ import { ConfigProvider, ConfigContext } from '@xfe-repo/web-components'
9
+ import type { ConfigProviderProps, IApiPayload, IConfigContext } from '@xfe-repo/web-components'
10
+ ```
11
+
12
+ ## 基本用法
13
+
14
+ ```tsx
15
+ import { ConfigProvider } from '@xfe-repo/web-components'
16
+ import zhCN from 'antd/locale/zh_CN'
17
+
18
+ function App() {
19
+ return (
20
+ <ConfigProvider
21
+ locale={zhCN}
22
+ apiPayload={{
23
+ jwt: jwtInstance,
24
+ apiEnv: 'production',
25
+ business: 'eshetang',
26
+ getUserToken: () => localStorage.getItem('token') || '',
27
+ setUserToken: (token) => localStorage.setItem('token', token),
28
+ removeUserToken: () => localStorage.removeItem('token'),
29
+ }}
30
+ >
31
+ <YourApp />
32
+ </ConfigProvider>
33
+ )
34
+ }
35
+ ```
36
+
37
+ ## 进阶用法
38
+
39
+ ### 自定义 API 服务
40
+
41
+ 通过 `apiService` 覆盖默认的 SaaS BFF 服务实现,适用于非标准后端或 Mock 场景。自定义方法会与默认 `saasApiService` 合并(浅合并,自定义优先)。
42
+
43
+ ```tsx
44
+ import { ConfigProvider } from '@xfe-repo/web-components'
45
+
46
+ const customApiService = {
47
+ categoryListToTree: async (params, config) => {
48
+ // 自定义分类树接口实现
49
+ return await myCustomApi.getCategoryTree(params)
50
+ },
51
+ brandComboBox: async (params, config) => {
52
+ // 自定义品牌下拉接口实现
53
+ return await myCustomApi.getBrands(params)
54
+ },
55
+ }
56
+
57
+ function App() {
58
+ return (
59
+ <ConfigProvider apiService={customApiService}>
60
+ <YourApp />
61
+ </ConfigProvider>
62
+ )
63
+ }
64
+ ```
65
+
66
+ ### 在子组件中消费 Context
67
+
68
+ ```tsx
69
+ import { useContext } from 'react'
70
+ import { ConfigContext } from '@xfe-repo/web-components'
71
+
72
+ function MyComponent() {
73
+ const configContext = useContext(ConfigContext)
74
+
75
+ // 获取 API 服务和认证信息
76
+ const { apiService, apiPayload } = configContext!
77
+ const token = apiPayload.getUserToken?.()
78
+
79
+ return <div>当前环境:{apiPayload.apiEnv}</div>
80
+ }
81
+ ```
82
+
83
+ ## Props
84
+
85
+ ```typescript
86
+ interface ConfigProviderProps {
87
+ /** SaaS BFF 认证信息,使用自定义 apiService 时可不传 */
88
+ apiPayload?: Partial<IApiPayload>
89
+ /** 自定义 API 服务实现,会覆盖默认的 SaaS BFF 服务 */
90
+ apiService?: Partial<IApiService>
91
+ /** antd 国际化语言包 */
92
+ locale?: Locale
93
+ /** antd 主题配置 */
94
+ theme?: ThemeConfig
95
+ /** antd App 组件的 className */
96
+ className?: string
97
+ /** 子组件 */
98
+ children: React.ReactNode
99
+ }
100
+ ```
101
+
102
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
103
+ | ---------- | ---------------------- | ---- | ---------------- | ----------------------------------------------- |
104
+ | apiPayload | `Partial<IApiPayload>` | 否 | `{}` | SaaS BFF 认证信息,包含 JWT、环境、Token 管理等 |
105
+ | apiService | `Partial<IApiService>` | 否 | `saasApiService` | 自定义 API 服务,与默认实现浅合并 |
106
+ | locale | `Locale` | 否 | - | antd 国际化语言包 |
107
+ | theme | `ThemeConfig` | 否 | - | antd 主题配置 |
108
+ | className | `string` | 否 | - | 传递给 antd App 组件的 className |
109
+ | children | `React.ReactNode` | 是 | - | 子组件 |
110
+
111
+ ## 导出类型
112
+
113
+ ### IApiPayload
114
+
115
+ API 认证载荷,包含运行环境和 Token 管理方法:
116
+
117
+ ```typescript
118
+ type IApiPayload = {
119
+ jwt: JWT // JWT 实例(来自 @xfe-repo/web-service)
120
+ apiEnv: ApiEnv // API 环境标识(来自 @xfe-repo/web-utils/env)
121
+ business: Business // 业务线标识(来自 @xfe-repo/web-utils/env)
122
+ getUserToken: () => string // 获取当前用户 Token
123
+ setUserToken: (token: string) => void // 设置用户 Token
124
+ removeUserToken: () => void // 移除用户 Token
125
+ }
126
+ ```
127
+
128
+ ### IApiService
129
+
130
+ API 服务接口,定义了所有 Effect 组件内部调用的接口方法:
131
+
132
+ ```typescript
133
+ interface IApiService {
134
+ categoryListToTree: Request<InQueryCategoryListToTree, OutListToTreeCategoryDto> // 分类树
135
+ brandComboBox: Request<InQueryBrandComboBox, OutComboBoxBrandDto> // 品牌下拉
136
+ seriesComboBox: Request<InQuerySeriesComboBox, OutComboBoxSeriesDto> // 系列下拉
137
+ seriesList: Request<InQuerySeriesList, OutListSeriesDto> // 系列列表
138
+ skuFindOne: Request<InPathSkuFindOne, OutFindOneSkuDto> // SKU 详情
139
+ skuListV2: Request<InQuerySkuListV2, OutListSkuV2Dto> // SKU 列表
140
+ spuList: Request<InQuerySpuList, OutListSpuDto> // SPU 列表
141
+ productImageSpuSkuList: Request<InQueryProductImageSpuSkuList, OutListProductImageSpuSkuDto> // 商品图片列表
142
+ uploadUploadFile: Request<InUploadFileDto, OutUploadFileDto> // 文件上传
143
+ uploadRemoteCreate: Request<InRemoteCreateDto, OutRemoteCreateDto> // 远程文件创建
144
+ commonAddressList: Request<InPathCommonAddressList, OutAddressListDto> // 地址列表
145
+ storeComboBox: Request<InPathStoreComboBox & InQueryStoreComboBox, OutComboBoxWarehouseStoreDto> // 仓库下拉
146
+ reservoirList: Request<InQueryReservoirList, OutListReservoirDto> // 库区列表
147
+ shelveList: Request<InQueryShelveList, OutShelveListV2Dto> // 货架列表
148
+ merchantList: Request<InMerchantListBusDto, OutMerchantListBusDto> // 商户列表
149
+ businessList: Request<InQueryBusinessList, OutListBusDto> // 业务线列表
150
+ }
151
+ ```
152
+
153
+ ### IConfigContext
154
+
155
+ Context 值类型:
156
+
157
+ ```typescript
158
+ type IConfigContext = {
159
+ apiPayload: Partial<IApiPayload>
160
+ apiService: IApiService
161
+ }
162
+ ```
163
+
164
+ ### ConfigContext
165
+
166
+ ```typescript
167
+ const ConfigContext: React.Context<IConfigContext | null>
168
+ ```
169
+
170
+ ## 常见陷阱
171
+
172
+ - ❌ 未在应用入口包裹 `ConfigProvider`,直接使用 Effect 组件:
173
+ ```tsx
174
+ // 所有 Effect 组件会因为缺少 Context 而报错
175
+ <EffectBrandSelect />
176
+ ```
177
+ - ✅ 在应用最外层包裹 `ConfigProvider`:
178
+
179
+ ```tsx
180
+ <ConfigProvider apiPayload={payload}>
181
+ <EffectBrandSelect />
182
+ </ConfigProvider>
183
+ ```
184
+
185
+ - ❌ 传入完整的 `apiService` 对象但遗漏了某些方法 —— 不会报错但运行时调用缺失方法会崩溃
186
+ - ✅ 只覆盖需要自定义的方法,其余自动使用默认的 `saasApiService`:
187
+ ```tsx
188
+ <ConfigProvider apiService={{ brandComboBox: myBrandApi }}>
189
+ ```
190
+
191
+ ## 相关组件
192
+
193
+ | 场景 | 组件 | 说明 |
194
+ | -------- | ----------------------- | ------------------------------------------------------ |
195
+ | 品牌选择 | `EffectBrandSelect` | 依赖 ConfigProvider 提供 apiService.brandComboBox |
196
+ | 分类选择 | `EffectCategoryCascade` | 依赖 ConfigProvider 提供 apiService.categoryListToTree |
197
+ | 文件上传 | `EffectFileUpload` | 依赖 ConfigProvider 提供 apiService.uploadUploadFile |
198
+ | 商品范围 | `EffectScopeSelect` | 内部聚合多个 Effect 组件,间接依赖 ConfigProvider |
@@ -0,0 +1,109 @@
1
+ # Countdown
2
+
3
+ > 倒计时组件,支持 `date`(天时分秒格式)和 `second`(纯秒数)两种展示模式。
4
+
5
+ ## 导入
6
+
7
+ ```tsx
8
+ import { Countdown, formatDate } from '@xfe-repo/web-components'
9
+ import type { CountdownProps } from '@xfe-repo/web-components'
10
+ ```
11
+
12
+ ## 基本用法
13
+
14
+ ### 秒数模式(默认)
15
+
16
+ ```tsx
17
+ import { Countdown } from '@xfe-repo/web-components'
18
+
19
+ function Timer() {
20
+ return <Countdown init={60} /> {/* 显示: 60, 59, 58... */}
21
+ }
22
+ ```
23
+
24
+ ### 日期模式
25
+
26
+ ```tsx
27
+ <Countdown init={3661} mode="date" /> {/* 显示: 0天01:01:01 */}
28
+ ```
29
+
30
+ ## 进阶用法
31
+
32
+ ### 自定义结束文案
33
+
34
+ ```tsx
35
+ <Countdown
36
+ init={10}
37
+ mode="date"
38
+ onEnd={() => '已过期'} // 倒计时结束后显示"已过期"
39
+ />
40
+ ```
41
+
42
+ ### 监听每秒变化
43
+
44
+ ```tsx
45
+ <Countdown
46
+ init={300}
47
+ mode="date"
48
+ onInterval={(remainSeconds) => {
49
+ if (remainSeconds <= 10) {
50
+ console.log('即将过期')
51
+ }
52
+ }}
53
+ />
54
+ ```
55
+
56
+ ### 自定义日期格式
57
+
58
+ ```tsx
59
+ <Countdown
60
+ init={7200}
61
+ mode="date"
62
+ // 显示: 02小时00分00秒
63
+ formatStr="HH小时MM分SS秒"
64
+ />
65
+ ```
66
+
67
+ ## Props
68
+
69
+ ```typescript
70
+ export interface CountdownProps {
71
+ init: number | string
72
+ onEnd?: () => string | void
73
+ onInterval?: (s: number) => string | void
74
+ mode?: 'date' | 'second'
75
+ formatStr?: string
76
+ className?: string
77
+ }
78
+ ```
79
+
80
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
81
+ | ---------- | ------------------------------- | ---- | ---------------- | ----------------------------------------------------- |
82
+ | init | `number \| string` | 是 | - | 初始倒计时秒数,或直接显示的字符串 |
83
+ | mode | `'date' \| 'second'` | 否 | - | 展示模式。`date` 格式化为天时分秒;不传则直接显示秒数 |
84
+ | formatStr | `string` | 否 | `'DD天HH:MM:SS'` | 日期模式的格式字符串,支持 DD/HH/MM/SS |
85
+ | onEnd | `() => string \| void` | 否 | - | 倒计时结束回调,返回字符串则替换显示内容 |
86
+ | onInterval | `(s: number) => string \| void` | 否 | - | 每秒触发,参数为剩余秒数 |
87
+ | className | `string` | 否 | - | 自定义 className |
88
+
89
+ ## 导出类型
90
+
91
+ ### formatDate
92
+
93
+ ```typescript
94
+ export function formatDate(s: number, formatStr?: string): string
95
+ ```
96
+
97
+ 独立的秒数格式化函数,将秒数转换为 `DD天HH:MM:SS` 格式。
98
+
99
+ ## 常见陷阱
100
+
101
+ - ❌ `init` 传入字符串类型时,倒计时不会启动,仅静态展示该字符串
102
+ - ✅ 需要倒计时功能必须传入 `number` 类型
103
+
104
+ ## 相关组件
105
+
106
+ | 场景 | 组件 | 说明 |
107
+ | -------- | --------- | ----------------- |
108
+ | 正向计时 | `Counter` | 从 0 开始递增计数 |
109
+ | 实时时钟 | `Clock` | 展示当前时间 |
@@ -0,0 +1,75 @@
1
+ # Counter
2
+
3
+ > 正向计数器组件,`loading` 为 true 时开始从初始值递增,停止时触发结束回调。
4
+
5
+ ## 导入
6
+
7
+ ```tsx
8
+ import { Counter } from '@xfe-repo/web-components'
9
+ import type { CounterProps } from '@xfe-repo/web-components'
10
+ ```
11
+
12
+ ## 基本用法
13
+
14
+ ```tsx
15
+ import { Counter } from '@xfe-repo/web-components'
16
+ import { useState } from 'react'
17
+
18
+ function Timer() {
19
+ const [running, setRunning] = useState(false)
20
+
21
+ return (
22
+ <div>
23
+ <Counter loading={running} />
24
+ <button onClick={() => setRunning(!running)}>{running ? '停止' : '开始'}</button>
25
+ </div>
26
+ )
27
+ }
28
+ ```
29
+
30
+ ## 进阶用法
31
+
32
+ ### 自定义递增步长
33
+
34
+ ```tsx
35
+ <Counter loading={true} interval={5} /> {/* 每秒增加 5 */}
36
+ ```
37
+
38
+ ### 结束回调
39
+
40
+ ```tsx
41
+ <Counter
42
+ loading={isProcessing}
43
+ onEnd={() => '已完成'} // loading 变为 false 时显示"已完成"
44
+ onInterval={(value) => console.log('当前计数:', value)}
45
+ />
46
+ ```
47
+
48
+ ## Props
49
+
50
+ ```typescript
51
+ export interface CounterProps {
52
+ loading: boolean
53
+ onEnd?: () => string | void
54
+ onInterval?: (s: number) => string | void
55
+ interval?: number
56
+ className?: string
57
+ init?: number | string
58
+ }
59
+ ```
60
+
61
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
62
+ | ---------- | ------------------------------- | ---- | ------ | ------------------------------------ |
63
+ | loading | `boolean` | 是 | - | 是否正在计数 |
64
+ | init | `number \| string` | 否 | `0` | 初始值 |
65
+ | interval | `number` | 否 | `1` | 每秒递增的步长 |
66
+ | onEnd | `() => string \| void` | 否 | - | 停止时回调,返回字符串则替换显示内容 |
67
+ | onInterval | `(s: number) => string \| void` | 否 | - | 每秒触发,参数为当前计数值 |
68
+ | className | `string` | 否 | - | 自定义 className |
69
+
70
+ ## 相关组件
71
+
72
+ | 场景 | 组件 | 说明 |
73
+ | -------- | ----------- | ------------------ |
74
+ | 倒计时 | `Countdown` | 从指定秒数递减到 0 |
75
+ | 实时时钟 | `Clock` | 展示当前时间 |
@@ -0,0 +1,112 @@
1
+ # Currency
2
+
3
+ > 金额展示组件,支持分/角/元单位自动换算,统一以"¥"前缀展示。
4
+
5
+ ## 导入
6
+
7
+ ```tsx
8
+ import { Currency } from '@xfe-repo/web-components'
9
+ import type { CurrencyProps, CurrencyUnit } from '@xfe-repo/web-components'
10
+ ```
11
+
12
+ ## 基本用法
13
+
14
+ ```tsx
15
+ import { Currency } from '@xfe-repo/web-components'
16
+
17
+ // 后端返回金额单位为"分"
18
+ function Price() {
19
+ return <Currency>{9990}</Currency> {/* 显示: ¥99.90 */}
20
+ }
21
+ ```
22
+
23
+ > ⚠️ **`unit` 默认为 `'fen'`(分)**。如果后端返回的金额单位已经是"元",必须显式设置 `unit="yuan"`,否则金额将被放大 100 倍。
24
+
25
+ ## 进阶用法
26
+
27
+ ### 指定单位
28
+
29
+ ```tsx
30
+ <Currency unit="yuan">{99.9}</Currency> {/* 显示: ¥99.90 */}
31
+ <Currency unit="jiao">{999}</Currency> {/* 显示: ¥99.90 */}
32
+ <Currency unit="fen">{9990}</Currency> {/* 显示: ¥99.90 */}
33
+ ```
34
+
35
+ ### 自定义小数位
36
+
37
+ ```tsx
38
+ <Currency toFixed={0}>{9990}</Currency> {/* 显示: ¥100 */}
39
+ <Currency toFixed={3}>{9990}</Currency> {/* 显示: ¥99.900 */}
40
+ ```
41
+
42
+ ### 空值和脱敏值处理
43
+
44
+ ```tsx
45
+ <Currency>{undefined}</Currency> {/* 显示: -- */}
46
+ <Currency>{null}</Currency> {/* 显示: -- */}
47
+ <Currency>{'***'}</Currency> {/* 显示: ¥ *** */}
48
+ ```
49
+
50
+ ### 在 Table 列渲染中使用
51
+
52
+ 最常见场景(85%+ 使用率):
53
+
54
+ ```tsx
55
+ const columns = [
56
+ {
57
+ title: '金额',
58
+ dataIndex: 'amount',
59
+ render: (amount: number) => <Currency>{amount}</Currency>,
60
+ align: 'center' as const,
61
+ },
62
+ ]
63
+ ```
64
+
65
+ ## Props
66
+
67
+ ```typescript
68
+ export type CurrencyUnit = 'yuan' | 'jiao' | 'fen'
69
+
70
+ export interface CurrencyProps {
71
+ unit?: CurrencyUnit
72
+ toFixed?: number
73
+ children?: number | string
74
+ className?: string
75
+ }
76
+ ```
77
+
78
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
79
+ | --------- | --------------------------- | ---- | ------- | ------------------------------------- |
80
+ | unit | `'yuan' \| 'jiao' \| 'fen'` | 否 | `'fen'` | 金额单位,自动换算为元 |
81
+ | toFixed | `number` | 否 | `2` | 保留的小数位数 |
82
+ | children | `number \| string` | 否 | - | 金额值,为 null/undefined 时显示 `--` |
83
+ | className | `string` | 否 | - | 自定义 className |
84
+
85
+ ## 常见陷阱
86
+
87
+ - ❌ 后端返回"元"但未指定 unit,金额放大 100 倍:
88
+ ```tsx
89
+ // 后端返回 price = 99.9 (元)
90
+ <Currency>{price}</Currency> {/* 显示: ¥0.99 — 错误! */}
91
+ ```
92
+ - ✅ 根据后端单位正确设置 unit:
93
+
94
+ ```tsx
95
+ <Currency unit="yuan">{price}</Currency> {/* 显示: ¥99.90 — 正确 */}
96
+ ```
97
+
98
+ - ⚠️ 空值防御:`children` 为 `null`/`undefined` 时显示为 `--`。如需区分"未填写"与"零元",应在外层判断:
99
+ ```tsx
100
+ render: (amount) => (amount != null ? <Currency>{amount}</Currency> : '-')
101
+ ```
102
+
103
+ ### 汇总金额
104
+
105
+ ```tsx
106
+ const total = items.reduce((sum, item) => sum + (item.amount ?? 0), 0)
107
+ <Currency>{total}</Currency>
108
+ ```
109
+
110
+ ## 导出类型
111
+
112
+ > 类型定义见上方 Props 部分的 `CurrencyUnit`。
@@ -0,0 +1,110 @@
1
+ # EffectAddressCascade
2
+
3
+ > 省市区三级地址级联选择器,基于 Ant Design Cascader 实现异步按需加载,数据通过 `apiService.commonAddressList` 自动获取。
4
+
5
+ ## 导入
6
+
7
+ ```tsx
8
+ import { EffectAddressCascade } from '@xfe-repo/web-components'
9
+ import type { SelectItem } from '@xfe-repo/web-components'
10
+ ```
11
+
12
+ ## 基本用法
13
+
14
+ ```tsx
15
+ import { EffectAddressCascade } from '@xfe-repo/web-components'
16
+ import type { SelectItem } from '@xfe-repo/web-components'
17
+
18
+ function MyForm() {
19
+ const handleChange = (selectedList?: SelectItem[]) => {
20
+ // selectedList: [{ value: '省ID', label: '省名', index: 0 }, { value: '市ID', label: '市名', index: 1 }, ...]
21
+ console.log('选中地址:', selectedList)
22
+ }
23
+
24
+ return <EffectAddressCascade onChange={handleChange} />
25
+ }
26
+ ```
27
+
28
+ ## 进阶用法
29
+
30
+ ### 设置默认值
31
+
32
+ 通过 `defaultValue` 传入省、市、区的 ID 数组来设置初始选中值:
33
+
34
+ ```tsx
35
+ <EffectAddressCascade defaultValue={['110000', '110100', '110101']} onChange={(selectedList) => console.log(selectedList)} />
36
+ ```
37
+
38
+ ### 禁用状态
39
+
40
+ ```tsx
41
+ <EffectAddressCascade disabled defaultValue={['110000', '110100', '110101']} />
42
+ ```
43
+
44
+ ## Props
45
+
46
+ ```typescript
47
+ type SelectItem = { value: string; label: string; index: number }
48
+
49
+ type Props = {
50
+ className?: string
51
+ onChange?: (value?: SelectItem[]) => void
52
+ defaultValue?: string[]
53
+ disabled?: boolean
54
+ }
55
+ ```
56
+
57
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
58
+ | ------------ | -------------------------------- | ---- | ------ | ---------------------------------- |
59
+ | onChange | `(value?: SelectItem[]) => void` | 否 | - | 选中值变化回调,返回各级选中项数组 |
60
+ | defaultValue | `string[]` | 否 | - | 默认选中值,省/市/区 ID 组成的数组 |
61
+ | disabled | `boolean` | 否 | - | 禁用状态 |
62
+ | className | `string` | 否 | - | 自定义样式类名 |
63
+
64
+ ## 导出类型
65
+
66
+ ```typescript
67
+ // 选中项数据结构
68
+ export type SelectItem = {
69
+ value: string // 地区 ID
70
+ label: string // 地区名称
71
+ index: number // 在当前级别选项列表中的索引
72
+ }
73
+ ```
74
+
75
+ ## API 数据源
76
+
77
+ - **内部接口**:`apiService.commonAddressList`
78
+ - **请求参数**:`{ pid: string }`(父级地区 ID,首次加载传空字符串获取省份列表)
79
+ - **加载方式**:异步按需加载(`loadData`),选中省后加载市,选中市后加载区
80
+ - **可覆盖**:通过 `<ConfigProvider apiService={{ commonAddressList: customFn }}>` 替换默认实现
81
+
82
+ ## 常见陷阱
83
+
84
+ - ❌ 期望 `onChange` 返回字符串数组(如 `['省ID', '市ID', '区ID']`):
85
+ ```tsx
86
+ // onChange 返回的是 SelectItem[] 对象数组,不是简单字符串数组
87
+ ```
88
+ - ✅ 从 `SelectItem[]` 中提取所需字段:
89
+
90
+ ```tsx
91
+ <EffectAddressCascade
92
+ onChange={(selectedList) => {
93
+ const ids = selectedList?.map((item) => item.value) // ['110000', '110100', '110101']
94
+ const names = selectedList?.map((item) => item.label) // ['北京', '北京市', '东城区']
95
+ }}
96
+ />
97
+ ```
98
+
99
+ - ❌ 将组件当作受控组件使用(无 `value` prop)
100
+ - ✅ 本组件仅支持 `defaultValue` 设置初始值,不支持受控模式
101
+
102
+ ## 使用提示
103
+
104
+ > 💡 与 Form.Item 集成时可能需要 `valuePropName="defaultValue"` 解决非受控模式兼容问题。
105
+
106
+ ## 相关组件
107
+
108
+ | 场景 | 组件 | 说明 |
109
+ | -------- | ---------------- | -------------------------------------------- |
110
+ | API 配置 | `ConfigProvider` | 提供 `apiService.commonAddressList` 接口实现 |