item.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <!-- @format -->
  2. <script lang="ts" setup>
  3. import { useUserStore } from '@/stores/modules/user'
  4. import { addShopCartApi } from '~/api/model/goods'
  5. const props = defineProps({
  6. item: Object as any,
  7. w: {
  8. type: String,
  9. default: 'w-300px',
  10. },
  11. h: {
  12. type: String,
  13. default: 'h-300px',
  14. },
  15. })
  16. const emit = defineEmits(['update:login'])
  17. const flag = ref(false)
  18. const inquireVisible = ref(false)
  19. const userStore = useUserStore()
  20. const { isLogin } = storeToRefs(userStore)
  21. const { openLoginModal } = useLoginModal()
  22. function onClickDetail(item: any) {
  23. const router = useRouter()
  24. router.push({
  25. path: `/product/${item.id}`,
  26. })
  27. }
  28. async function addShopCart() {
  29. try {
  30. const { status, isFirstLogin } = await openLoginModal()
  31. if (status) {
  32. await addShopCartApi({
  33. mid: props.item.id,
  34. quantity: props.item.moq,
  35. })
  36. ElMessage({
  37. message: 'Add to cart successfully',
  38. type: 'success',
  39. plain: true,
  40. })
  41. if (isFirstLogin)
  42. emit('update:login')
  43. // commonStore.getCartGoodsList()
  44. }
  45. }
  46. catch (error) {
  47. console.log(error)
  48. }
  49. }
  50. async function onClickLogin() {
  51. const { status, isFirstLogin } = await openLoginModal()
  52. if (status) {
  53. inquireVisible.value = true
  54. if (isFirstLogin)
  55. emit('update:login')
  56. }
  57. }
  58. function getFeaturedLabel(item: any) {
  59. if (item.recommend)
  60. return item.recommend.split(',')[0]
  61. return ''
  62. }
  63. // 验证是否过期
  64. function getIsExpire(item: any) {
  65. const currentTime = Date.now()
  66. if (item.recommendPeriodTime) {
  67. // 转化为时间戳
  68. const expireTime = new Date(item.recommendPeriodTime).getTime()
  69. if (expireTime < currentTime)
  70. return true
  71. return false
  72. }
  73. return false
  74. }
  75. function getImgList() {
  76. const list = []
  77. if (props.item.masterImage)
  78. list.push(...props.item.masterImage.split(','))
  79. if (list.length > 2)
  80. return list
  81. else if (list.length > 0 && list.length < 2 && props.item.detailImage)
  82. return list.concat(...props.item.detailImage.split(','))
  83. return list
  84. }
  85. </script>
  86. <template>
  87. <div>
  88. <div
  89. class="pos-relative custom-main cursor-pointer b-rd-10px b-#FAFAFA b-1px b-solid overflow-hidden"
  90. :class="[w, h]"
  91. @click="onClickDetail(item)"
  92. >
  93. <img
  94. class="object-cover h-full w-full"
  95. :src="getImgList()[0]"
  96. alt=""
  97. srcset=""
  98. >
  99. <img
  100. class="object-cover h-full w-full pos-absolute top-0 left-0 right-0 bottom-0 z-10 transition-duration-1000"
  101. :class="flag ? 'opacity-100' : 'opacity-0'"
  102. :src="getImgList()[1]"
  103. alt=""
  104. srcset=""
  105. @mouseover="flag = true"
  106. @mouseleave="flag = false"
  107. >
  108. <div
  109. v-if="getFeaturedLabel(item) && !getIsExpire(item)"
  110. class="py-4px px-10px bg-#CC9879 text-#fff pos-absolute top-10px left-10px b-rd-4px z-12"
  111. >
  112. {{ getFeaturedLabel(item) }}
  113. </div>
  114. <common-favorite
  115. :data="item"
  116. class="custom-like pos-absolute bottom-60px z-12"
  117. svg-size="18px"
  118. w="36px"
  119. />
  120. <el-button
  121. class="custom-add !h-40px !b-rd-6px !bg-transparent pos-absolute left-50% transform-translate-x--50% w-94% z-12"
  122. @click.stop="addShopCart"
  123. >
  124. Add to Cart
  125. </el-button>
  126. </div>
  127. <div class="text-left">
  128. <div class="text-16px hover:underline text-#666 mt-20px mb-10px">
  129. <nuxt-link v-if="item.brandId" :to="`/brand/${item.brandId}`">
  130. {{ item.brandName }}
  131. </nuxt-link>
  132. <div v-else class="h-21px" />
  133. </div>
  134. <div
  135. class="fw-600 text-24px mb-20px text-#363C40 line-clamp-2 cursor-pointer hover:underline custom-title-font"
  136. @click="onClickDetail(item)"
  137. >
  138. {{ item.title }}
  139. </div>
  140. <div class="flex justify-between items-center">
  141. <div class="text-#666666">
  142. MOQ {{ item.moq }} Pcs
  143. </div>
  144. <div v-if="!isLogin" class="flex items-center">
  145. <div class="text-#AB7045 cursor-pointer hover:fw-500" @click="onClickLogin">
  146. Inquire
  147. </div>
  148. <!-- <el-popover
  149. placement="top"
  150. :width="200"
  151. popper-class="text-center"
  152. trigger="hover"
  153. content="Join to unlock pricing"
  154. >
  155. <template #reference>
  156. <div
  157. class="underline text-#B06B3C ml-8px cursor-pointer"
  158. @click="onClickLogin"
  159. >
  160. Price
  161. </div>
  162. </template>
  163. </el-popover> -->
  164. </div>
  165. <div v-else class="text-#B06B3C cursor-pointer" @click="onClickLogin">
  166. <!-- $ {{ numberToTwoDecimals(item.sellPrice || 0) }} USD -->
  167. Inquire
  168. </div>
  169. </div>
  170. </div>
  171. <business-account-rfqs-quotation-modal v-if="inquireVisible" v-model:visible="inquireVisible" />
  172. </div>
  173. </template>
  174. <style lang="less" scoped>
  175. .custom-main {
  176. .custom-like {
  177. right: -50px;
  178. opacity: 0;
  179. transition: all 0.3s ease-out;
  180. }
  181. .custom-add {
  182. bottom: -50px;
  183. opacity: 0;
  184. transition: all 0.3s ease-out;
  185. }
  186. &:hover {
  187. .custom-like {
  188. right: 10px;
  189. opacity: 1;
  190. }
  191. .custom-add {
  192. bottom: 10px;
  193. opacity: 1;
  194. }
  195. }
  196. }
  197. </style>