s-goods-column.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. <!-- 页面 -->
  2. <template>
  3. <view class="ss-goods-wrap">
  4. <!-- xs卡片:横向紧凑型,一行放两个,图片左内容右边 -->
  5. <view
  6. v-if="size === 'xs'"
  7. class="xs-goods-card ss-flex ss-col-stretch"
  8. :style="[elStyles]"
  9. @tap="onClick"
  10. >
  11. <view v-if="tagStyle.show" class="tag-icon-box">
  12. <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
  13. </view>
  14. <image class="xs-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFit" />
  15. <view
  16. v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
  17. class="xs-goods-content ss-flex-col ss-row-around"
  18. >
  19. <view
  20. v-if="goodsFields.title?.show || goodsFields.name?.show"
  21. class="xs-goods-title ss-line-1"
  22. :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
  23. >
  24. {{ data.title || data.name }}
  25. </view>
  26. <!-- 活动信息 -->
  27. <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
  28. <view class="card" v-if="discountText">{{ discountText }}</view>
  29. <view
  30. class="card2"
  31. v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
  32. :key="item"
  33. >
  34. {{ item }}
  35. </view>
  36. </view>
  37. <view
  38. v-if="goodsFields.price?.show"
  39. class="xs-goods-price font-OPPOSANS"
  40. :style="[{ color: goodsFields.price.color }]"
  41. >
  42. <!-- 活动价格 -->
  43. <text v-if="data.activityType && data.activityType === PromotionActivityTypeEnum.POINT.type">
  44. {{ data.point }}积分
  45. {{ !data.pointPrice || data.pointPrice === 0 ? '' : `+${fen2yuan(data.pointPrice)}元` }}
  46. </text>
  47. <template v-else>
  48. <text class="price-unit ss-font-24">{{ priceUnit }}</text>
  49. <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
  50. <text v-else>
  51. {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
  52. </text>
  53. </template>
  54. </view>
  55. </view>
  56. </view>
  57. <!-- sm卡片:竖向紧凑,一行放三个,图上内容下 -->
  58. <view v-if="size === 'sm'" class="sm-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
  59. <view v-if="tagStyle.show" class="tag-icon-box">
  60. <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
  61. </view>
  62. <image
  63. class="sm-img-box"
  64. :src="sheep.$url.cdn(data.image || data.picUrl)"
  65. mode="aspectFill"
  66. ></image>
  67. <view
  68. v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
  69. class="sm-goods-content"
  70. :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
  71. >
  72. <view
  73. v-if="goodsFields.title?.show || goodsFields.name?.show"
  74. class="sm-goods-title ss-line-1 ss-m-b-16"
  75. >
  76. {{ data.title || data.name }}
  77. </view>
  78. <!-- 活动信息 -->
  79. <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
  80. <view class="card" v-if="discountText">{{ discountText }}</view>
  81. <view
  82. class="card2"
  83. v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
  84. :key="item"
  85. >
  86. {{ item }}
  87. </view>
  88. </view>
  89. <view
  90. v-if="goodsFields.price?.show"
  91. class="sm-goods-price font-OPPOSANS"
  92. :style="[{ color: goodsFields.price.color }]"
  93. >
  94. <!-- 活动价格 -->
  95. <text v-if="data.activityType && data.activityType === PromotionActivityTypeEnum.POINT.type">
  96. {{ data.point }}积分
  97. {{ !data.pointPrice || data.pointPrice === 0 ? '' : `+${fen2yuan(data.pointPrice)}元` }}
  98. </text>
  99. <template v-else>
  100. <text class="price-unit ss-font-24">{{ priceUnit }}</text>
  101. <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
  102. <text v-else>
  103. {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
  104. </text>
  105. </template>
  106. </view>
  107. </view>
  108. </view>
  109. <!-- md卡片:竖向,一行放两个,图上内容下 -->
  110. <view v-if="size === 'md'" class="md-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
  111. <view v-if="tagStyle.show" class="tag-icon-box">
  112. <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)" />
  113. </view>
  114. <image class="md-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="widthFix" />
  115. <view
  116. class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16"
  117. :id="elId"
  118. >
  119. <view
  120. v-if="goodsFields.title?.show || goodsFields.name?.show"
  121. class="md-goods-title ss-line-1"
  122. :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
  123. >
  124. {{ data.title || data.name }}
  125. </view>
  126. <view
  127. v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
  128. class="md-goods-subtitle ss-m-t-16 ss-line-1"
  129. :style="[{ color: subTitleColor, background: subTitleBackground }]"
  130. >
  131. {{ data.subtitle || data.introduction }}
  132. </view>
  133. <slot name="activity">
  134. <view v-if="data.promos?.length" class="tag-box ss-flex-wrap ss-flex ss-col-center">
  135. <view
  136. class="activity-tag ss-m-r-10 ss-m-t-16"
  137. v-for="item in data.promos"
  138. :key="item.id"
  139. >
  140. {{ item.title }}
  141. </view>
  142. </view>
  143. </slot>
  144. <!-- 活动信息 -->
  145. <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
  146. <view class="card" v-if="discountText">{{ discountText }}</view>
  147. <view
  148. class="card2"
  149. v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
  150. :key="item"
  151. >
  152. {{ item }}
  153. </view>
  154. </view>
  155. <view class="ss-flex ss-col-bottom">
  156. <view
  157. v-if="goodsFields.price?.show"
  158. class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
  159. :style="[{ color: goodsFields.price.color }]"
  160. >
  161. <!-- 活动价格 -->
  162. <text v-if="data.activityType && data.activityType === PromotionActivityTypeEnum.POINT.type">
  163. {{ data.point }}积分
  164. {{ !data.pointPrice || data.pointPrice === 0 ? '' : `+${fen2yuan(data.pointPrice)}元` }}
  165. </text>
  166. <template v-else>
  167. <text class="price-unit ss-font-24">{{ priceUnit }}</text>
  168. <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
  169. <text v-else>
  170. {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
  171. </text>
  172. </template>
  173. </view>
  174. <view
  175. v-if="
  176. (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
  177. (data.original_price > 0 || data.marketPrice > 0)
  178. "
  179. class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
  180. :style="[{ color: originPriceColor }]"
  181. >
  182. <text class="price-unit ss-font-20">{{ priceUnit }}</text>
  183. <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
  184. </view>
  185. </view>
  186. <view class="ss-m-t-16 ss-flex ss-col-center ss-flex-wrap">
  187. <view class="sales-text">{{ salesAndStock }}</view>
  188. </view>
  189. </view>
  190. <slot name="cart">
  191. <view class="cart-box ss-flex ss-col-center ss-row-center">
  192. <image class="cart-icon" src="/static/img/shop/tabbar/category2.png" mode="" />
  193. </view>
  194. </slot>
  195. </view>
  196. <!-- lg卡片:横向型,一行放一个,图片左内容右边 -->
  197. <view
  198. v-if="size === 'lg'"
  199. class="lg-goods-card ss-flex ss-col-stretch"
  200. :style="[elStyles]"
  201. @tap="onClick"
  202. >
  203. <view v-if="tagStyle.show" class="tag-icon-box">
  204. <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
  205. </view>
  206. <view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center">秒杀</view>
  207. <view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
  208. <view class="tag-icon">拼团</view>
  209. </view>
  210. <image
  211. class="lg-img-box"
  212. :src="sheep.$url.cdn(data.image || data.picUrl)"
  213. mode="aspectFill"
  214. />
  215. <view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
  216. <view>
  217. <view
  218. v-if="goodsFields.title?.show || goodsFields.name?.show"
  219. class="lg-goods-title ss-line-2"
  220. :style="[{ color: titleColor }]"
  221. >
  222. {{ data.title || data.name }}
  223. </view>
  224. <view
  225. v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
  226. class="lg-goods-subtitle ss-m-t-10 ss-line-1"
  227. :style="[{ color: subTitleColor, background: subTitleBackground }]"
  228. >
  229. {{ data.subtitle || data.introduction }}
  230. </view>
  231. </view>
  232. <view>
  233. <slot name="activity">
  234. <view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center">
  235. <view class="activity-tag ss-m-r-10" v-for="item in data.promos" :key="item.id">
  236. {{ item.title }}
  237. </view>
  238. </view>
  239. </slot>
  240. <!-- 活动信息 -->
  241. <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
  242. <view class="card" v-if="discountText">{{ discountText }}</view>
  243. <view
  244. class="card2"
  245. v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
  246. :key="item"
  247. >
  248. {{ item }}
  249. </view>
  250. </view>
  251. <view class="ss-flex ss-col-bottom ss-m-t-10">
  252. <view
  253. v-if="goodsFields.price?.show"
  254. class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
  255. :style="[{ color: goodsFields.price.color }]"
  256. >
  257. <text class="ss-font-24">{{ priceUnit }}</text>
  258. {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
  259. </view>
  260. <view
  261. v-if="
  262. (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
  263. (data.original_price > 0 || data.marketPrice > 0)
  264. "
  265. class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS"
  266. :style="[{ color: originPriceColor }]"
  267. >
  268. <!-- 活动价格 -->
  269. <text v-if="data.activityType && data.activityType === PromotionActivityTypeEnum.POINT.type">
  270. {{ data.point }}积分
  271. {{ !data.pointPrice || data.pointPrice === 0 ? '' : `+${fen2yuan(data.pointPrice)}元` }}
  272. </text>
  273. <template v-else>
  274. <text class="price-unit ss-font-20">{{ priceUnit }}</text>
  275. <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
  276. <text v-else>
  277. {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
  278. </text>
  279. </template>
  280. </view>
  281. </view>
  282. <view class="ss-m-t-8 ss-flex ss-col-center ss-flex-wrap">
  283. <view class="sales-text">{{ salesAndStock }}</view>
  284. </view>
  285. </view>
  286. </view>
  287. <slot name="cart">
  288. <view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow"> 去购买</view>
  289. </slot>
  290. </view>
  291. <!-- sl卡片:竖向型,一行放一个,图片上内容下边 -->
  292. <view v-if="size === 'sl'" class="sl-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
  293. <view v-if="tagStyle.show" class="tag-icon-box">
  294. <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)" />
  295. </view>
  296. <image
  297. class="sl-img-box"
  298. :src="sheep.$url.cdn(data.image || data.picUrl)"
  299. mode="aspectFill"
  300. />
  301. <view class="sl-goods-content">
  302. <view>
  303. <view
  304. v-if="goodsFields.title?.show || goodsFields.name?.show"
  305. class="sl-goods-title ss-line-1"
  306. :style="[{ color: titleColor }]"
  307. >
  308. {{ data.title || data.name }}
  309. </view>
  310. <view
  311. v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
  312. class="sl-goods-subtitle ss-m-t-16"
  313. :style="[{ color: subTitleColor, background: subTitleBackground }]"
  314. >
  315. {{ data.subtitle || data.introduction }}
  316. </view>
  317. </view>
  318. <view>
  319. <slot name="activity">
  320. <view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center ss-flex-wrap">
  321. <view
  322. class="activity-tag ss-m-r-10 ss-m-t-16"
  323. v-for="item in data.promos"
  324. :key="item.id"
  325. >
  326. {{ item.title }}
  327. </view>
  328. </view>
  329. </slot>
  330. <!-- 活动信息 -->
  331. <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
  332. <view class="card" v-if="discountText">{{ discountText }}</view>
  333. <view
  334. class="card2"
  335. v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
  336. :key="item"
  337. >
  338. {{ item }}
  339. </view>
  340. </view>
  341. <view v-if="goodsFields.price?.show" class="ss-flex ss-col-bottom font-OPPOSANS">
  342. <view class="sl-goods-price ss-m-r-12" :style="[{ color: goodsFields.price.color }]">
  343. <!-- 活动价格 -->
  344. <text v-if="data.activityType && data.activityType === PromotionActivityTypeEnum.POINT.type">
  345. {{ data.point }}积分
  346. {{ !data.pointPrice || data.pointPrice === 0 ? '' : `+${fen2yuan(data.pointPrice)}元` }}
  347. </text>
  348. <template v-else>
  349. <text class="price-unit ss-font-24">{{ priceUnit }}</text>
  350. <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
  351. <text v-else>
  352. {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
  353. </text>
  354. </template>
  355. </view>
  356. <view
  357. v-if="
  358. (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
  359. (data.original_price > 0 || data.marketPrice > 0)
  360. "
  361. class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
  362. :style="[{ color: originPriceColor }]"
  363. >
  364. <text class="price-unit ss-font-20">{{ priceUnit }}</text>
  365. <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
  366. </view>
  367. </view>
  368. <view class="ss-m-t-16 ss-flex ss-flex-wrap">
  369. <view class="sales-text">{{ salesAndStock }}</view>
  370. </view>
  371. </view>
  372. </view>
  373. <slot name="cart">
  374. <view class="buy-box ss-flex ss-col-center ss-row-center">去购买</view>
  375. </slot>
  376. </view>
  377. </view>
  378. </template>
  379. <script setup>
  380. /**
  381. * 商品卡片
  382. *
  383. * @property {Array} size = [xs | sm | md | lg | sl ] - 列表数据
  384. * @property {String} tag - md及以上才有
  385. * @property {String} img - 图片
  386. * @property {String} background - 背景色
  387. * @property {String} topRadius - 上圆角
  388. * @property {String} bottomRadius - 下圆角
  389. * @property {String} title - 标题
  390. * @property {String} titleColor - 标题颜色
  391. * @property {Number} titleWidth = 0 - 标题宽度,默认0,单位rpx
  392. * @property {String} subTitle - 副标题
  393. * @property {String} subTitleColor - 副标题颜色
  394. * @property {String} subTitleBackground - 副标题背景
  395. * @property {String | Number} price - 价格
  396. * @property {String} priceColor - 价格颜色
  397. * @property {String | Number} originPrice - 原价/划线价
  398. * @property {String} originPriceColor - 原价颜色
  399. * @property {String | Number} sales - 销售数量
  400. * @property {String} salesColor - 销售数量颜色
  401. *
  402. * @slots activity - 活动插槽
  403. * @slots cart - 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
  404. *
  405. * @event {Function()} click - 点击卡片
  406. *
  407. */
  408. import { computed, getCurrentInstance, nextTick, onMounted } from 'vue';
  409. import sheep from '@/sheep';
  410. import {
  411. fen2yuan,
  412. formatExchange,
  413. formatSales,
  414. formatStock,
  415. getRewardActivityRuleItemDescriptions,
  416. } from '@/sheep/hooks/useGoods';
  417. import { isArray } from 'lodash-es';
  418. import { PromotionActivityTypeEnum } from '@/sheep/util/const';
  419. // 接收参数
  420. const props = defineProps({
  421. goodsFields: {
  422. type: [Array, Object],
  423. default() {
  424. return {
  425. // 商品价格
  426. price: {
  427. show: true,
  428. },
  429. // 库存
  430. stock: {
  431. show: true,
  432. },
  433. // 商品名称
  434. name: {
  435. show: true,
  436. },
  437. // 商品介绍
  438. introduction: {
  439. show: true,
  440. },
  441. // 市场价
  442. marketPrice: {
  443. show: true,
  444. },
  445. // 销量
  446. salesCount: {
  447. show: true,
  448. },
  449. };
  450. },
  451. },
  452. tagStyle: {
  453. type: Object,
  454. default: () => ({}),
  455. },
  456. data: {
  457. type: Object,
  458. default: () => ({}),
  459. },
  460. size: {
  461. type: String,
  462. default: 'sl',
  463. },
  464. background: {
  465. type: String,
  466. default: '',
  467. },
  468. topRadius: {
  469. type: Number,
  470. default: 0,
  471. },
  472. bottomRadius: {
  473. type: Number,
  474. default: 0,
  475. },
  476. titleWidth: {
  477. type: Number,
  478. default: 0,
  479. },
  480. titleColor: {
  481. type: String,
  482. default: '#333',
  483. },
  484. priceColor: {
  485. type: String,
  486. default: '',
  487. },
  488. originPriceColor: {
  489. type: String,
  490. default: '#C4C4C4',
  491. },
  492. priceUnit: {
  493. type: String,
  494. default: '¥',
  495. },
  496. subTitleColor: {
  497. type: String,
  498. default: '#999999',
  499. },
  500. subTitleBackground: {
  501. type: String,
  502. default: '',
  503. },
  504. buttonShow: {
  505. type: Boolean,
  506. default: true,
  507. },
  508. seckillTag: {
  509. type: Boolean,
  510. default: false,
  511. },
  512. grouponTag: {
  513. type: Boolean,
  514. default: false,
  515. },
  516. });
  517. // 优惠文案
  518. const discountText = computed(() => {
  519. const promotionType = props.data.promotionType;
  520. if (promotionType === 4) {
  521. return '限时优惠';
  522. } else if (promotionType === 6) {
  523. return '会员价';
  524. }
  525. return undefined;
  526. });
  527. // 组件样式
  528. const elStyles = computed(() => {
  529. return {
  530. background: props.background,
  531. 'border-top-left-radius': props.topRadius + 'px',
  532. 'border-top-right-radius': props.topRadius + 'px',
  533. 'border-bottom-left-radius': props.bottomRadius + 'px',
  534. 'border-bottom-right-radius': props.bottomRadius + 'px',
  535. };
  536. });
  537. // 格式化销量、库存信息
  538. const salesAndStock = computed(() => {
  539. let text = [];
  540. if (props.goodsFields.salesCount?.show) {
  541. if (props.data.activityType && props.data.activityType === PromotionActivityTypeEnum.POINT.type) {
  542. text.push(formatExchange(props.data.sales_show_type, (props.data.pointTotalStock || 0) - (props.data.pointStock || 0)));
  543. }else {
  544. text.push(formatSales(props.data.sales_show_type, props.data.salesCount));
  545. }
  546. }
  547. if (props.goodsFields.stock?.show) {
  548. if (props.data.activityType && props.data.activityType === PromotionActivityTypeEnum.POINT.type) {
  549. text.push(formatStock(props.data.stock_show_type, props.data.pointTotalStock));
  550. }else {
  551. text.push(formatStock(props.data.stock_show_type, props.data.stock));
  552. }
  553. }
  554. return text.join(' | ');
  555. });
  556. // 返回事件
  557. const emits = defineEmits(['click', 'getHeight']);
  558. const onClick = () => {
  559. emits('click');
  560. };
  561. // 获取卡片实时高度
  562. const { proxy } = getCurrentInstance();
  563. const elId = `sheep_${Math.ceil(Math.random() * 10e5).toString(36)}`;
  564. function getGoodsPriceCardWH() {
  565. if (props.size === 'md') {
  566. const view = uni.createSelectorQuery().in(proxy);
  567. view.select(`#${elId}`).fields({
  568. size: true,
  569. scrollOffset: true,
  570. });
  571. view.exec((data) => {
  572. let totalHeight = 0;
  573. const goodsPriceCard = data[0];
  574. if (props.data.image_wh) {
  575. totalHeight =
  576. (goodsPriceCard.width / props.data.image_wh.w) * props.data.image_wh.h +
  577. goodsPriceCard.height;
  578. } else {
  579. totalHeight = goodsPriceCard.width;
  580. }
  581. emits('getHeight', totalHeight);
  582. });
  583. }
  584. }
  585. onMounted(() => {
  586. nextTick(() => {
  587. getGoodsPriceCardWH();
  588. });
  589. });
  590. </script>
  591. <style lang="scss" scoped>
  592. .tag-icon-box {
  593. position: absolute;
  594. left: 0;
  595. top: 0;
  596. z-index: 2;
  597. .tag-icon {
  598. width: 72rpx;
  599. height: 44rpx;
  600. }
  601. }
  602. .seckill-tag {
  603. position: absolute;
  604. left: 0;
  605. top: 0;
  606. z-index: 2;
  607. width: 68rpx;
  608. height: 38rpx;
  609. background: linear-gradient(90deg, #ff5854 0%, #ff2621 100%);
  610. border-radius: 10rpx 0px 10rpx 0px;
  611. font-size: 24rpx;
  612. font-weight: 500;
  613. color: #ffffff;
  614. line-height: 32rpx;
  615. }
  616. .groupon-tag {
  617. position: absolute;
  618. left: 0;
  619. top: 0;
  620. z-index: 2;
  621. width: 68rpx;
  622. height: 38rpx;
  623. background: linear-gradient(90deg, #fe832a 0%, #ff6600 100%);
  624. border-radius: 10rpx 0px 10rpx 0px;
  625. font-size: 24rpx;
  626. font-weight: 500;
  627. color: #ffffff;
  628. line-height: 32rpx;
  629. }
  630. .goods-img {
  631. width: 100%;
  632. height: 100%;
  633. background-color: #f5f5f5;
  634. }
  635. .price-unit {
  636. margin-right: -4px;
  637. }
  638. .sales-text {
  639. display: table;
  640. font-size: 24rpx;
  641. transform: scale(0.8);
  642. margin-left: 0rpx;
  643. color: #c4c4c4;
  644. }
  645. .activity-tag {
  646. font-size: 20rpx;
  647. color: #ff0000;
  648. line-height: 30rpx;
  649. padding: 0 10rpx;
  650. border: 1px solid rgba(#ff0000, 0.25);
  651. border-radius: 4px;
  652. flex-shrink: 0;
  653. }
  654. .goods-origin-price {
  655. font-size: 20rpx;
  656. color: #c4c4c4;
  657. line-height: 36rpx;
  658. text-decoration: line-through;
  659. }
  660. // xs
  661. .xs-goods-card {
  662. overflow: hidden;
  663. // max-width: 375rpx;
  664. background-color: $white;
  665. position: relative;
  666. .xs-img-box {
  667. width: 128rpx;
  668. height: 128rpx;
  669. margin-right: 20rpx;
  670. }
  671. .xs-goods-title {
  672. font-size: 26rpx;
  673. color: #333;
  674. font-weight: 500;
  675. }
  676. .xs-goods-price {
  677. font-size: 30rpx;
  678. color: $red;
  679. }
  680. }
  681. // sm
  682. .sm-goods-card {
  683. overflow: hidden;
  684. // width: 223rpx;
  685. // width: 100%;
  686. background-color: $white;
  687. position: relative;
  688. .sm-img-box {
  689. // width: 228rpx;
  690. width: 100%;
  691. height: 208rpx;
  692. }
  693. .sm-goods-content {
  694. padding: 20rpx 16rpx;
  695. box-sizing: border-box;
  696. }
  697. .sm-goods-title {
  698. font-size: 26rpx;
  699. color: #333;
  700. }
  701. .sm-goods-price {
  702. font-size: 30rpx;
  703. color: $red;
  704. }
  705. }
  706. // md
  707. .md-goods-card {
  708. overflow: hidden;
  709. width: 100%;
  710. position: relative;
  711. z-index: 1;
  712. background-color: $white;
  713. position: relative;
  714. .md-img-box {
  715. width: 100%;
  716. }
  717. .md-goods-title {
  718. font-size: 26rpx;
  719. color: #333;
  720. width: 100%;
  721. }
  722. .md-goods-subtitle {
  723. font-size: 24rpx;
  724. font-weight: 400;
  725. color: #999999;
  726. }
  727. .md-goods-price {
  728. font-size: 30rpx;
  729. color: $red;
  730. line-height: 36rpx;
  731. }
  732. .cart-box {
  733. width: 54rpx;
  734. height: 54rpx;
  735. background: linear-gradient(90deg, #fe8900, #ff5e00);
  736. border-radius: 50%;
  737. position: absolute;
  738. bottom: 50rpx;
  739. right: 20rpx;
  740. z-index: 2;
  741. .cart-icon {
  742. width: 30rpx;
  743. height: 30rpx;
  744. }
  745. }
  746. }
  747. // lg
  748. .lg-goods-card {
  749. overflow: hidden;
  750. position: relative;
  751. z-index: 1;
  752. background-color: $white;
  753. height: 280rpx;
  754. .lg-img-box {
  755. width: 280rpx;
  756. height: 280rpx;
  757. margin-right: 20rpx;
  758. }
  759. .lg-goods-title {
  760. font-size: 28rpx;
  761. font-weight: 500;
  762. color: #333333;
  763. // line-height: 36rpx;
  764. // width: 410rpx;
  765. }
  766. .lg-goods-subtitle {
  767. font-size: 24rpx;
  768. font-weight: 400;
  769. color: #999999;
  770. // line-height: 30rpx;
  771. // width: 410rpx;
  772. }
  773. .lg-goods-price {
  774. font-size: 30rpx;
  775. color: $red;
  776. line-height: 36rpx;
  777. }
  778. .buy-box {
  779. position: absolute;
  780. bottom: 20rpx;
  781. right: 20rpx;
  782. z-index: 2;
  783. width: 120rpx;
  784. height: 50rpx;
  785. background: linear-gradient(90deg, #fe8900, #ff5e00);
  786. border-radius: 25rpx;
  787. font-size: 24rpx;
  788. color: #ffffff;
  789. }
  790. .tag-box {
  791. width: 100%;
  792. }
  793. }
  794. // sl
  795. .sl-goods-card {
  796. overflow: hidden;
  797. position: relative;
  798. z-index: 1;
  799. width: 100%;
  800. background-color: $white;
  801. .sl-goods-content {
  802. padding: 20rpx 20rpx;
  803. box-sizing: border-box;
  804. }
  805. .sl-img-box {
  806. width: 100%;
  807. height: 360rpx;
  808. }
  809. .sl-goods-title {
  810. font-size: 26rpx;
  811. color: #333;
  812. font-weight: 500;
  813. }
  814. .sl-goods-subtitle {
  815. font-size: 24rpx;
  816. font-weight: 400;
  817. color: #999999;
  818. line-height: 30rpx;
  819. }
  820. .sl-goods-price {
  821. font-size: 30rpx;
  822. color: $red;
  823. line-height: 36rpx;
  824. }
  825. .buy-box {
  826. position: absolute;
  827. bottom: 20rpx;
  828. right: 20rpx;
  829. z-index: 2;
  830. width: 148rpx;
  831. height: 50rpx;
  832. background: linear-gradient(90deg, #fe8900, #ff5e00);
  833. border-radius: 25rpx;
  834. font-size: 24rpx;
  835. color: #ffffff;
  836. }
  837. }
  838. .card {
  839. width: fit-content;
  840. height: fit-content;
  841. padding: 2rpx 10rpx;
  842. background-color: red;
  843. color: #ffffff;
  844. font-size: 24rpx;
  845. margin-top: 5rpx;
  846. }
  847. .card2 {
  848. width: fit-content;
  849. height: fit-content;
  850. padding: 2rpx 10rpx;
  851. background-color: rgb(255, 242, 241);
  852. color: #ff2621;
  853. font-size: 24rpx;
  854. margin: 5rpx 0 5rpx 5rpx;
  855. }
  856. .iconBox {
  857. width: 100%;
  858. height: fit-content;
  859. margin-top: 10rpx;
  860. display: flex;
  861. justify-content: flex-start;
  862. flex-wrap: wrap;
  863. }
  864. </style>