PlayfulCard.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <template>
  2. <view class="playful-card" :class="cardClasses" :style="computedStyle" @click="handleClick">
  3. <view class="playful-card__header" v-if="hasHeader">
  4. <slot name="header"></slot>
  5. </view>
  6. <view class="playful-card__content">
  7. <slot></slot>
  8. </view>
  9. <view class="playful-card__actions" v-if="hasActions">
  10. <slot name="actions"></slot>
  11. </view>
  12. </view>
  13. </template>
  14. <script>
  15. export default {
  16. name: 'PlayfulCard',
  17. props: {
  18. variant: { type: String, default: 'flat' },
  19. shadow: { type: String, default: 'md' },
  20. clickable: { type: Boolean, default: false },
  21. padding: { type: String, default: '' }
  22. },
  23. data() {
  24. return {
  25. hasHeader: false,
  26. hasActions: false
  27. }
  28. },
  29. mounted() {
  30. this.hasHeader = !!this.$slots.header
  31. this.hasActions = !!this.$slots.actions
  32. },
  33. computed: {
  34. cardClasses() {
  35. return [
  36. 'playful-card--' + this.variant,
  37. 'playful-card--shadow-' + this.shadow,
  38. this.clickable ? 'playful-card--clickable' : ''
  39. ].filter(Boolean)
  40. },
  41. computedStyle() {
  42. const style = {}
  43. if (this.padding) style.padding = this.padding
  44. return style
  45. }
  46. },
  47. methods: {
  48. handleClick(e) {
  49. if (this.clickable) this.$emit('click', e)
  50. }
  51. }
  52. }
  53. </script>
  54. <style scoped>
  55. .playful-card {
  56. background: var(--surface, #ffffff);
  57. border-radius: 20rpx;
  58. padding: 24rpx;
  59. transition: transform .15s ease, box-shadow .2s ease;
  60. }
  61. .playful-card--flat {
  62. border: 1px solid var(--border, #CBD5E1);
  63. box-shadow: var(--shadow-md);
  64. }
  65. .playful-card--clay {
  66. border: 1px solid var(--border-light, #E2E8F0);
  67. background: var(--surface, #FFFFFF);
  68. box-shadow: var(--shadow-md);
  69. }
  70. .playful-card--bordered {
  71. border: 1px solid var(--border-light, #E2E8F0);
  72. }
  73. .playful-card--teacher {
  74. border-left: 4px solid var(--color-primary, #5B9BD5);
  75. border-top: 1px solid var(--border-light, #E2E8F0);
  76. border-right: 1px solid var(--border-light, #E2E8F0);
  77. border-bottom: 1px solid var(--border-light, #E2E8F0);
  78. box-shadow: var(--shadow-sm);
  79. background: var(--surface, #ffffff);
  80. }
  81. .playful-card--shadow-none { box-shadow: none; }
  82. .playful-card--shadow-sm { box-shadow: var(--shadow-sm); }
  83. .playful-card--shadow-md { box-shadow: var(--shadow-md); }
  84. .playful-card--shadow-lg { box-shadow: var(--shadow-lg); }
  85. .playful-card--clickable:active {
  86. transform: scale(0.98);
  87. }
  88. .playful-card__header {
  89. font-weight: 700;
  90. font-size: 32rpx;
  91. margin-bottom: 16rpx;
  92. color: var(--text, #1E293B);
  93. }
  94. .playful-card__content {
  95. color: var(--text, #1E293B);
  96. line-height: 1.6;
  97. font-size: 28rpx;
  98. }
  99. .playful-card__actions {
  100. margin-top: 16rpx;
  101. display: flex;
  102. justify-content: flex-end;
  103. gap: 16rpx;
  104. flex-wrap: wrap;
  105. }
  106. </style>