Files
zkxw/docs/superpowers/plans/2026-05-26-action-column.md
T
2026-05-26 22:31:48 +08:00

4.5 KiB
Raw Blame History

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:所有按钮 disabled
  • selected.length === 1:所有按钮可用
  • selected.length > 1 && mode === 'single':disabled + tooltip「请选择单条记录」
  • danger=true:type="danger" 样式
  • disabled=true(调用方传入):始终禁用
  • 非 danger 按钮: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>

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 规则自动失效)