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 |
之前的演示文件 |
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
}
Files:
src/components/common/toolbar-action/index.vuesrc/components/common/amount-input/index.vue(组件结构参考)src/views/production/consumable/index.vue:46-72(工具栏按钮布局参考)Reference: src/assets/styles/core/el-ui.scss:987-995(.btn-ghost 样式)
[ ] Step 1: 创建组件文件
组件关键行为:
visible !== false 的 actionsselected.length === 0:所有按钮 disabledselected.length === 1:所有按钮可用selected.length > 1 && mode === 'single':disabled + tooltip「请选择单条记录」danger=true:type="danger" 样式disabled=true(调用方传入):始终禁用btn-ghost class<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>
Files: 无新增修改
Run: cd web-admin && pnpm build
Expected: 构建成功
Files:
Delete: web-admin/demo-action-column.html
[ ] Step 1: 删除演示文件
Run: rm web-admin/demo-action-column.html
min-width: 260px 规则自动失效)