4.5 KiB
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: 创建类型文件
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:所有按钮 disabledselected.length === 1:所有按钮可用selected.length > 1 && mode === 'single':disabled + tooltip「请选择单条记录」danger=true:type="danger"样式disabled=true(调用方传入):始终禁用- 非 danger 按钮:
btn-ghostclass
<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规则自动失效)