PlayfulCard.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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, #FED7AA);
  63. box-shadow: var(--shadow-md);
  64. }
  65. .playful-card--clay {
  66. border: 4rpx solid var(--border, #FED7AA);
  67. background: linear-gradient(145deg, #FFFFFF, var(--bg, #FFF7ED));
  68. box-shadow: var(--shadow-clay);
  69. }
  70. .playful-card--bordered {
  71. border: 1px solid var(--border-light, #FFEDD5);
  72. }
  73. .playful-card--teacher {
  74. border: 1px solid #DBEAFE;
  75. box-shadow: 0 4rpx 14rpx rgba(59, 130, 246, 0.08);
  76. background: var(--surface, #ffffff);
  77. }
  78. .playful-card--shadow-none { box-shadow: none; }
  79. .playful-card--shadow-sm { box-shadow: var(--shadow-sm); }
  80. .playful-card--shadow-md { box-shadow: var(--shadow-md); }
  81. .playful-card--shadow-lg { box-shadow: var(--shadow-lg); }
  82. .playful-card--clickable:active {
  83. transform: scale(0.98);
  84. }
  85. .playful-card__header {
  86. font-weight: 700;
  87. font-size: 32rpx;
  88. margin-bottom: 16rpx;
  89. color: var(--text, #3D2E1E);
  90. }
  91. .playful-card__content {
  92. color: var(--text, #3D2E1E);
  93. line-height: 1.6;
  94. font-size: 28rpx;
  95. }
  96. .playful-card__actions {
  97. margin-top: 16rpx;
  98. display: flex;
  99. justify-content: flex-end;
  100. gap: 16rpx;
  101. flex-wrap: wrap;
  102. }
  103. </style>