goods-list.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <template>
  2. <view>
  3. <view v-if="(data || null) != null && (data.goods_list || null) != null && data.goods_list.length > 0">
  4. <view v-if="(data.title || null) != null || (data.vice_title || null) != null" class="spacing-nav-title">
  5. <text v-if="(data.title || null) != null" class="text-wrapper" :style="'color:'+(data.color || '#333')+';'">{{data.title}}</text>
  6. <text v-if="(data.vice_title || null) != null" class="vice-name margin-left-lg cr-gray">{{data.vice_title}}</text>
  7. <navigator v-if="(data[propMoreUrlKey] || null) != null" :url="data[propMoreUrlKey]" hover-class="none" class="arrow-right padding-right-xxxl cr-gray fr">更多</navigator>
  8. </view>
  9. <view class="wh-auto oh pr goods-list">
  10. <view v-if="(data.keywords_arr || null) != null && data.keywords_arr.length > 0" class="word-list scroll-view-horizontal margin-bottom-lg">
  11. <scroll-view scroll-x>
  12. <block v-for="(kv, ki) in data.keywords_arr" :key="ki">
  13. <navigator v-if="(kv || null) != null" :url="propKeywordsUrl + kv" hover-class="none" class="word-icon dis-inline-block bg-main-light text-size-xs cr-main round padding-top-xs padding-bottom-xs padding-left padding-right">{{kv}}</navigator>
  14. </block>
  15. </scroll-view>
  16. </view>
  17. <!-- 默认图文 -->
  18. <block v-if="(data.style_type || 0) == 0">
  19. <view class="goods-data-list">
  20. <view v-for="(item, index) in data.goods_list" :key="index" class="item oh padding-main border-radius-main bg-white oh pr spacing-mb">
  21. <!-- 商品主体内容 -->
  22. <view class="cp" :data-value="item.goods_url" @tap="url_event">
  23. <image class="goods-img fl radius" :src="item.images" mode="aspectFit"></image>
  24. <view v-if="(item.is_error || 0) == 1" class="error-msg pa cr-gray tc radius">{{item.error_msg}}</view>
  25. <view class="base fr">
  26. <view class="multi-text">{{item.title}}</view>
  27. <view v-if="(item.simple_desc || null) != null" class="cr-grey single-text margin-top-sm">{{item.simple_desc}}</view>
  28. <view class="base-bottom pa">
  29. <text v-if="propIsShowPriceIcon && (item.price_icon || null) != null" class="bg-red br-red cr-white text-size-xs padding-left-sm padding-right-sm round va-m margin-right-xs">{{item.price_icon}}</text>
  30. <text class="sales-price va-m">{{propCurrencySymbol}}{{item[propPriceField]}}</text>
  31. </view>
  32. <view v-if="(item.is_error || 0) == 0" class="pa bg-white right-cart-icon" :data-index="index" @tap.stop="goods_cart_event">
  33. <uni-icons type="plus" size="22" color="#1AAD19"></uni-icons>
  34. <view class="cart-badge-icon pa">
  35. <component-badge :propNumber="item.user_cart_count || 0"></component-badge>
  36. </view>
  37. </view>
  38. </view>
  39. </view>
  40. <!-- 标签插件 -->
  41. <view v-if="(propLabel || null) != null && propLabel.data.length > 0" :class="'plugins-label oh pa plugins-label-'+((propLabel.base.is_user_goods_label_icon || 0) == 0 ? 'text' : 'img')+' plugins-label-'+(propLabel.base.user_goods_show_style || 'top-left')">
  42. <block v-for="(lv,li) in propLabel.data" :key="li">
  43. <view v-if="(lv.goods_ids || null) != null && lv.goods_ids.indexOf(item.id) != -1" class="lv dis-inline-block va-m" :data-value="((propLabel.base.is_user_goods_label_url || 0) == 1) ? (lv.url || '') : ''" @tap="url_event">
  44. <view v-if="(propLabel.base.is_user_goods_label_icon || 0) == 0" class="round cr-white bg-main text-size-xs fl" :style="((lv.bg_color || null) != null ? 'background-color:'+ lv.bg_color+' !important;' : '')+((lv.text_color || null) != null ? 'color:'+ lv.text_color+' !important;' : '')">{{lv.name}}</view>
  45. <image v-else class="dis-block" :src="lv.icon" mode="scaleToFill"></image>
  46. </view>
  47. </block>
  48. </view>
  49. </view>
  50. </view>
  51. </block>
  52. <!-- 九方格 -->
  53. <block v-else-if="data.style_type == 1">
  54. <view class="goods-data-grid-list">
  55. <view v-for="(item, index) in data.goods_list" :key="index" class="item oh border-radius-main bg-white oh pr spacing-mb">
  56. <!-- 商品主体内容 -->
  57. <view class="cp" :data-value="item.goods_url" @tap="url_event">
  58. <image class="goods-img dis-block wh-auto" :src="item.images" mode="aspectFit"></image>
  59. <view v-if="(item.is_error || 0) == 1" class="error-msg pa cr-gray tc radius wh-auto">{{item.error_msg}}</view>
  60. <view class="base padding-horizontal-main margin-top-sm">
  61. <view class="goods-title multi-text">{{item.title}}</view>
  62. <view class="margin-top-sm">
  63. <view class="fl">
  64. <text v-if="propIsShowPriceIcon && (item.price_icon || null) != null" class="bg-red br-red cr-white text-size-xs padding-left-sm padding-right-sm round va-m margin-right-xs">{{item.price_icon}}</text>
  65. <text class="sales-price va-m">{{propCurrencySymbol}}{{item[propPriceField]}}</text>
  66. </view>
  67. <view v-if="(item.is_error || 0) == 0" class="pa bg-white right-cart-icon" :data-index="index" @tap.stop="goods_cart_event">
  68. <uni-icons type="plus" size="22" color="#1AAD19"></uni-icons>
  69. <view class="cart-badge-icon pa">
  70. <component-badge :propNumber="item.user_cart_count || 0"></component-badge>
  71. </view>
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. <!-- 标签插件 -->
  77. <view v-if="(propLabel || null) != null && propLabel.data.length > 0" :class="'plugins-label oh pa plugins-label-'+((propLabel.base.is_user_goods_label_icon || 0) == 0 ? 'text' : 'img')+' plugins-label-'+(propLabel.base.user_goods_show_style || 'top-left')">
  78. <block v-for="(lv,li) in propLabel.data" :key="li">
  79. <view v-if="(lv.goods_ids || null) != null && lv.goods_ids.indexOf(item.id) != -1" class="lv dis-inline-block va-m" :data-value="((propLabel.base.is_user_goods_label_url || 0) == 1) ? (lv.url || '') : ''" @tap="url_event">
  80. <view v-if="(propLabel.base.is_user_goods_label_icon || 0) == 0" class="round cr-white bg-main text-size-xs fl" :style="((lv.bg_color || null) != null ? 'background-color:'+ lv.bg_color+' !important;' : '')+((lv.text_color || null) != null ? 'color:'+ lv.text_color+' !important;' : '')">{{lv.name}}</view>
  81. <image v-else class="dis-block" :src="lv.icon" mode="scaleToFill"></image>
  82. </view>
  83. </block>
  84. </view>
  85. </view>
  86. </view>
  87. </block>
  88. <!-- 滚动 -->
  89. <view v-else-if="data.style_type == 2" class="rolling-horizontal border-radius-main oh spacing-mb">
  90. <view class="goods-data-rolling-list scroll-view-horizontal">
  91. <swiper :vertical="false" :autoplay="propIsAutoPlay" :circular="false" :display-multiple-items="((data.multiple_items || null) == null) ? (data.goods_list.length < 3 ? data.goods_list.length : 3) : (data.goods_list.length < data.multiple_items ? data.goods_list.length : data.multiple_items)" interval="3000">
  92. <block v-for="(item, index) in data.goods_list" :key="index">
  93. <swiper-item>
  94. <view class="item bg-white border-radius-main margin-right-main oh pr ht-auto pr">
  95. <!-- 商品主体内容 -->
  96. <view class="cp" :data-value="item.goods_url" @tap="url_event">
  97. <image class="goods-img dis-block wh-auto" :src="item.images" mode="aspectFit"></image>
  98. <view v-if="(item.is_error || 0) == 1" class="error-msg pa cr-gray tc radius wh-auto">{{item.error_msg}}</view>
  99. <view class="padding-left-sm padding-right-sm margin-top-sm">
  100. <view class="multi-text">{{item.title}}</view>
  101. <view class="margin-top-sm">
  102. <view class="fl">
  103. <text v-if="propIsShowPriceIcon && (item.price_icon || null) != null" class="bg-red br-red cr-white text-size-xs padding-left-sm padding-right-sm round va-m margin-right-xs">{{item.price_icon}}</text>
  104. <text class="sales-price va-m">{{propCurrencySymbol}}{{item[propPriceField]}}</text>
  105. </view>
  106. <view v-if="(item.is_error || 0) == 0" class="pa bg-white right-cart-icon" :data-index="index" @tap.stop="goods_cart_event">
  107. <uni-icons type="plus" size="22" color="#1AAD19"></uni-icons>
  108. <view class="cart-badge-icon pa">
  109. <component-badge :propNumber="item.user_cart_count || 0"></component-badge>
  110. </view>
  111. </view>
  112. </view>
  113. </view>
  114. </view>
  115. <!-- 标签插件 -->
  116. <view v-if="(propLabel || null) != null && propLabel.data.length > 0" :class="'plugins-label oh pa plugins-label-'+((propLabel.base.is_user_goods_label_icon || 0) == 0 ? 'text' : 'img')+' plugins-label-'+(propLabel.base.user_goods_show_style || 'top-left')">
  117. <block v-for="(lv,li) in propLabel.data" :key="li">
  118. <view v-if="(lv.goods_ids || null) != null && lv.goods_ids.indexOf(item.id) != -1" class="lv dis-inline-block va-m" :data-value="((propLabel.base.is_user_goods_label_url || 0) == 1) ? (lv.url || '') : ''" @tap="url_event">
  119. <view v-if="(propLabel.base.is_user_goods_label_icon || 0) == 0" class="round cr-white bg-main text-size-xs fl" :style="((lv.bg_color || null) != null ? 'background-color:'+ lv.bg_color+' !important;' : '')+((lv.text_color || null) != null ? 'color:'+ lv.text_color+' !important;' : '')">{{lv.name}}</view>
  120. <image v-else class="dis-block" :src="lv.icon" mode="scaleToFill"></image>
  121. </view>
  122. </block>
  123. </view>
  124. </view>
  125. </swiper-item>
  126. </block>
  127. </swiper>
  128. </view>
  129. </view>
  130. </view>
  131. </view>
  132. <!-- 商品购买 -->
  133. <component-goods-buy ref="goods_buy" v-on:CartSuccessEvent="goods_cart_back_event"></component-goods-buy>
  134. <!-- 购物车抛物线 -->
  135. <component-cart-para-curve ref="cart_para_curve"></component-cart-para-curve>
  136. </view>
  137. </template>
  138. <script>
  139. const app = getApp();
  140. import componentBadge from "../../components/badge/badge";
  141. import componentGoodsBuy from "../../components/goods-buy/goods-buy";
  142. import componentCartParaCurve from '../../components/cart-para-curve/cart-para-curve';
  143. export default {
  144. data() {
  145. return {
  146. data: null,
  147. };
  148. },
  149. components: {
  150. componentBadge,
  151. componentGoodsBuy,
  152. componentCartParaCurve
  153. },
  154. props: {
  155. // 价格符号
  156. propCurrencySymbol: {
  157. type: String,
  158. default: app.globalData.data.currency_symbol
  159. },
  160. // 列表数据
  161. propData: {
  162. type: [Array,Object],
  163. default: []
  164. },
  165. // 更多url地址
  166. propMoreUrlKey: {
  167. type: String,
  168. default: 'url'
  169. },
  170. // 关键字url地址
  171. propKeywordsUrl: {
  172. type: String,
  173. default: '/pages/goods-search/goods-search?keywords='
  174. },
  175. // 滚动自动播放
  176. propIsAutoPlay: {
  177. type: Boolean,
  178. default: true
  179. },
  180. // 标签数据
  181. propLabel: {
  182. type: [Array,Object,String],
  183. default: null
  184. },
  185. // 展示加购抛物线
  186. propIsCartParaCurve: {
  187. type: Boolean,
  188. default: false
  189. },
  190. // 展示价格icon图标
  191. propIsShowPriceIcon: {
  192. type: Boolean,
  193. default: false
  194. },
  195. // 展示价格字段
  196. propPriceField: {
  197. type: String,
  198. default: 'min_price'
  199. }
  200. },
  201. // 属性值改变监听
  202. watch: {
  203. // 数据
  204. propData(value, old_value) {
  205. this.data = value;
  206. }
  207. },
  208. // 页面被展示
  209. created: function() {
  210. this.data = this.propData;
  211. },
  212. methods: {
  213. // 加入购物车
  214. goods_cart_event(e) {
  215. if((this.$refs.goods_buy || null) != null) {
  216. var index = e.currentTarget.dataset.index || 0;
  217. var goods = this.propData.goods_list[index];
  218. // 开启购物车抛物线效果则展示提示操作
  219. var is_success_tips = this.propIsCartParaCurve ? 0 : 1;
  220. this.$refs.goods_buy.init(goods, {buy_event_type: 'cart', is_direct_cart: 1, is_success_tips: is_success_tips}, {index: index, pos: e});
  221. }
  222. },
  223. // 加入购物车成功回调
  224. goods_cart_back_event(e) {
  225. // 增加数量
  226. var back = e.back_data;
  227. var temp = this.data;
  228. var goods = temp['goods_list'][back.index];
  229. goods['user_cart_count'] = parseInt(goods['user_cart_count'] || 0)+parseInt(e.stock);
  230. if(goods['user_cart_count'] > 99) {
  231. goods['user_cart_count'] = '99+';
  232. }
  233. temp['goods_list'][back.index] = goods;
  234. this.setData({data: temp});
  235. // 抛物线
  236. if(this.propIsCartParaCurve && (this.$refs.cart_para_curve || null) != null) {
  237. this.$refs.cart_para_curve.init(null, back.pos, goods.images);
  238. }
  239. // 导航购物车处理
  240. var cart_total = e.cart_number || 0;
  241. if (cart_total <= 0) {
  242. app.globalData.set_tab_bar_badge(2, 0);
  243. } else {
  244. app.globalData.set_tab_bar_badge(2, 1, cart_total);
  245. }
  246. // 当前页面
  247. var page = app.globalData.current_page().split('?');
  248. switch(page[0]) {
  249. // 商品详情页面
  250. case 'pages/goods-detail/goods-detail' :
  251. var res = app.globalData.get_page_object(page[0]);
  252. if(res.length > 0) {
  253. for(var i in res) {
  254. res[i].$vm.goods_cart_count_handle(cart_total);
  255. }
  256. }
  257. break;
  258. }
  259. },
  260. // url事件
  261. url_event(e) {
  262. app.globalData.url_event(e);
  263. }
  264. }
  265. };
  266. </script>
  267. <style>
  268. </style>