168 lines
4.5 KiB
Markdown
168 lines
4.5 KiB
Markdown
# ToolbarAction 组件实施计划
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 封装 ToolbarAction 可复用组件,将操作按钮从表格操作列移至工具栏,通过勾选行激活操作。
|
||
|
||
**Architecture:** 新建 `src/components/common/toolbar-action/` 组件,接收 `selected`(已选行)和 `actions`(操作列表),根据选中数量和操作模式(batch/single)自动控制按钮禁用状态。复用现有 `.btn-ghost` 样式。
|
||
|
||
**Tech Stack:** Vue 3 + TypeScript + Element Plus
|
||
|
||
---
|
||
|
||
## 文件结构
|
||
|
||
| 操作 | 文件 | 职责 |
|
||
|------|------|------|
|
||
| 创建 | `src/components/common/toolbar-action/types.ts` | ToolbarActionItem 类型定义 |
|
||
| 创建 | `src/components/common/toolbar-action/index.vue` | 组件本体(模板 + 逻辑 + scoped 样式) |
|
||
| 删除 | `web-admin/demo-action-column.html` | 之前的演示文件 |
|
||
|
||
---
|
||
|
||
### Task 1: 创建类型定义
|
||
|
||
**Files:**
|
||
- Create: `src/components/common/toolbar-action/types.ts`
|
||
|
||
- [ ] **Step 1: 创建类型文件**
|
||
|
||
```ts
|
||
import type { Component } from 'vue'
|
||
|
||
export interface ToolbarActionItem {
|
||
label: string
|
||
icon?: Component
|
||
handler: (rows: any[]) => void
|
||
mode: 'batch' | 'single'
|
||
danger?: boolean
|
||
disabled?: boolean
|
||
visible?: boolean
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Task 2: 创建 ToolbarAction 组件
|
||
|
||
**Files:**
|
||
- Create: `src/components/common/toolbar-action/index.vue`
|
||
- Reference: `src/components/common/amount-input/index.vue`(组件结构参考)
|
||
- Reference: `src/views/production/consumable/index.vue:46-72`(工具栏按钮布局参考)
|
||
- Reference: `src/assets/styles/core/el-ui.scss:987-995`(`.btn-ghost` 样式)
|
||
|
||
- [ ] **Step 1: 创建组件文件**
|
||
|
||
组件关键行为:
|
||
- 过滤 `visible !== false` 的 actions
|
||
- `selected.length === 0`:所有按钮 disabled
|
||
- `selected.length === 1`:所有按钮可用
|
||
- `selected.length > 1 && mode === 'single'`:disabled + tooltip「请选择单条记录」
|
||
- `danger=true`:`type="danger"` 样式
|
||
- `disabled=true`(调用方传入):始终禁用
|
||
- 非 danger 按钮:`btn-ghost` class
|
||
|
||
```vue
|
||
<template>
|
||
<template v-for="action in visibleActions" :key="action.label">
|
||
<el-tooltip
|
||
v-if="isSingleDisabled(action)"
|
||
content="请选择单条记录"
|
||
placement="top"
|
||
>
|
||
<span class="toolbar-action-disabled-wrap">
|
||
<el-button
|
||
class="btn-ghost"
|
||
:type="action.danger ? 'danger' : undefined"
|
||
disabled
|
||
>
|
||
<el-icon v-if="action.icon"><component :is="action.icon" /></el-icon>
|
||
{{ action.label }}
|
||
</el-button>
|
||
</span>
|
||
</el-tooltip>
|
||
<el-button
|
||
v-else
|
||
class="btn-ghost"
|
||
:type="action.danger ? 'danger' : undefined"
|
||
:disabled="isDisabled(action)"
|
||
@click="action.handler(selected)"
|
||
>
|
||
<el-icon v-if="action.icon"><component :is="action.icon" /></el-icon>
|
||
{{ action.label }}
|
||
</el-button>
|
||
</template>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import type { ToolbarActionItem } from './types'
|
||
|
||
defineOptions({ name: 'ToolbarAction' })
|
||
|
||
interface Props {
|
||
selected: any[]
|
||
actions: ToolbarActionItem[]
|
||
}
|
||
|
||
const props = defineProps<Props>()
|
||
|
||
const visibleActions = computed(() =>
|
||
props.actions.filter((a) => a.visible !== false),
|
||
)
|
||
|
||
const selectedCount = computed(() => props.selected.length)
|
||
|
||
function isDisabled(action: ToolbarActionItem): boolean {
|
||
if (action.disabled) return true
|
||
if (selectedCount.value === 0) return true
|
||
if (action.mode === 'single' && selectedCount.value > 1) return true
|
||
return false
|
||
}
|
||
|
||
function isSingleDisabled(action: ToolbarActionItem): boolean {
|
||
return (
|
||
!action.disabled &&
|
||
action.mode === 'single' &&
|
||
selectedCount.value > 1
|
||
)
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.toolbar-action-disabled-wrap {
|
||
display: inline-flex;
|
||
margin-left: 12px;
|
||
}
|
||
</style>
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3: 验证构建
|
||
|
||
**Files:** 无新增修改
|
||
|
||
- [ ] **Step 1: 运行构建**
|
||
|
||
Run: `cd web-admin && pnpm build`
|
||
Expected: 构建成功
|
||
|
||
---
|
||
|
||
### Task 4: 清理演示文件
|
||
|
||
**Files:**
|
||
- Delete: `web-admin/demo-action-column.html`
|
||
|
||
- [ ] **Step 1: 删除演示文件**
|
||
|
||
Run: `rm web-admin/demo-action-column.html`
|
||
|
||
---
|
||
|
||
## 不在本计划范围
|
||
|
||
- 改造现有页面的操作列(后续按需逐步替换)
|
||
- 全局注册组件(按需 import 即可)
|
||
- 修改全局样式(使用 ToolbarAction 的页面移除操作列后,`min-width: 260px` 规则自动失效)
|