point-selection-captcha-card.vue 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. <script setup lang="ts">
  2. import type { PointSelectionCaptchaCardProps } from '../types';
  3. import { computed } from 'vue';
  4. import { $t } from '@vben/locales';
  5. import {
  6. Card,
  7. CardContent,
  8. CardFooter,
  9. CardHeader,
  10. CardTitle,
  11. } from '@vben-core/shadcn-ui';
  12. const props = withDefaults(defineProps<PointSelectionCaptchaCardProps>(), {
  13. height: '220px',
  14. paddingX: '12px',
  15. paddingY: '16px',
  16. title: '',
  17. width: '300px',
  18. });
  19. const emit = defineEmits<{
  20. click: [MouseEvent];
  21. }>();
  22. const parseValue = (value: number | string) => {
  23. if (typeof value === 'number') {
  24. return value;
  25. }
  26. const parsed = Number.parseFloat(value);
  27. return Number.isNaN(parsed) ? 0 : parsed;
  28. };
  29. const rootStyles = computed(() => ({
  30. padding: `${parseValue(props.paddingY)}px ${parseValue(props.paddingX)}px`,
  31. width: `${parseValue(props.width) + parseValue(props.paddingX) * 2}px`,
  32. }));
  33. const captchaStyles = computed(() => {
  34. return {
  35. height: `${parseValue(props.height)}px`,
  36. width: `${parseValue(props.width)}px`,
  37. };
  38. });
  39. function handleClick(e: MouseEvent) {
  40. emit('click', e);
  41. }
  42. </script>
  43. <template>
  44. <Card :style="rootStyles" aria-labelledby="captcha-title" role="region">
  45. <CardHeader class="p-0">
  46. <CardTitle id="captcha-title" class="flex items-center justify-between">
  47. <template v-if="$slots.title">
  48. <slot name="title">{{ $t('ui.captcha.title') }}</slot>
  49. </template>
  50. <template v-else>
  51. <span>{{ title }}</span>
  52. </template>
  53. <div class="flex items-center justify-end">
  54. <slot name="extra"></slot>
  55. </div>
  56. </CardTitle>
  57. </CardHeader>
  58. <CardContent class="relative mt-2 flex w-full overflow-hidden rounded p-0">
  59. <img
  60. v-show="captchaImage"
  61. :alt="$t('ui.captcha.alt')"
  62. :src="captchaImage"
  63. :style="captchaStyles"
  64. class="relative z-10"
  65. @click="handleClick"
  66. />
  67. <div class="absolute inset-0">
  68. <slot></slot>
  69. </div>
  70. </CardContent>
  71. <CardFooter class="mt-2 flex justify-between p-0">
  72. <slot name="footer"></slot>
  73. </CardFooter>
  74. </Card>
  75. </template>