gaoluyang
2026-06-24 c0cb161bb52ce0fbdce5c66ec391d107c75e2452
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<script setup lang="ts">
import type { ActionItem } from './types';
 
import { computed, ref } from 'vue';
 
import { cn } from '..\..\..\..\..\base\shared\src\utils';
 
import { Popover, PopoverContent, PopoverTrigger } from '../../ui';
import { VbenButton } from '../button';
import { VbenIcon } from '../icon';
 
const props = defineProps<{ action: ActionItem }>();
 
const open = ref(false);
 
const buttonClass = computed(() =>
  cn(
    'gap-1',
    props.action.danger && 'text-destructive hover:text-destructive',
    props.action.class,
  ),
);
 
const variant = computed(() => props.action.variant ?? 'link');
const size = computed(() => props.action.size ?? 'default');
 
function onClick() {
  if (props.action.disabled || props.action.loading) return;
  props.action.onClick?.();
}
 
function onConfirm() {
  open.value = false;
  const pc = props.action.popConfirm;
  if (pc?.confirm) {
    pc.confirm();
  } else {
    props.action.onClick?.();
  }
}
 
function onCancel() {
  open.value = false;
}
</script>
 
<template>
  <!-- 气泡确认 -->
  <Popover v-if="action.popConfirm" v-model:open="open">
    <PopoverTrigger as-child>
      <VbenButton
        :class="buttonClass"
        :disabled="action.disabled"
        :loading="action.loading"
        :size="size"
        class="p-2"
        :variant="variant"
      >
        <VbenIcon :icon="action.icon" v-if="action.icon" class="size-4" />
        <span v-if="action.text">{{ action.text }}</span>
      </VbenButton>
    </PopoverTrigger>
    <PopoverContent class="z-popup w-60" side="top">
      <div class="text-foreground mb-3 text-sm">
        {{ action.popConfirm.title ?? 'Are you sure?' }}
      </div>
      <div class="flex justify-end gap-2">
        <VbenButton size="default" variant="outline" @click="onCancel">
          {{ action.popConfirm.cancelText ?? 'Cancel' }}
        </VbenButton>
        <VbenButton
          :variant="action.danger ? 'destructive' : 'default'"
          size="default"
          class="p-2"
          @click="onConfirm"
        >
          {{ action.popConfirm.okText ?? 'OK' }}
        </VbenButton>
      </div>
    </PopoverContent>
  </Popover>
 
  <!-- 普通按钮 -->
  <VbenButton
    v-else
    :class="buttonClass"
    :disabled="action.disabled"
    :loading="action.loading"
    :size="size"
    class="p-2"
    :variant="variant"
    @click="onClick"
  >
    <VbenIcon :icon="action.icon" v-if="action.icon" class="size-4" />
    <span v-if="action.text">{{ action.text }}</span>
  </VbenButton>
</template>