巴青农资商城

CartShopGroup.vue 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <view class="cart-shop">
  3. <view class="cart-shop__head">
  4. <view
  5. class="cart-shop__check"
  6. :class="{ 'cart-shop__check--disabled': !hasPurchasable }"
  7. @click.stop="onShopCheck"
  8. >
  9. <view class="check-icon" :class="{ 'check-icon--on': shopAllChecked && hasPurchasable }">
  10. <u-icon v-if="shopAllChecked && hasPurchasable" name="checkbox-mark" color="#fff" size="14" />
  11. </view>
  12. </view>
  13. <view class="cart-shop__name-wrap" @click="emit('shop-click', group)">
  14. <u-icon name="shop" color="#2e7d32" size="18" />
  15. <text class="cart-shop__name">{{ group.shopName }}</text>
  16. <text v-if="group.isClosed" class="cart-shop__tag">休息中</text>
  17. <u-icon name="arrow-right" color="#ccc" size="14" />
  18. </view>
  19. </view>
  20. <cart-item-row
  21. v-for="item in group.items"
  22. :key="item.cartItemId"
  23. :item="item"
  24. @check-change="(row, checked) => emit('check-change', row, checked)"
  25. @quantity-change="(row, qty) => emit('quantity-change', row, qty)"
  26. @delete="(row) => emit('delete', row)"
  27. @goods-click="(row) => emit('goods-click', row)"
  28. />
  29. </view>
  30. </template>
  31. <script setup>
  32. import { computed } from 'vue'
  33. import CartItemRow from '@/components/cart/CartItemRow.vue'
  34. const props = defineProps({
  35. group: {
  36. type: Object,
  37. required: true
  38. }
  39. })
  40. const emit = defineEmits(['shop-check', 'shop-click', 'check-change', 'quantity-change', 'delete', 'goods-click'])
  41. const purchasableItems = computed(() =>
  42. (props.group.items || []).filter((item) => item.purchasable)
  43. )
  44. const hasPurchasable = computed(() => purchasableItems.value.length > 0)
  45. const shopAllChecked = computed(() => {
  46. if (!hasPurchasable.value) return false
  47. return purchasableItems.value.every((item) => item.checked)
  48. })
  49. function onShopCheck() {
  50. if (!hasPurchasable.value) return
  51. emit('shop-check', props.group, !shopAllChecked.value)
  52. }
  53. </script>
  54. <style lang="scss" scoped>
  55. .cart-shop {
  56. margin-bottom: 20rpx;
  57. background: #fff;
  58. border-radius: 12rpx;
  59. overflow: hidden;
  60. padding: 0 20rpx 8rpx;
  61. }
  62. .cart-shop__head {
  63. display: flex;
  64. align-items: center;
  65. padding: 20rpx 0 8rpx;
  66. border-bottom: 1rpx solid #f0f0f0;
  67. }
  68. .cart-shop__check {
  69. margin-right: 8rpx;
  70. }
  71. .cart-shop__check--disabled {
  72. opacity: 0.4;
  73. }
  74. .check-icon {
  75. width: 36rpx;
  76. height: 36rpx;
  77. border: 2rpx solid #ccc;
  78. border-radius: 50%;
  79. display: flex;
  80. align-items: center;
  81. justify-content: center;
  82. background: #fff;
  83. }
  84. .check-icon--on {
  85. background: #2e7d32;
  86. border-color: #2e7d32;
  87. }
  88. .cart-shop__name-wrap {
  89. flex: 1;
  90. display: flex;
  91. align-items: center;
  92. gap: 8rpx;
  93. min-width: 0;
  94. }
  95. .cart-shop__name {
  96. flex: 1;
  97. font-size: 28rpx;
  98. color: #333;
  99. font-weight: 500;
  100. overflow: hidden;
  101. text-overflow: ellipsis;
  102. white-space: nowrap;
  103. }
  104. .cart-shop__tag {
  105. font-size: 22rpx;
  106. color: #e65100;
  107. background: #fff3e0;
  108. padding: 4rpx 10rpx;
  109. border-radius: 6rpx;
  110. flex-shrink: 0;
  111. }
  112. </style>