bw-pro-table 0.0.4 → 0.0.6

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.
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # BwProTable
2
2
 
3
- 基于 **ant-design-vue 4** 的高级业务表格组件,提供 ProTable 级别的开箱即用体验。采用 Vue 3 Composition API + TypeScript 编写,提供完整的类型推导。
3
+ 基于 **ant-design-vue 4** 的高级业务表格组件(ProTable),提供开箱即用的数据表格体验。采用 Vue 3 Composition API + TypeScript 编写,提供完整的类型推导。
4
4
 
5
5
  ## 特性
6
6
 
7
7
  ### 已集成功能
8
8
 
9
9
  - 🚀 **双模式数据加载**:`request` 异步请求模式 与 `dataSource` 静态数据模式互斥,支持自动竞态保护与页码越界校验
10
- - 🎨 **12 种内置渲染器**:`text`、`number`、`date`、`tag`、`image`、`link`、`progress`、`avatar`、`action`、`index`、`currency`、`boolean`(含 `enum` 别名),支持 `defineColumnType` 注册自定义类型
10
+ - 🎨 **13 种内置渲染器**:`text`、`number`、`date`、`dateTime`、`tag`、`image`、`link`、`progress`、`avatar`、`action`、`index`、`currency`、`boolean`(含 `enum` 别名),支持 `defineColumnType` 注册自定义类型
11
11
  - 🔍 **三管道筛选系统**:搜索栏 + 表头筛选(ant-design-vue 原生)+ 列头搜索(Popover),独立运行并合并为 `mergedSearchParams`
12
12
  - 📊 **客户端筛选与排序**:DataSource 模式下自动应用 `applyClientFilters`(三管道合并)与 `applyClientSort`(支持自定义 sorter 函数)
13
13
  - ✏️ **行内编辑**:单元格级 / 行级双模式编辑,草稿数据管理,字段校验(required/type/min/max/pattern/validator),撤销/重做(Command Pattern),批量编辑
@@ -15,15 +15,15 @@
15
15
  - 💾 **状态持久化**:列配置、分页、密度、筛选、排序持久化到 `localStorage` / `sessionStorage` / 自定义 `StorageAdapter`,支持版本管理与数据校验
16
16
  - ✅ **跨页多选**:跨页保持选中状态,支持全选所有页(DataSource 内存 / Request 回调),最大选择数限制
17
17
  - 📎 **Excel 导入导出**:xlsx 按需懒加载,导出 Excel/CSV/选中行,导入预览/自动列映射/校验/模板下载
18
- - 🔄 **工具栏**:刷新、密度切换、全屏、列设置、边框/斑马纹切换、清除筛选、选中计数显示
18
+ - 🔄 **工具栏**:标题、刷新、密度切换、全屏、列设置、边框/斑马纹切换、清除筛选、选中计数显示
19
19
  - 🌐 **国际化**:vue-i18n 集成,`locale` prop 部分覆写,优先级:`props.locale` > `vue-i18n` > `zh-CN` 默认
20
20
  - 🎯 **TypeScript 全类型支持**:完整的 Props / Events / Slots / Methods / Composables 类型导出
21
21
 
22
22
  ### 已编码但未集成的功能
23
23
 
24
- 以下功能已在 `composables/` 中实现对应逻辑,类型定义已就绪,但**尚未在主组件 `BwProTable.vue` 中集成**,运行时不生效。详见 [未集成功能说明](#未集成功能说明) 章节。
24
+ 以下功能已在 `composables/` 或独立组件中实现对应逻辑,类型定义已就绪,但**尚未在主组件 `BwProTable.vue` 中集成**,运行时不生效。详见 [未集成功能说明](#未集成功能说明) 章节。
25
25
 
26
- - 右键菜单(`BwProTableContextMenu.vue`)
26
+ - 右键菜单(`BwProTableContextMenu.vue` + `useContextMenu`)
27
27
  - 高级筛选面板(`BwProTableAdvancedFilter.vue`)
28
28
  - 视图管理(`useTableView`)
29
29
  - 键盘导航(`useBwKeyboard`)
@@ -55,15 +55,19 @@ npm install bw-pro-table
55
55
  | `xlsx` | `^0.18.0` | Excel 导入导出功能(按需动态 `import()` 懒加载) |
56
56
  | `screenfull` | `^6.0.0` | 工具栏全屏切换功能 |
57
57
 
58
+ **运行环境**:
59
+
60
+ - Node.js `>=20.19.0`
61
+
58
62
  ## 快速开始
59
63
 
60
64
  ```vue
61
65
  <template>
62
66
  <BwProTable
63
- title="用户列表"
64
67
  :columns="columns"
65
68
  :request="fetchUsers"
66
69
  :row-selection="rowSelection"
70
+ :toolbar="{ title: '用户列表', refresh: true, columnSetting: true }"
67
71
  />
68
72
  </template>
69
73
 
@@ -90,8 +94,8 @@ const columns: ProColumnsType<User> = [
90
94
  dataIndex: 'status',
91
95
  valueType: 'tag',
92
96
  valueEnum: {
93
- active: { text: '启用', color: 'green' },
94
- inactive: { text: '禁用', color: 'red' },
97
+ active: { text: '启用', status: 'Success' },
98
+ inactive: { text: '禁用', status: 'Error' },
95
99
  },
96
100
  },
97
101
  { title: '创建时间', dataIndex: 'createdAt', valueType: 'date' },
@@ -130,7 +134,6 @@ const rowSelection = {
130
134
  | `rowKey` | `string \| GetRowKey` | `'id'` | 行唯一标识字段名或函数(函数式 rowKey 时编辑/选择等功能可能受限,建议用字符串) |
131
135
  | `tableId` | `string` | 随机生成 | 表格唯一标识,持久化命名空间必需 |
132
136
  | `cacheKey` | `string` | - | 持久化缓存键(与 `tableId` 二选一,优先使用 `cacheKey`) |
133
- | `title` | `string` | - | 表格标题(显示在工具栏) |
134
137
 
135
138
  #### 搜索
136
139
 
@@ -139,7 +142,13 @@ const rowSelection = {
139
142
  | `search` | `boolean \| SearchConfig` | - | 搜索栏配置,`false` 隐藏搜索栏,`true` 全部使用默认值 |
140
143
  | `columnSearch` | `false \| HeaderSearchConfig` | - | 列头搜索全局配置,`false` 禁用所有列的 `headerSearch` |
141
144
 
142
- > **SearchConfig**:`{ labelWidth?: number; defaultCollapsed?: boolean; resetText?: string; searchText?: string; collapsedCount?: number; colon?: boolean }`
145
+ > **SearchConfig**:`{ labelWidth?: number; defaultCollapsed?: boolean; resetText?: string; searchText?: string; collapsedCount?: number; colon?: boolean; searchFields?: SearchFieldConfig[] }`
146
+ >
147
+ > - `labelWidth`:搜索栏标签宽度,默认 `80`
148
+ > - `defaultCollapsed`:搜索栏默认是否折叠,默认 `false`
149
+ > - `collapsedCount`:折叠时显示的行数,默认 `4`
150
+ > - `colon`:是否显示 label 后的冒号,默认 `true`
151
+ > - `searchFields`:自定义搜索字段列表。未提供时降级为从 columns 自动生成(向后兼容)
143
152
 
144
153
  #### 工具栏
145
154
 
@@ -147,7 +156,12 @@ const rowSelection = {
147
156
  |------|------|--------|------|
148
157
  | `toolbar` | `false \| ToolbarConfig` | - | 工具栏配置,`false` 隐藏整个工具栏 |
149
158
 
150
- > **ToolbarConfig**:`{ refresh?: boolean; density?: boolean; fullscreen?: boolean; columnSetting?: boolean; export?: boolean \| ExportConfig; clearFilter?: boolean; import?: boolean \| ImportConfig; viewManager?: boolean; bordered?: boolean; striped?: boolean }`
159
+ > **ToolbarConfig**:`{ title?: string; refresh?: boolean; density?: boolean; fullscreen?: boolean; columnSetting?: boolean; export?: boolean \| ExportConfig; clearFilter?: boolean; import?: boolean \| ImportConfig; viewManager?: boolean; bordered?: boolean; striped?: boolean }`
160
+ >
161
+ > - `title`:工具栏左侧标题文本(注意:这是 BwProTable 自己的工具栏标题,非 antd Table 原生的 `title`,后者通过 `$attrs` 透传)
162
+ > - `bordered`:是否显示边框切换开关(默认 `true`)
163
+ > - `striped`:是否显示斑马纹切换开关(默认 `true`)
164
+ > - `viewManager`:视图管理按钮(**类型已定义,运行时未集成**)
151
165
 
152
166
  #### 功能配置
153
167
 
@@ -157,12 +171,12 @@ const rowSelection = {
157
171
  | `dragConfig` | `DragConfig` | - | 拖拽配置(当前仅 `columnDraggable` 生效) |
158
172
  | `rowSelection` | `TableRowSelection` | - | 行选择配置(透传 ant-design-vue) |
159
173
  | `crossPageSelection` | `false \| CrossPageSelectionConfig` | - | 跨页多选配置,`false` 禁用 |
160
- | `exportConfig` | `ExportConfig` | - | 导出配置(也可通过 `toolbar.export` 传入) |
161
- | `importConfig` | `ImportConfig` | - | 导入配置(也可通过 `toolbar.import` 传入) |
162
174
  | `contextMenu` | `ContextMenuConfig` | - | 右键菜单配置(**类型已定义,运行时未集成**) |
163
175
  | `persistence` | `false \| PersistenceConfig` | - | 持久化配置,`false` 禁用 |
164
176
 
165
- #### 样式与透传
177
+ > **注意**:导出/导入配置通过 `toolbar.export` / `toolbar.import` 传入,不存在独立的 `exportConfig` / `importConfig` 顶层 prop。
178
+
179
+ #### 样式与外观
166
180
 
167
181
  | 参数 | 类型 | 默认值 | 说明 |
168
182
  |------|------|--------|------|
@@ -170,15 +184,24 @@ const rowSelection = {
170
184
  | `bordered` | `boolean` | `false` | 是否显示边框 |
171
185
  | `striped` | `boolean` | `false` | 是否显示斑马纹 |
172
186
  | `defaultEmptyText` | `string` | `'-'` | 空单元格占位符(`null`/`undefined`/`''` 时显示) |
173
- | `loading` | `boolean` | - | 外部加载态(与内部状态机合并) |
187
+ | `loading` | `boolean \| { spinning?: boolean; tip?: string }` | - | 外部加载态(支持 antd SpinProps 对象形式,与内部状态机合并,用户传入值优先) |
174
188
  | `pagination` | `false \| TablePaginationConfig` | `{}` | 分页配置,`false` 禁用分页 |
175
- | `scroll` | `{ x?, y? }` | - | 表格滚动配置 |
176
- | `sticky` | `boolean \| { offsetHeader? }` | - | 表头固定 |
177
- | `expandable` | `ExpandableConfig` | - | 行展开配置 |
178
- | `rowClassName` | `(record, index) => string` | - | className 函数(与内置斑马纹/选中样式合并) |
179
- | `class` | `string` | - | 表格根元素 CSS 类名 |
180
- | `style` | `CSSProperties` | - | 表格根元素样式 |
189
+
190
+ #### 透传与扩展
191
+
192
+ | 参数 | 类型 | 默认值 | 说明 |
193
+ |------|------|--------|------|
181
194
  | `locale` | `Partial<BwProTableLocale>` | - | 国际化语言包,传入部分字段即可覆写 |
195
+ | `tableLocale` | `Record<string, any>` | - | 透传给 ant-design-vue Table 组件的原生 `locale`(如 Empty 组件文案),优先级高于 `locale` |
196
+ | `expandable` | `ExpandableConfig` | - | 行展开配置(透传 ant-design-vue) |
197
+ | `expandedRowKeys` | `(string \| number)[]` | - | 受控展开行 keys(等价于 `expandable.expandedRowKeys`,二者合并后 `expandable` 内同名属性优先) |
198
+ | `expandedRowRender` | `(props) => VNode` | - | 展开行渲染函数(等价于 `expandable.expandedRowRender`,二者合并后 `expandable` 内同名属性优先) |
199
+ | `rowClassName` | `(record, index) => string` | - | 行 className 函数(与内置斑马纹/选中样式合并) |
200
+
201
+ > **纯透传属性**:以下 ant-design-vue Table 原生属性不单独声明,通过 Vue `$attrs` + `v-bind="$attrs"` 自然流通至底层 `<a-table>`:
202
+ > `scroll`、`sticky`、`customRow`、`customHeaderRow`、`customCell`、`customHeaderCell`、`showHeader`、`indentSize`、`tableLayout`、`defaultExpandAllRows`、`class`、`style` 等。
203
+ >
204
+ > **注意**:`customCell` 的 class 会与内部溢出 class 合并(非替换);`customHeaderCell` 的事件处理器会与内部拖拽处理器链式调用(非替换)。
182
205
 
183
206
  ### Events
184
207
 
@@ -237,14 +260,14 @@ const rowSelection = {
237
260
 
238
261
  | 插槽名 | 作用域参数 | 说明 |
239
262
  |--------|-----------|------|
240
- | `search` | - | 自定义整个搜索栏(替换默认组件) |
241
- | `toolbar` | - | 自定义整个工具栏(替换默认组件) |
242
- | `toolbar-extra` | - | 工具栏左侧额外内容(追加到默认工具栏) |
243
- | `toolbar-right` | - | 工具栏右侧额外内容(追加到内置按钮组左侧) |
263
+ | `search` | - | 自定义整个搜索栏(替换默认 `BwProTableSearch` 组件) |
264
+ | `toolbar` | - | 自定义整个工具栏(替换默认 `BwProTableToolbar` 组件) |
265
+ | `toolbar-extra` | - | 工具栏左侧额外内容(在标题与内置按钮组之间) |
266
+ | `toolbar-right` | - | 工具栏右侧额外内容(在内置按钮组右侧) |
244
267
  | `bodyCell` | `{ column, record, index, text, value }` | 自定义单元格渲染(覆盖 valueType 渲染器) |
245
268
  | `headerCell` | `{ column }` | 自定义表头单元格(列头搜索 Popover 仍会追加在右侧) |
246
269
 
247
- > **插槽透传机制**:除上述具名插槽外,所有 ant-design-vue Table 原生插槽均通过 `v-for="$slots"` 透传支持。
270
+ > **插槽透传机制**:除上述具名插槽外,所有 ant-design-vue Table 原生插槽(如 `emptyText`、`title`、`footer` 等)均通过 `v-for="$slots"` 透传支持。
248
271
 
249
272
  ## ProColumnType 列定义
250
273
 
@@ -253,45 +276,45 @@ const rowSelection = {
253
276
  ```ts
254
277
  interface ProColumnType<RecordType = any> extends Omit<TableColumnType<RecordType>, 'children'> {
255
278
  // === 值渲染 ===
256
- valueType?: ValueType; // 内置渲染器类型
257
- valueEnum?: ValueEnumMap; // 枚举值映射(tag/enum 渲染 + 搜索栏 select)
258
- dateFormat?: string; // 日期格式(valueType='date',默认 'YYYY-MM-DD')
259
- precision?: number; // 小数精度(valueType='number'/'currency')
260
- currencyPrefix?: string; // 货币前缀(默认 '¥')
261
- currencySuffix?: string; // 货币后缀(默认 '')
262
- customRender?: RenderFn; // 自定义渲染函数(无 valueType 匹配时回退)
279
+ valueType?: ValueType; // 内置渲染器类型
280
+ valueEnum?: ValueEnumMap; // 枚举值映射(tag/enum 渲染 + 搜索栏 select)
281
+ dateFormat?: string; // 日期格式(valueType='date',默认 'YYYY-MM-DD')
282
+ dateTimeFormat?: string; // 日期时间格式(valueType='dateTime',默认 'YYYY-MM-DD HH:mm:ss')
283
+ precision?: number; // 小数精度(valueType='number'/'currency'
284
+ currencyPrefix?: string; // 货币前缀(默认 '¥')
285
+ currencySuffix?: string; // 货币后缀
286
+ customRender?: RenderFn; // 自定义渲染函数(无 valueType 匹配时回退)
263
287
 
264
288
  // === 空值与溢出 ===
265
- emptyText?: string; // 空单元格占位符(覆盖全局 defaultEmptyText)
289
+ emptyText?: string; // 空单元格占位符(覆盖全局 defaultEmptyText)
266
290
  overflow?: 'ellipsis' | 'wrap' | 'clip'; // 溢出策略
267
291
 
268
292
  // === 搜索 ===
269
- search?: boolean | SearchFieldConfig; // 搜索栏字段配置(true 启用自动匹配控件)
293
+ hideInSearch?: boolean; // 是否在搜索栏中隐藏该列(默认 false,即显示在搜索栏)
270
294
  headerSearch?: boolean | HeaderSearchConfig; // 列头搜索(仅 valueType='text' 生效)
271
295
  renderFormItem?: (context: { model, search, resetField }) => VNode; // 自定义搜索表单控件
272
- hideInSearch?: boolean; // 是否在搜索栏中隐藏该列(默认 false)
273
296
 
274
297
  // === 编辑 ===
275
- editable?: boolean | ((record) => boolean); // 是否可编辑
276
- formRules?: FormRule[]; // 编辑校验规则
277
- editComponent?: string; // 编辑态组件类型(当前按 valueType 自动匹配)
278
- editComponentProps?: Record<string, any>; // 编辑态组件额外属性
298
+ editable?: boolean | ((record) => boolean); // 是否可编辑
299
+ formRules?: FormRule[]; // 编辑校验规则
300
+ editComponent?: string; // 编辑态组件类型(当前按 valueType 自动匹配)
301
+ editComponentProps?: Record<string, any>; // 编辑态组件额外属性
279
302
 
280
303
  // === 渲染器专属 ===
281
- actions?: ActionItem[]; // 操作列按钮(valueType='action')
282
- imageWidth?: number; // 图片宽度(默认 32)
283
- imageHeight?: number; // 图片高度(默认 32)
284
- linkProps?: { href?, target?, onClick? }; // 链接配置
285
- progressProps?: { strokeColor? }; // 进度条配置
304
+ actions?: ActionItem[]; // 操作列按钮(valueType='action')
305
+ imageWidth?: number; // 图片宽度(默认 32)
306
+ imageHeight?: number; // 图片高度(默认 32)
307
+ linkProps?: { href?, target?, onClick? }; // 链接配置
308
+ progressProps?: { strokeColor? }; // 进度条配置
286
309
  avatarProps?: { srcField?, nameField?, showName?, size?, shape? }; // 头像配置
287
- booleanSwitch?: boolean; // 布尔列使用 Switch 开关(默认图标)
310
+ booleanSwitch?: boolean; // 布尔列使用 Switch 开关(默认图标)
288
311
 
289
312
  // === 其他 ===
290
- hidden?: boolean; // 是否隐藏列
291
- description?: string; // 表头说明文字(Tooltip 显示)
292
- columnGroup?: string; // 列所属分组
293
- authority?: string | string[]; // 列级权限标识(类型已定义,运行时未集成)
294
- children?: ProColumnsType; // 子列(分组表头)
313
+ hidden?: boolean; // 是否隐藏列
314
+ description?: string; // 表头说明文字(Tooltip 显示)
315
+ columnGroup?: string; // 列所属分组
316
+ authority?: string | string[]; // 列级权限标识(类型已定义,运行时未集成)
317
+ children?: ProColumnsType; // 子列(分组表头)
295
318
  }
296
319
  ```
297
320
 
@@ -300,7 +323,7 @@ interface ProColumnType<RecordType = any> extends Omit<TableColumnType<RecordTyp
300
323
  ```ts
301
324
  interface ActionItem<RecordType = any> {
302
325
  label: string; // 按钮文字
303
- type?: 'primary' | 'dashed' | 'link' | 'text' | 'default'; // 按钮类型(默认 'link')
326
+ type?: 'primary' | 'dashed' | 'link' | 'text' | 'default'; // 按钮类型
304
327
  danger?: boolean; // 危险操作样式
305
328
  icon?: string; // @ant-design/icons-vue 图标名
306
329
  confirm?: string; // 气泡确认文案(设置后点击先弹 Popconfirm)
@@ -331,9 +354,10 @@ interface FormRule {
331
354
 
332
355
  | valueType | 渲染输出 | 支持的额外列属性 |
333
356
  |-----------|----------|------------------|
334
- | `text` | 文本 + Tooltip(`ellipsis !== false` 时) | `emptyText`、`ellipsis` |
357
+ | `text` | 文本 + Tooltip(`ellipsis !== false` 时) | `emptyText`、`overflow` |
335
358
  | `number` | 千分位格式化数字 | `precision`、`emptyText` |
336
359
  | `date` | dayjs 格式化日期 | `dateFormat`(默认 `'YYYY-MM-DD'`)、`emptyText` |
360
+ | `dateTime` | dayjs 格式化日期时间 | `dateTimeFormat`(默认 `'YYYY-MM-DD HH:mm:ss'`)、`dateFormat`(回退)、`emptyText` |
337
361
  | `currency` | 货币符号 + 千分位 | `precision`、`currencyPrefix`(默认 `'¥'`)、`currencySuffix`、`emptyText` |
338
362
  | `tag` / `enum` | `a-tag` + 颜色 | `valueEnum`、`emptyText` |
339
363
  | `image` | `a-image` 缩略图(含预览) | `imageWidth`(默认 32)、`imageHeight`(默认 32)、`emptyText` |
@@ -368,10 +392,10 @@ const columns = [
368
392
 
369
393
  ```ts
370
394
  type RendererFn = (ctx: {
371
- value: any; // 单元格值
372
- record: any; // 行数据
373
- index: number; // 行索引
374
- column: ProColumnType; // 列配置
395
+ value: any; // 单元格值
396
+ record: any; // 行数据
397
+ index: number; // 行索引
398
+ column: ProColumnType; // 列配置
375
399
  }) => VNode | string | number;
376
400
  ```
377
401
 
@@ -385,6 +409,7 @@ type RendererFn = (ctx: {
385
409
  | `hasRenderer(type)` | 判断渲染器是否存在 |
386
410
  | `getRendererSafe(type)` | 获取渲染器(自动初始化内置渲染器) |
387
411
  | `ensureRenderers()` | 惰性初始化所有内置渲染器(幂等) |
412
+ | `initBuiltinRenderers()` | 同 `ensureRenderers`(保留旧 API 兼容) |
388
413
  | `resetRenderers()` | 重置注册表(仅用于测试隔离) |
389
414
 
390
415
  ## 数据加载模式
@@ -424,7 +449,6 @@ const request = async (params: {
424
449
 
425
450
  ```ts
426
451
  const dataSource = ref<User[]>([...]);
427
-
428
452
  // 模板
429
453
  <BwProTable :columns="columns" :data-source="dataSource" />
430
454
  ```
@@ -434,7 +458,7 @@ const dataSource = ref<User[]>([...]);
434
458
  按以下顺序对数据应用三管道筛选:
435
459
 
436
460
  1. **searchFormParams**(搜索栏):
437
- - `tag`/`boolean`/`number`/`currency`/`date` 类型 → 精确匹配(`===`)
461
+ - `tag`/`boolean`/`number`/`currency`/`date`/`dateTime` 类型 → 精确匹配(`===`)
438
462
  - `text`/其他类型 → 子串匹配(大小写不敏感)
439
463
  2. **headerSearchParams**(列头搜索):子串匹配(大小写不敏感)
440
464
  3. **tableFilterParams**(表头筛选):数组 `includes` 或精确匹配
@@ -474,6 +498,7 @@ const dataSource = ref<User[]>([...]);
474
498
  | `boolean` | `a-select`(是/否选项) |
475
499
  | `number` / `currency` | `a-input-number` |
476
500
  | `date` | `a-date-picker` |
501
+ | `dateTime` | `a-date-picker` |
477
502
  | `image` / `avatar` / `progress` / `action` / `index` | 不可搜索(自动排除) |
478
503
  | 其他 | `a-input`(兜底) |
479
504
 
@@ -507,7 +532,7 @@ const dataSource = ref<User[]>([...]);
507
532
  { title: '姓名', dataIndex: 'name', valueType: 'text', headerSearch: { placeholder: '搜索姓名' } }
508
533
  ```
509
534
 
510
- **HeaderSearchConfig**:`{ enabled?, placeholder?, searchText?, resetText? }`
535
+ **HeaderSearchConfig**:`{ enabled?: boolean; placeholder?: string; searchText?: string; resetText?: string }`
511
536
 
512
537
  全局配置通过 `columnSearch` prop:
513
538
  - `columnSearch: false` → 禁用所有列的列头搜索
@@ -540,7 +565,7 @@ interface EditConfig<RecordType = any> {
540
565
  | `cell` | `startCellEdit(rowKey, field)` | 仅单个单元格进入编辑态,其他单元格正常显示 |
541
566
  | `row` | `startRowEdit(rowKey)` | 整行进入编辑态 |
542
567
 
543
- **草稿数据管理**:编辑期间的修改存储在 `draftData: Map<rowKey, Record<field, value>>`,保存时合并到数据源,取消时回滚到 `originalData` 备份。
568
+ **草稿数据管理**:编辑期间的修改存储在 `draftData: Map<rowKey, Record<field, value>>`,保存时合并到数据源,取消时回滚到原始数据备份。
544
569
 
545
570
  ### 编辑组件自动匹配
546
571
 
@@ -550,6 +575,7 @@ interface EditConfig<RecordType = any> {
550
575
  |-----------|----------|
551
576
  | `number` / `currency` | `a-input-number` |
552
577
  | `date` | `a-date-picker`(格式使用 `dateFormat` 或默认 `'YYYY-MM-DD'`) |
578
+ | `dateTime` | `a-date-picker`(格式使用 `dateTimeFormat`,回退 `dateFormat`,默认 `'YYYY-MM-DD HH:mm:ss'`) |
553
579
  | `tag` / `enum` | `a-select`(选项来自 `valueEnum`) |
554
580
  | `boolean` | `a-switch` |
555
581
  | 其他(`text` 等) | `a-input` |
@@ -807,7 +833,7 @@ interface ExportConfig {
807
833
 
808
834
  **导出列处理**:自动排除 `hidden: true` 的列和特殊列(`index`/`action`),表头使用 `columnMapping[dataIndex]` 或 `column.title`。
809
835
 
810
- **分片导出**:数据量超过 `chunkSize` 时分片构建 sheet,每 5 片 yield 到主线程避免阻塞,进度通过 `exportProgress` ref 暴露。
836
+ **分片导出**:数据量超过 `chunkSize` 时分片构建 sheet,每 5 片 yield 到主线程避免阻塞。
811
837
 
812
838
  ### ImportConfig 导入配置
813
839
 
@@ -853,6 +879,7 @@ tableRef.value.downloadTemplate(
853
879
  ```vue
854
880
  <BwProTable
855
881
  :toolbar="{
882
+ title: '用户列表', // 工具栏标题
856
883
  refresh: true, // 刷新按钮
857
884
  density: true, // 密度切换(small/middle/default)
858
885
  fullscreen: true, // 全屏切换
@@ -866,6 +893,8 @@ tableRef.value.downloadTemplate(
866
893
  />
867
894
  ```
868
895
 
896
+ > **注意**:`toolbar.title` 是 BwProTable 工具栏自带的标题,与 ant-design-vue Table 原生的 `title` 插槽/属性不同,后者通过 `$attrs` 透传。
897
+
869
898
  ### 全屏
870
899
 
871
900
  使用 `screenfull` 库实现全屏切换。全屏时动态切换 `getPopupContainer`,确保 Popover/Dropdown 挂载到全屏容器内(通过 `a-config-provider` 实现)。
@@ -898,7 +927,7 @@ props.locale > vue-i18n 全局消息 > zh-CN 默认值
898
927
 
899
928
  **方式二:vue-i18n 集成**
900
929
 
901
- vue-i18n 配置中添加 `bwProTable` 命名空间的消息,组件会自动读取当前 locale 对应的消息。
930
+ 组件通过 `useI18n({ useScope: 'global' })` 读取当前 locale 对应的消息,支持 `^9.0.0 || ^10.0.0 || ^11.0.0` 版本的 vue-i18n。在 vue-i18n 配置中添加对应的消息键即可。
902
931
 
903
932
  **方式三:导入默认中文包**
904
933
 
@@ -914,18 +943,25 @@ import { zhCN } from 'bw-pro-table';
914
943
 
915
944
  以下 composables 可独立于 `BwProTable` 组件使用(均已从 `index.ts` 导出):
916
945
 
917
- | Composable | 说明 |
918
- |------------|------|
919
- | `useBwRowEdit` | 行内编辑(草稿/校验/撤销重做/批量编辑) |
920
- | `useExportExcel` | Excel 导出(xlsx 懒加载/分片/进度) |
921
- | `useImportExcel` | Excel 导入(解析/映射/校验/预览) |
922
- | `usePersistence` | 状态持久化(localStorage/sessionStorage/自定义) |
923
- | `useBwRowSelection` | 行选择管理 |
924
- | `useQueryParams` | 查询参数管理 |
925
- | `useColumnHeaderSearch` | 列头搜索状态管理 |
926
- | `useLocale` / `mergeLocale` | 国际化工具 |
927
-
928
- 示例:
946
+ | Composable | 说明 | 状态 |
947
+ |------------|------|------|
948
+ | `useBwRowEdit` | 行内编辑(草稿/校验/撤销重做/批量编辑) | ✅ 已集成 |
949
+ | `useExportExcel` | Excel 导出(xlsx 懒加载/分片/进度) | ✅ 已集成 |
950
+ | `useImportExcel` | Excel 导入(解析/映射/校验/预览) | ✅ 已集成 |
951
+ | `usePersistence` | 状态持久化(localStorage/sessionStorage/自定义) | ✅ 已集成 |
952
+ | `useBwRowSelection` | 行选择管理 | ✅ 可独立使用 |
953
+ | `useQueryParams` | URL 查询参数管理 | ✅ 可独立使用 |
954
+ | `useColumnHeaderSearch` | 列头搜索状态管理 | ✅ 已集成 |
955
+ | `useContextMenu` | 右键菜单状态管理 | ⚠️ 未集成 |
956
+ | `useDragSort` | 拖拽排序 | ⚠️ 仅列拖拽集成 |
957
+ | `useBwKeyboard` | 键盘导航 | ⚠️ 未集成 |
958
+ | `useTableView` | 视图管理 | ⚠️ 未集成 |
959
+ | `useBwPermission` | 权限过滤 | ⚠️ 未集成 |
960
+ | `useLocale` / `mergeLocale` | 国际化工具 | ✅ 已集成 |
961
+
962
+ > ✅ 已集成 = 在 `BwProTable.vue` 中直接使用;可独立使用 = composable 已实现且类型导出,但主组件未引用;⚠️ 未集成 = 功能尚未在主组件中挂载。
963
+
964
+ 使用示例:
929
965
 
930
966
  ```ts
931
967
  import { useBwRowEdit, useExportExcel } from 'bw-pro-table';
@@ -939,9 +975,54 @@ const { editingKeys, startRowEdit, saveEdit, undo, redo } = useBwRowEdit({
939
975
  });
940
976
  ```
941
977
 
978
+ ### 完整导出清单
979
+
980
+ ```ts
981
+ // 组件
982
+ export { BwProTable } from 'bw-pro-table';
983
+
984
+ // 渲染器
985
+ export {
986
+ defineColumnType, ensureRenderers, getRendererSafe,
987
+ initBuiltinRenderers, resetRenderers,
988
+ } from 'bw-pro-table';
989
+
990
+ // 依赖注入
991
+ export { BW_PRO_TABLE_KEY } from 'bw-pro-table';
992
+ export type { BwProTableContext } from 'bw-pro-table';
993
+
994
+ // Composables
995
+ export {
996
+ useQueryParams, useBwRowEdit, useBwRowSelection,
997
+ useExportExcel, useImportExcel, usePersistence,
998
+ useContextMenu, useDragSort, useBwKeyboard,
999
+ useTableView, useBwPermission, useColumnHeaderSearch,
1000
+ useLocale, mergeLocale, BW_PRO_TABLE_LOCALE_KEY,
1001
+ } from 'bw-pro-table';
1002
+
1003
+ // 类型
1004
+ export type {
1005
+ ProColumnType, ProColumnsType, ValueType,
1006
+ ValueEnumItem, ValueEnumMap, ActionItem, FormRule,
1007
+ GetRowKey, TableRowSelection, ExpandableConfig,
1008
+ BwProTableProps, EditConfig, ContextMenuConfig, ContextMenuItem,
1009
+ DragConfig, ExportConfig, ImportConfig, ViewConfig,
1010
+ TableState, TableStatus, PersistedColumnState, PersistedTableState,
1011
+ StorageAdapter, PersistenceConfig, EditCommand,
1012
+ FilterOperator, AdvancedFilterCondition, AdvancedFilterGroup,
1013
+ RendererFn, RendererContext, BwProTableLocale,
1014
+ } from 'bw-pro-table';
1015
+
1016
+ // 常量
1017
+ export { DEFAULT_EMPTY_TEXT, DEFAULT_PAGE_SIZE, DEFAULT_DATE_FORMAT } from 'bw-pro-table';
1018
+
1019
+ // 国际化
1020
+ export { zhCN } from 'bw-pro-table';
1021
+ ```
1022
+
942
1023
  ## 未集成功能说明
943
1024
 
944
- 以下功能已在 `composables/` 或独立组件中实现,但**尚未在主组件 `BwProTable.vue` 中集成**,运行时不生效。相关类型定义已就绪,可在 types.ts 中查阅。
1025
+ 以下功能已在 `composables/` 或独立组件中实现,但**尚未在主组件 `BwProTable.vue` 中集成**,运行时不生效。相关类型定义已就绪,可在 `types.ts` 中查阅。
945
1026
 
946
1027
  | 功能 | 位置 | 类型定义 | 状态 |
947
1028
  |------|------|----------|------|
@@ -1013,6 +1094,77 @@ const columns = [{ title: '优先级', dataIndex: 'priority', valueType: 'priori
1013
1094
 
1014
1095
  > 使用 `bodyCell` 插槽会覆盖 valueType 渲染器的自动匹配。
1015
1096
 
1097
+ ### 跨页多选 + 批量编辑
1098
+
1099
+ ```vue
1100
+ <template>
1101
+ <BwProTable
1102
+ ref="tableRef"
1103
+ :columns="columns"
1104
+ :request="fetchUsers"
1105
+ :row-selection="{ type: 'checkbox' }"
1106
+ :cross-page-selection="{
1107
+ enabled: true,
1108
+ maxSelectCount: 100,
1109
+ onSelectAllPages: fetchAllKeys,
1110
+ }"
1111
+ :edit-config="editConfig"
1112
+ >
1113
+ <template #toolbar-right>
1114
+ <a-button @click="tableRef?.openBatchEdit()" :disabled="selectionCount === 0">
1115
+ 批量编辑选中项
1116
+ </a-button>
1117
+ </template>
1118
+ </BwProTable>
1119
+ </template>
1120
+ ```
1121
+
1122
+ ### 自定义持久化存储适配器
1123
+
1124
+ ```ts
1125
+ import type { StorageAdapter, PersistedTableState } from 'bw-pro-table';
1126
+
1127
+ const apiAdapter: StorageAdapter = {
1128
+ get: async (key: string) => {
1129
+ const res = await fetch(`/api/table-state/${key}`);
1130
+ return res.ok ? res.json() : null;
1131
+ },
1132
+ set: async (key: string, value: PersistedTableState) => {
1133
+ await fetch(`/api/table-state/${key}`, {
1134
+ method: 'PUT',
1135
+ headers: { 'Content-Type': 'application/json' },
1136
+ body: JSON.stringify(value),
1137
+ });
1138
+ },
1139
+ remove: async (key: string) => {
1140
+ await fetch(`/api/table-state/${key}`, { method: 'DELETE' });
1141
+ },
1142
+ };
1143
+ ```
1144
+
1145
+ ### 列变换管道(高级)
1146
+
1147
+ 理解列的变换顺序有助于自定义 `customCell` / `customHeaderCell` 等高级行为:
1148
+
1149
+ ```
1150
+ 用户定义的 columns
1151
+ → Stage 1: BwProTable.vue injectFilteredValue()
1152
+ 注入 filterValue/sortOrder/width 覆盖
1153
+ → Stage 2: BwProTable.vue displayColumns (computed)
1154
+ 过滤 hidden 列,按持久化顺序重排
1155
+ → Stage 3: BwProTableCore.vue wrappedColumns
1156
+ customCell class 合并(非替换),customHeaderCell 事件链式调用
1157
+ → Stage 4: <a-table> 渲染
1158
+ ```
1159
+
1160
+ | 列字段 | 行为说明 |
1161
+ |--------|----------|
1162
+ | `customCell` | class 合并为 `['user-class', 'bw-pro-table-cell-overflow-ellipsis'].join(' ')` |
1163
+ | `customHeaderCell` | 拖拽事件链式调用:用户处理器 → 内部处理器 |
1164
+ | `filteredValue` | **被覆盖**为内部控制值 |
1165
+ | `sortOrder` | **被覆盖**:当前排序列注入排序值,其余列强制 `null` |
1166
+ | `width` | 用户值优先,列宽拖拽覆盖值通过 rAF 批处理注入 |
1167
+
1016
1168
  ## License
1017
1169
 
1018
1170
  MIT
@@ -1,2 +1,2 @@
1
- .bw-pro-table-column-search[data-v-06f12966]{min-width:200px;padding:8px}.bw-pro-table-column-search .bw-pro-table-column-search-input[data-v-06f12966]{margin-bottom:8px}.bw-pro-table-column-search .bw-pro-table-column-search-actions[data-v-06f12966]{justify-content:flex-end;display:flex}.bw-pro-table-core[data-v-406475b2] .ant-result{padding:48px 0}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-overflow-ellipsis{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-overflow-wrap{white-space:normal;word-break:break-all;-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.bw-pro-table-core .bw-pro-table-header-cell[data-v-406475b2]{justify-content:space-between;align-items:center;width:100%;display:flex}.bw-pro-table-core .bw-pro-table-header-left[data-v-406475b2]{text-overflow:ellipsis;align-items:center;gap:4px;min-width:0;display:inline-flex;overflow:hidden}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-header-description-icon{color:var(--ant-color-text-secondary,#00000073);cursor:help;font-size:14px}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-row-selected{background-color:var(--ant-primary-1,#e6f4ff)!important}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-error .ant-input,.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-error .ant-input-number,.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-error .ant-select-selector,.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-error .ant-picker{border-color:var(--ant-color-error,#ff4d4f)!important}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-cell-error-msg{color:var(--ant-color-error,#ff4d4f);margin-top:4px;font-size:12px;line-height:1.5}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-header-drag-source{opacity:.45}.bw-pro-table-core[data-v-406475b2] .bw-pro-table-header-drag-target{box-shadow:inset 2px 0 0 0 var(--ant-primary-color,#1890ff)}.bw-pro-table-core .bw-pro-table-header-drag-icon[data-v-406475b2]{color:var(--ant-color-text-quaternary,#bfbfbf);cursor:grab;flex-shrink:0;font-size:16px;transition:color .2s}.bw-pro-table-core .bw-pro-table-header-drag-icon[data-v-406475b2]:hover{color:var(--ant-primary-color,#1890ff)}.bw-pro-table-core .bw-pro-table-header-drag-icon--active[data-v-406475b2]{color:var(--ant-primary-color,#1890ff);cursor:grabbing}.bw-pro-table-search[data-v-8bc76b31]{background:var(--ant-color-bg-container,#fff);border-radius:8px;padding:24px 24px 0}.bw-pro-table-search .bw-search-form[data-v-8bc76b31] .ant-form-inline{row-gap:16px}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex-wrap:nowrap!important;flex:0 0 100%!important;margin-bottom:0!important;margin-right:0!important}@media (width>=576px){.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex:0 0 calc(50% - 12px)!important;margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(2n){margin-right:0!important}}@media (width>=768px){.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex:0 0 calc(33.333% - 16px)!important;margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(2n){margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(3n){margin-right:0!important}}@media (width>=992px){.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex:0 0 calc(25% - 18px)!important;margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(3n){margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(4n){margin-right:0!important}}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-label{white-space:nowrap;align-items:center;overflow:hidden;flex:0 0 var(--bw-search-label-width,80px)!important;display:flex!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-label>label{text-overflow:ellipsis;white-space:nowrap;width:100%;overflow:hidden}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control{flex-direction:column;min-width:0;flex:1!important;display:flex!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control-input,.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control-input-content{width:100%}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control-input-content>*{box-sizing:border-box;width:100%!important}.bw-pro-table-search .bw-pro-table-search-actions{justify-content:flex-end;padding:16px;display:flex}.bw-pro-table-column-setting-panel[data-v-7e735b2d]{width:280px}.bw-pro-table-column-setting-header[data-v-7e735b2d]{border-bottom:1px solid #f0f0f0;justify-content:space-between;align-items:center;padding:12px 12px 8px;font-weight:600;display:flex}.bw-pro-table-column-setting-body[data-v-7e735b2d]{max-height:50vh;padding:4px 0;overflow-y:auto}.bw-pro-table-column-setting-item[data-v-7e735b2d]{cursor:default;align-items:center;gap:8px;padding:8px 12px;transition:background .15s;display:flex}.bw-pro-table-column-setting-item[data-v-7e735b2d]:hover{background:#fafafa}.bw-pro-table-column-setting-item--dragging[data-v-7e735b2d]{opacity:.45;background:#f0f0f0}.bw-pro-table-column-setting-item--drag-over[data-v-7e735b2d]{box-shadow:inset 0 2px 0 0 var(--ant-primary-color,#1890ff);background:#e6f7ff}.bw-pro-table-column-setting-item .bw-pro-table-column-drag-icon[data-v-7e735b2d]{color:#999;cursor:grab;flex-shrink:0;font-size:16px}.bw-pro-table-column-setting-item .bw-pro-table-column-drag-icon--active[data-v-7e735b2d]{color:var(--ant-primary-color,#1890ff);cursor:grabbing}.bw-pro-table-toolbar[data-v-db6f1492]{overflow:auto hidden}.bw-pro-table-toolbar .bw-pro-table-toolbar-container[data-v-db6f1492]{justify-content:space-between;align-items:center;height:64px;padding:0 24px;line-height:64px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-left[data-v-db6f1492]{align-items:center;gap:16px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-right[data-v-db6f1492]{align-items:center;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-title[data-v-db6f1492]{color:var(--ant-color-text,#000000d9);font-family:PingFangSC-Medium;font-size:16px}.bw-pro-table-toolbar .bw-pro-table-toolbar-selection-alert[data-v-db6f1492]{background:var(--ant-primary-1,#e6f4ff);border-bottom:1px solid var(--ant-primary-3,#91caff);justify-content:space-between;align-items:center;padding:8px 24px;font-size:14px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-selection-alert .bw-pro-table-toolbar-selection-count[data-v-db6f1492]{color:var(--ant-color-text,#000000d9)}.bw-pro-table[data-v-ce85e68e]{background:var(--ant-color-bg-container,#fff);border-radius:8px}.bw-pro-table[data-v-ce85e68e] .bw-pro-table-row-striped{background:var(--ant-color-bg-layout,#f5f5f5)}.bw-pro-table[data-v-ce85e68e] .bw-pro-table-row-selected{background-color:var(--ant-primary-1,#e6f4ff)!important}
1
+ .bw-pro-table-column-search[data-v-06f12966]{min-width:200px;padding:8px}.bw-pro-table-column-search .bw-pro-table-column-search-input[data-v-06f12966]{margin-bottom:8px}.bw-pro-table-column-search .bw-pro-table-column-search-actions[data-v-06f12966]{justify-content:flex-end;display:flex}.bw-pro-table-core[data-v-e5d41f2b] .ant-result{padding:48px 0}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-overflow-ellipsis{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-overflow-wrap{white-space:normal;word-break:break-all;-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.bw-pro-table-core .bw-pro-table-header-cell[data-v-e5d41f2b]{justify-content:space-between;align-items:center;width:100%;display:flex}.bw-pro-table-core .bw-pro-table-header-left[data-v-e5d41f2b]{text-overflow:ellipsis;align-items:center;gap:4px;min-width:0;display:inline-flex;overflow:hidden}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-header-description-icon{color:var(--ant-color-text-secondary,#00000073);cursor:help;font-size:14px}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-row-selected{background-color:var(--ant-primary-1,#e6f4ff)!important}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-error .ant-input,.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-error .ant-input-number,.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-error .ant-select-selector,.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-error .ant-picker{border-color:var(--ant-color-error,#ff4d4f)!important}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-cell-error-msg{color:var(--ant-color-error,#ff4d4f);margin-top:4px;font-size:12px;line-height:1.5}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-header-drag-source{opacity:.45}.bw-pro-table-core[data-v-e5d41f2b] .bw-pro-table-header-drag-target{box-shadow:inset 2px 0 0 0 var(--ant-primary-color,#1890ff)}.bw-pro-table-core .bw-pro-table-header-drag-icon[data-v-e5d41f2b]{color:var(--ant-color-text-quaternary,#bfbfbf);cursor:grab;flex-shrink:0;font-size:16px;transition:color .2s}.bw-pro-table-core .bw-pro-table-header-drag-icon[data-v-e5d41f2b]:hover{color:var(--ant-primary-color,#1890ff)}.bw-pro-table-core .bw-pro-table-header-drag-icon--active[data-v-e5d41f2b]{color:var(--ant-primary-color,#1890ff);cursor:grabbing}.bw-pro-table-search[data-v-51eef1de]{background:var(--ant-color-bg-container,#fff);border-radius:8px;padding:24px 24px 0}.bw-pro-table-search .bw-search-form[data-v-51eef1de] .ant-form-inline{row-gap:16px}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex-wrap:nowrap!important;flex:0 0 100%!important;margin-bottom:0!important;margin-right:0!important}@media (width>=576px){.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex:0 0 calc(50% - 12px)!important;margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(2n){margin-right:0!important}}@media (width>=768px){.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex:0 0 calc(33.333% - 16px)!important;margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(2n){margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(3n){margin-right:0!important}}@media (width>=992px){.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item{flex:0 0 calc(25% - 18px)!important;margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(3n){margin-right:24px!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item:nth-child(4n){margin-right:0!important}}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-label{white-space:nowrap;align-items:center;overflow:hidden;flex:0 0 var(--bw-search-label-width,80px)!important;display:flex!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-label>label{text-overflow:ellipsis;white-space:nowrap;width:100%;overflow:hidden}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control{flex-direction:column;min-width:0;flex:1!important;display:flex!important}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control-input,.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control-input-content{width:100%}.bw-pro-table-search [data-bw-search] .ant-form-inline .ant-form-item.bw-search-form-item .ant-form-item-control-input-content>*{box-sizing:border-box;width:100%!important}.bw-pro-table-search .bw-pro-table-search-actions{justify-content:flex-end;padding:16px;display:flex}.bw-pro-table-column-setting-panel[data-v-7e735b2d]{width:280px}.bw-pro-table-column-setting-header[data-v-7e735b2d]{border-bottom:1px solid #f0f0f0;justify-content:space-between;align-items:center;padding:12px 12px 8px;font-weight:600;display:flex}.bw-pro-table-column-setting-body[data-v-7e735b2d]{max-height:50vh;padding:4px 0;overflow-y:auto}.bw-pro-table-column-setting-item[data-v-7e735b2d]{cursor:default;align-items:center;gap:8px;padding:8px 12px;transition:background .15s;display:flex}.bw-pro-table-column-setting-item[data-v-7e735b2d]:hover{background:#fafafa}.bw-pro-table-column-setting-item--dragging[data-v-7e735b2d]{opacity:.45;background:#f0f0f0}.bw-pro-table-column-setting-item--drag-over[data-v-7e735b2d]{box-shadow:inset 0 2px 0 0 var(--ant-primary-color,#1890ff);background:#e6f7ff}.bw-pro-table-column-setting-item .bw-pro-table-column-drag-icon[data-v-7e735b2d]{color:#999;cursor:grab;flex-shrink:0;font-size:16px}.bw-pro-table-column-setting-item .bw-pro-table-column-drag-icon--active[data-v-7e735b2d]{color:var(--ant-primary-color,#1890ff);cursor:grabbing}.bw-pro-table-toolbar[data-v-e832720d]{overflow:auto hidden}.bw-pro-table-toolbar .bw-pro-table-toolbar-container[data-v-e832720d]{justify-content:space-between;align-items:center;height:64px;padding:0 24px;line-height:64px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-left[data-v-e832720d]{align-items:center;gap:16px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-right[data-v-e832720d]{align-items:center;gap:8px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-title[data-v-e832720d]{color:var(--ant-color-text,#000000d9);font-family:PingFangSC-Medium;font-size:16px}.bw-pro-table-toolbar .bw-pro-table-toolbar-selection-alert[data-v-e832720d]{background:var(--ant-primary-1,#e6f4ff);border-bottom:1px solid var(--ant-primary-3,#91caff);justify-content:space-between;align-items:center;padding:8px 24px;font-size:14px;display:flex}.bw-pro-table-toolbar .bw-pro-table-toolbar-selection-alert .bw-pro-table-toolbar-selection-count[data-v-e832720d]{color:var(--ant-color-text,#000000d9)}.bw-pro-table[data-v-a6808263]{background:var(--ant-color-bg-container,#fff);border-radius:8px}.bw-pro-table[data-v-a6808263] .bw-pro-table-row-striped td{background:var(--ant-color-bg-layout,#f5f5f5)!important}.bw-pro-table[data-v-a6808263] .bw-pro-table-row-selected td{background-color:var(--ant-primary-1,#e6f4ff)!important}
2
2
  /*$vite$:1*/