app-product-list.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. <template>
  2. <view :class="[!listStyle ? 'list-padding' : '', 'page-width', 'product-list', 'dir-top-nowrap']">
  3. <view class="f-swipe-content" @click="routeGo(item)" v-if="listStyle" v-for="(item, index) in goods_list"
  4. :key="item.id">
  5. <view class="f-item dir-left-nowrap">
  6. <view class="f-out-dialog" v-if="item.goods_stock == 0 && appSetting.is_show_stock == '1'">
  7. <image :src="appSetting.is_use_stock == '1' ? appImg.plugins_out : appSetting.sell_out_pic"></image>
  8. </view>
  9. <image class="f-img" :src="item.cover_pic" :lazy-load="true" mode="aspectFill"></image>
  10. <!-- 此层wrap在此为必写的,否则可能会出现标题定位错误 -->
  11. <view class="f-content dir-top-wrap main-between">
  12. <text class="t-omit-two f-title">{{ item.name }}</text>
  13. <view>
  14. <!-- 会员价 -->
  15. <view class="member-price" v-if="item.is_level == 1 && item.is_negotiable != 1">
  16. <app-member-price :price="item.level_price" :theme="themeObject" :sign="sign">
  17. </app-member-price>
  18. </view>
  19. <!-- 超级会员卡 -->
  20. <view class="app-sup-vip" v-if="item.vip_card_appoint.discount && item.is_negotiable != 1">
  21. <app-sup-vip :discount="item.vip_card_appoint.discount"
  22. :is_vip_card_user="item.vip_card_appoint.is_vip_card_user"></app-sup-vip>
  23. </view>
  24. <view class="dir-left-nowrap main-between">
  25. <view class="dir-top-wrap main-between">
  26. <text class="f-price"
  27. :class="sign === 'gift' ? theme + '-color' : theme + '-m-text ' + theme">{{item.price_content}}</text>
  28. <text class="f-scale"
  29. v-if="item.is_negotiable != 1 && isShowSalesNum == 1">{{item.sales}}</text>
  30. </view>
  31. <view
  32. v-if="sign !== 'gift' && item.is_negotiable != 1 && isShowCart == 1 && item.goods_stock > 0">
  33. <image class="f-cat-icon" @click.stop="specification(item)"
  34. :class="theme +'-m-back ' + theme" src="/static/image/icon/cats.png"></image>
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. </view>
  40. </view>
  41. <view v-if="!listStyle" class="page-width dir-left-wrap main-between">
  42. <view @click="routeGo(item)" class="u-goods box-grow-0 dir-top-nowrap main-between"
  43. v-for="(item, index) in goods_list" :class="'index-'+index" :key="index">
  44. <view class="image-name dir-top-nowrap main-left">
  45. <view class="out-dialog" v-if="item.goods_stock == 0 && appSetting.is_show_stock == '1'">
  46. <image :src="appSetting.is_use_stock == '1' ? appImg.plugins_out : appSetting.sell_out_pic">
  47. </image>
  48. </view>
  49. <image class="image" :src="item.cover_pic" :lazy-load="true" mode="aspectFill"></image>
  50. <view class="name t-omit-two" v-if="is_name && isShowGoodsName == 1">{{item.name}}</view>
  51. </view>
  52. <view class="content dir-top-nowrap main-right"
  53. :style="{height: is_name ? 'calc(100% - #{426rpx})': 'height: calc(100% - #{384rpx});'}">
  54. <!-- 会员价 -->
  55. <view class="member-price"
  56. v-if="(item.is_level == 1 || (sign === 'exchange' && item.level_show != 0)) && item.is_negotiable != 1">
  57. <app-member-price :price="item.level_price" :theme="themeObject" :sign="sign">
  58. </app-member-price>
  59. </view>
  60. <!-- 超级会员卡 -->
  61. <view class="app-sup-vip" v-if="item.vip_card_appoint.discount && item.is_negotiable != 1">
  62. <app-sup-vip :discount="item.vip_card_appoint.discount"
  63. :is_vip_card_user="item.vip_card_appoint.is_vip_card_user"></app-sup-vip>
  64. </view>
  65. <!-- 价格 销量 -->
  66. <view v-if="sign !== 'exchange'"
  67. class="price-total page-width dir-left-nowrap main-between cross-bottom">
  68. <view>
  69. <view class="price"
  70. :class="sign === 'gift' ? theme + '-color' : theme + '-m-text ' + theme">
  71. {{item.price_content}}
  72. </view>
  73. <view class="origin-price" v-if="isListUnderlinePrice == 1">
  74. ¥{{item.original_price}}
  75. </view>
  76. </view>
  77. <template v-if="sign === 'gift'">
  78. <text v-if="item.is_negotiable != 1" class="gray sales">{{item.sales}}</text>
  79. </template>
  80. <template v-else>
  81. <text v-if="item.is_negotiable != 1 && isShowSalesNum == 1"
  82. class="gray sales">{{item.sales}}</text>
  83. <view class="box-grow-1" style="position: relative;"
  84. v-if="item.is_negotiable != 1 && isShowCart == 1 && item.goods_stock > 0">
  85. <!-- #ifdef MP-ALIPAY -->
  86. <div class="cart-box" @click.stop="specification(item)"
  87. style="-webkit-background-origin: content-box;background-origin: content-box;">
  88. <app-cart-image class="goods-cart" :sign="sign" :theme="theme"></app-cart-image>
  89. </div>
  90. <!-- #endif -->
  91. <!-- #ifndef MP-ALIPAY -->
  92. <div class="cart-box" @click.stop="specification(item)">
  93. <app-cart-image class="goods-cart" :sign="sign" :theme="theme"></app-cart-image>
  94. </div>
  95. <!-- #endif -->
  96. </view>
  97. </template>
  98. </view>
  99. <view v-if="sign === 'exchange'" class="price-total exchange page-width">
  100. <template>
  101. <text class="price" :class="theme + '-m-text ' + theme">
  102. {{item.price_content}}
  103. </text>
  104. <view class="dir-left-nowrap cross-center sales-box box-grow-0">
  105. <view class="sales">{{item.sales}}</view>
  106. </view>
  107. <view class="dir-left-nowrap cross-center sales-box box-grow-0">
  108. <view class="sales">库存:{{item.goods_stock}}{{item.unit}}</view>
  109. </view>
  110. </template>
  111. </view>
  112. </view>
  113. </view>
  114. </view>
  115. <u-attr v-model="attrGoods.attrShow" :checked="attrGoods.select" :goods="attrGoods.goods"
  116. :theme-object="themeObject" @check="checkClick"></u-attr>
  117. </view>
  118. </template>
  119. <script>
  120. import {
  121. mapState
  122. } from "vuex";
  123. import appAttr from '../../../components/page-component/app-attr/app-attr.vue';
  124. import uAttr from '../../../components/page-component/goods/u-attr.vue';
  125. export default {
  126. name: 'product-list',
  127. props: {
  128. goods_list: Array,
  129. theme: String,
  130. is_name: {
  131. type: Boolean,
  132. default: true,
  133. },
  134. is_cart: {
  135. type: Boolean,
  136. default: true,
  137. },
  138. sign: String,
  139. listStyle: {
  140. type: Boolean,
  141. default: false
  142. },
  143. isShowAttr: {
  144. type: Boolean,
  145. default: true
  146. },
  147. themeObject: {
  148. type: Object
  149. }
  150. },
  151. computed: {
  152. ...mapState({
  153. appImg: state => state.mallConfig.__wxapp_img.mall,
  154. isShowCart: state => state.mallConfig.mall.setting.is_show_cart,
  155. isShowGoodsName: state => state.mallConfig.mall.setting.is_show_goods_name,
  156. isShowSalesNum: state => state.mallConfig.mall.setting.is_show_sales_num,
  157. appSetting: state => state.mallConfig.mall.setting,
  158. isListUnderlinePrice: state => state.mallConfig.mall.setting.is_list_underline_price
  159. })
  160. },
  161. methods: {
  162. routeGo(data) {
  163. console.log(180)
  164. console.log(data)
  165. this.$emit('routeGo', data);
  166. },
  167. specification(goods) {
  168. this.attrGoods.select = null;
  169. if (this.isShowAttr) {
  170. this.attrGoods.goods = goods;
  171. this.attrGoods.attrShow = true;
  172. } else {
  173. uni.showLoading({
  174. text: '',
  175. mask: true
  176. });
  177. this.$request({
  178. url: this.$api.goods.attr,
  179. data: {
  180. id: goods.id,
  181. mch_id: goods.mch_id
  182. }
  183. }).then(e => {
  184. uni.hideLoading();
  185. if (e.code === 0) {
  186. this.attrGoods.goods = Object.assign(goods, e.data);
  187. this.attrGoods.attrShow = true;
  188. } else {
  189. uni.showToast({
  190. title: e.msg,
  191. icon: 'none'
  192. })
  193. }
  194. })
  195. }
  196. },
  197. checkClick(select) {
  198. console.log(this.attrGoods,">>>>>>>>>>>>>>>>>>>>")
  199. this.attrGoods.select = select;
  200. }
  201. },
  202. data() {
  203. return {
  204. attrGoods: {
  205. goods: null,
  206. attrShow: 0,
  207. select: null
  208. }
  209. }
  210. },
  211. components: {
  212. 'app-attr': appAttr,
  213. uAttr
  214. }
  215. }
  216. </script>
  217. <style scoped lang="scss">
  218. .product-list {
  219. position: relative;
  220. .u-goods {
  221. margin-top: #{15upx};
  222. background-color: #ffffff;
  223. width: #{344upx};
  224. border-radius: #{15upx};
  225. }
  226. }
  227. .list-padding {
  228. padding: #{0 20upx};
  229. }
  230. /*图片名字*/
  231. .image-name {
  232. width: 100%;
  233. border-top-left-radius: #{15upx};
  234. border-top-right-radius: #{15upx};
  235. position: relative;
  236. .out-dialog {
  237. border-top-left-radius: #{15upx};
  238. border-top-right-radius: #{15upx};
  239. width: #{344upx};
  240. height: #{344upx};
  241. position: absolute;
  242. top: 0;
  243. z-index: 10;
  244. left: 0;
  245. background-color: rgba(0, 0, 0, .5);
  246. image {
  247. width: #{344upx};
  248. height: #{344upx};
  249. }
  250. }
  251. .image {
  252. width: 100%;
  253. height: #{344upx};
  254. border-top-left-radius: #{15upx};
  255. border-top-right-radius: #{15upx};
  256. }
  257. .name {
  258. font-size: #{26upx};
  259. color: #353535;
  260. padding: #{0 24upx};
  261. margin-top: #{20upx};
  262. line-height: #{36upx};
  263. }
  264. }
  265. .content-name {
  266. height: calc(100% - #{426upx});
  267. }
  268. .content-no {
  269. height: calc(100% - #{384upx});
  270. }
  271. /*复杂内容*/
  272. .content {
  273. padding: #{0 24upx};
  274. .price-total {
  275. margin: #{16upx 0 30upx 0};
  276. &.exchange {
  277. margin-top: #{6upx};
  278. margin-bottom: #{16upx};
  279. }
  280. .sales {
  281. font-size: #{20rpx};
  282. margin-left:#{12rpx};
  283. }
  284. .sales-box {
  285. color: #999999;
  286. .sales {
  287. margin-left: 0;
  288. }
  289. }
  290. .price {
  291. font-size: #{28rpx};
  292. }
  293. }
  294. /*会员价组件*/
  295. .member-price {
  296. margin-top: #{12upx};
  297. }
  298. /*超级会员卡组件*/
  299. .app-sup-vip {
  300. margin-top: #{9upx};
  301. }
  302. }
  303. /*默认文字颜色*/
  304. .default-color {
  305. color: #ff4544;
  306. }
  307. .cart-box {
  308. width: #{92upx};
  309. height: #{92upx};
  310. position: absolute;
  311. padding: #{32upx};
  312. right: #{-24rpx};
  313. top: #{-60rpx};
  314. }
  315. .goods-cart {
  316. width: #{28rpx};
  317. height: #{28rpx};
  318. }
  319. .f-swipe-content {
  320. background-color: #ffffff;
  321. .f-item {
  322. padding: 24upx;
  323. border-bottom: 1upx solid #e2e2e2;
  324. position: relative;
  325. .f-img {
  326. width: 200upx;
  327. height: 200upx;
  328. border-radius: 23upx;
  329. margin-right: 24upx;
  330. }
  331. .f-out-dialog {
  332. width: 200upx;
  333. height: 200upx;
  334. border-radius: 23upx;
  335. margin-right: 24upx;
  336. position: absolute;
  337. z-index: 10;
  338. background-color: rgba(0, 0, 0, .5);
  339. image {
  340. width: #{200upx};
  341. height: #{200upx};
  342. }
  343. }
  344. .f-content {
  345. width: 478upx;
  346. }
  347. .f-title {
  348. font-size: 26upx;
  349. line-height: 36upx;
  350. color: #353535;
  351. }
  352. .f-invalid {
  353. width: 128upx;
  354. height: 42upx;
  355. line-height: 42upx;
  356. background-color: #f7f7f7;
  357. padding: 0 27upx 0 18upx;
  358. >text {
  359. font-size: 23upx;
  360. color: #999999;
  361. }
  362. >image {
  363. width: 24upx;
  364. height: 24upx;
  365. }
  366. }
  367. .f-low-stock {
  368. width: 148upx;
  369. height: 42upx;
  370. line-height: 42upx;
  371. background-color: #ffecec;
  372. padding: 0 27upx 0 18upx;
  373. >text {
  374. font-size: 23upx;
  375. color: #ff4544;
  376. }
  377. >image {
  378. width: 24upx;
  379. height: 24upx;
  380. }
  381. }
  382. .f-low-price {
  383. height: 42upx;
  384. display: inline-block;
  385. background-color: #ffecec;
  386. padding: 0 27upx 0 18upx;
  387. position: relative;
  388. >text {
  389. font-size: 23upx;
  390. color: #ff4544;
  391. }
  392. >image {
  393. width: 24upx;
  394. margin-right: 14upx;
  395. height: 24upx;
  396. }
  397. }
  398. .f-cat-icon {
  399. width: 56upx;
  400. height: 56upx;
  401. }
  402. .f-price {
  403. font-size: 24upx;
  404. margin-top: 12upx;
  405. }
  406. .f-scale {
  407. font-size: 21upx;
  408. color: #b0b0b0;
  409. }
  410. }
  411. }
  412. .origin-price {
  413. font-size: 21upx;
  414. color: #999999;
  415. text-decoration: line-through;
  416. }
  417. </style>